why can enum class values of type int not be used as int

|▌冷眼眸甩不掉的悲伤 提交于 2021-02-05 11:25:28

问题


I wanted to change an old-style enum to enum class : int because of its own scope.

But the compiler complains about using the values in integer arithmetics. But why - since the enum is explicitly typed as int?

example:

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

produces

error C2678: binary '<<': no operator found which takes a left-hand operand of type 'MyClass::MsgType' (or there is no acceptable conversion)

This seems to be somewhat illogical to me.

Edit:
I am totally aware of the possillity to cast them. But if I would not want them to be convertible, why would i specify the type to be int. Especially if the syntax suggest some kind of "inherited from int"


回答1:


That's the feature. Scoped enumerations are not implicitly convertible to integers, so you can't use them in lieu of integers. They are strongly typed by design. If you want the implicit conversion, use unscoped enumerations.

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

Scoping and the specification of an underlying type are orthogonal.

Alternatively, if you only want some operations to be defined, while the enumerations remain strongly typed in general, you can overload the appropriate operators to accomplish that

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

But if I would not want them to be convertible, why would i specify the type to be int

To ensure a certain layout. To follow a specific ABI. To allow forward declaring the type.




回答2:


Type safety is the main reason to use the new scoped enums (perhaps the name is a bit misleading). If you merely want an enum that is scoped and can implicitly convert to integers you can wrap it in a struct or namespace:

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

Downside is that the type is now MsgSender::Values, but the values are MsgSender::A etc.

For a scoped enum you have to static_cast to the std::underlying_type<MsgSener> to get the integer.




回答3:


You can convert them explicitly via a static_cast.

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



回答4:


You can't use c++11 scoped enums directly as int, but can cast it into int.

Mainly because of type safety reason, unscoped enum can leak names inside the enums, and the scoped enum doest not have a risk of leak name, the names can only be visbile inside.

There are 2 kinds of enums in c++ so far.

C++98-style unscoped enums: enum Color {Red, Green, Yellow};, which can implicit convert to int.

C++11 scoped enums: enum class{Red, Green, Yellow};, which cann't be implicit convert to int, can only use a cast to convert to other type, like static_cast<int>(my_color).

Scoped enums have 3 advantage comparing to unscoped enums:

  1. Reduce namespace pollution;
  2. Strong type safety;
  3. Scoped enums may be forward-declared, unscoped enums needs additonal work to be forward-declared;

Meanwhile, Unscoped enums are more flexible than scoped enums.

Both scoped enums and unscoped enums support specification of the underlying type, the default underlying type for scoped enums is int. Unscoped enums have no default underlying type, which is compiler dependent, can be a char or int, according to the range of values.

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

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

Unscoped enums may be forward-declared only if ther declaration sepcifies an underlying type.

In Practice, prefer scoped enums to unscoped enums.

See the book "Effective Modern C++" by Scott Meyers, item 10: prefer scoped enums to unscoped enums.



来源:https://stackoverflow.com/questions/62653751/why-can-enum-class-values-of-type-int-not-be-used-as-int

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!