为了使代码更具可读性,我对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
....
答案 0 :(得分:3)
作用域枚举(enum class
)没有隐式转换为任何类型的整数。由于std::get
期望使用整数类型的模板参数,因此必须进行这种转换。
但是它不能,因此没有重载与提供的模板参数匹配。
您可以使用C ++ 11之前的“作用域枚举” hack:
struct tpl {
enum : int {
arg1 = 0, arg2 = 1, arg3 = 2
};
};
这使标识符成为作用域,但保留隐式转换。之所以引入C ++ 11范围的枚举,是因为通常隐式转换不是所需的功能,但是在这种情况下,我敢说是这样。
答案 1 :(得分:2)
问题在于,作用域枚举不会隐式转换为其基础类型。您可以通过
手动进行操作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
。
答案 2 :(得分:1)
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);