为什么不能将int类型的枚举类值用作int

时间:2020-06-30 08:54:44

标签: c++ enum-class

由于其自身的范围,我想将旧式enum更改为enum class : int

但是编译器抱怨在整数算术中使用这些值。 但是为什么-由于枚举被显式键入为int?

示例:

  enum class MsgType : int {
    Output = 1,
    Input  = 2,
    Debug  = 3
  };
  enum class MsgSender : int {
    A = 1,
    B = 2,
    C = 3
  };


  // later in code
  int id = (MsgType::Input << 16) + (MsgSender::A);

产生

错误C2678:二进制'<<':未找到采用'MyClass :: MsgType'类型的左操作数(或没有可接受的转换)的运算符

这对我来说似乎有点不合逻辑。

编辑:
我完全意识到抛弃他们的可能性。但是,如果我不希望它们可转换,为什么要将类型指定为int。特别是如果语法建议使用某种“从int继承的”

4 个答案:

答案 0 :(得分:6)

这就是功能。作用域枚举不能隐式转换为整数,因此您不能使用它们代替整数。它们是按设计强烈键入的。如果想要隐式转换,请使用无作用域枚举。

enum MsgType : int {
  Output = 1,
  Input  = 2,
  Debug  = 3
};
enum MsgSender : int {
  A = 1,
  B = 2,
  C = 3
};

作用域和基础类型的规范是正交的。

或者,如果只希望定义一些操作,而枚举通常保持强类型,则可以重载适当的运算符以完成操作

int operator<<(MsgType, int); // etc

但是,如果我不希望它们可转换,为什么要指定类型为int

确保一定的布局。遵循特定的ABI。允许向前声明类型。

答案 1 :(得分:2)

类型安全性是使用新的作用域枚举的主要原因(也许名称有点误导)。如果只需要一个有范围的枚举并且可以隐式转换为整数,则可以将其包装在struct或命名空间中:

struct MsgSender {
   enum Values {
      A = 1,
      B = 2,
      C = 3
   };
};

缺点是类型现在为MsgSender::Values,但值是MsgSender::A等。

对于有作用域的枚举,您必须static_caststd::underlying_type<MsgSener>才能获得整数。

答案 2 :(得分:2)

您可以通过static_cast显式转换它们。

  int id = (static_cast<uint32_t>(MsgType::Input) << 16) + (static_cast<uint32_t>(MsgSender::A)) ;

答案 3 :(得分:1)

您不能将c ++ 11范围内的枚举直接用作int,而是可以将其强制转换为int

主要是出于类型安全的原因,无范围的枚举可以泄漏枚举内部的名称,而作用域限定的枚举没有泄漏名称的风险,名称只能在内部隐匿。

到目前为止,c ++中有两种枚举。

C ++ 98风格的无作用域枚举: enum Color {Red, Green, Yellow};, 可以隐式转换为int。

C ++ 11范围内的枚举:enum class{Red, Green, Yellow};, 不能隐式转换为int,只能使用强制转换将其转换为其他类型,例如static_cast<int>(my_color)

与未限制范围的枚举相比,范围枚举的枚举具有3个优势:

  1. 减少命名空间污染;
  2. 安全性强;
  3. 范围内的枚举可能是前向声明的,无作用域的枚举需要进行额外的工作;

与此同时,无作用域的枚举比作用域枚举更灵活。

作用域枚举和未作用域枚举都支持基础类型的规范,作用域枚举的默认基础类型为int。未作用域的枚举没有默认的基础类型,它取决于编译器,根据值的范围可以是charint

enum class Color: std::uint8_t{Red, Green, Yellow}; // Definition

enum Color: std::uint8_t{Red, Green, Yellow}; // Forward Declaration

仅当ther声明分隔基础类型时,才可以向前声明未作用域的枚举。

在实践中,有范围的枚举比无范围的枚举更重要。

请参阅Scott Meyers撰写的“ Effective Modern C ++”一书,第10项:与无范围的枚举相比,更喜欢范围枚举。