std::get<0>(...) 和枚举索引



为了使代码更具可读性,我用tuple做了以下操作:

std::tuple<uint32_t, uint32_t, uint32_t> key;
enum  tpl {
    arg1 = 0, arg2 = 1, arg3 = 2
};

现在我可以写:

 auto _arg1 = std::get<tpl::arg1>(key);

我现在遇到一个问题。如果我写:

auto arg1 = std::get<tpl::arg1>(key);

变量arg1已经是枚举。因此,我想切换到:

enum class tpl: int {
    arg1 = 0, arg2 = 1, arg3 = 2
};

但是这里有些不对劲。编译器说:

错误 C2672:"std::get":未找到匹配的重载函数

这个索引在std::get是什么类型,可以在枚举类的定义中命名吗?

我试过了

const constexpr
const int 
....

作用域枚举 ( enum class ) 没有隐式转换为任何类型的整数。由于std::get需要整型模板参数,因此必须进行此类转换。

但它不能,因此没有重载与提供的模板参数匹配。

您可以使用在 C++11 之前采用的"作用域枚举"黑客:

struct tpl {
  enum : int {
    arg1 = 0, arg2 = 1, arg3 = 2
  };
};

这使得标识符的作用域,但保留隐式转换。引入了 C++11 作用域枚举,因为通常隐式转换不是所需的功能,但在这种情况下,我敢说它是。

问题是作用域枚举不会隐式转换为其基础类型。您可以通过以下方式手动执行此操作

std::get<static_cast<std::underlying_type_t<tpl>>(tpl::arg1)>(key);

但是,由于您的尝试是提高可读性,因此这不是一个很好的解决方案。相反,请考虑此选项:

namespace tpl {
   enum { arg1 = 0, arg2 = 1, arg3 = 2 };
}
std::get<tpl::arg1>(key);

它不具有与强类型枚举相同的类型安全含义,但它允许你想到的语法调用。

作为旁注,一旦您担心使用std::tuple对象的可读性影响,您可能希望切换到一个简单的struct

std::get 的索引模板参数的类型为 std::size_t 。作用域枚举不能隐式转换为其基础类型。因此,如果您坚持使用一个,则必须投射它。

auto arg1 = std::get<static_cast<int>(tpl::arg1)>(key);

如果要避免在演员表中提及基础类型

auto arg1 = std::get<static_cast<std::underlying_type_t<tpl>>(tpl::arg1)>(key);

最新更新