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

时间:2019-01-30 15:00:09

标签: c++ c++17 stdtuple

为了使代码更具可读性,我对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 
....

3 个答案:

答案 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);