使用int初始化枚举类

Bar*_*kPL 7 c++ enums initialization c++17

编程时我发现了一些有趣的东西:

enum class Foo {
  FOO_THING,
  FOO_TOO
};

int main() {
  Foo foo{1};    // It is OK
  Foo foo2(1);   // It is an invalid
}
Run Code Online (Sandbox Code Playgroud)

你能告诉我,为什么foo{1}编译器可以,为什么foo2(1)无效?

编译器GCC(g++ (Ubuntu 7.3.0-21ubuntu1~16.04) 7.3.0)说:

$ g++ -Wall -std=c++17 foo.cpp

  error: cannot convert ‘int’ to ‘Foo’ in initialization
  Foo foo2(1);
Run Code Online (Sandbox Code Playgroud)

我真的想知道潜在的机制.:)))

编辑:也许是一些编译器bug ...

acr*_*075 6

特定于C ++ 17的文档具有以下用于支撑式初始化程序的信息

否则,如果T是具有固定基础类型的作用域范围或不受作用域限制的枚举类型,并且braced-init-list仅具有一个初始化器,并且从初始化器到基础类型的转换是非变窄的,并且初始化是直接列表初始化,然后使用将初始化程序转换为其基础类型的结果来初始化枚举。

因此,foo似乎符合有效的C ++ 17,但未foo2进行初始化初始化无效。


Gab*_*ano 5

To understand the reasons why the two syntax are not both legit you must consider that scoped enums were introduced with standard c++11 to enforce static type checking and have scoped identifiers (i.e. no name pollution anymore).

Foo foo(1) is not working because implicit conversion from integer type to scoped enum is forbidden, otherwise you lose the benefit of scoped enums, and to avoid conflicts during overload resolution.

When using Foo foo{1} you are using list initialization that was introduced with c++11 too, but got an upgrade with c++17, that consist in implicit conversion from int value to enum as reported here, if a set of requirements are satisfied:

Both scoped enumeration types and unscoped enumeration types whose underlying type is fixed can be initialized from an integer without a cast, using list initialization, if all of the following is true:

  1. the initialization is direct-list-initialization

  2. the initializer list has only a single element

  3. the enumeration is either scoped or unscoped with underlying type fixed

  4. the conversion is non-narrowing.

这使得引入新的整数类型(例如 SafeInt)成为可能,这些新的整数类型与它们的底层整数类型享有相同的现有调用约定,甚至在按值惩罚传递/返回结构的 ABI 上也是如此。

这种语法是安全的,不会干扰遗留代码(在 c++11 之前编写),因为作用域枚举和列表初始化当时都不存在。此外,正如引用中所报道的,这使得可以使用新的整数类型(如 SafeInt 库的整数类型),而无需在符合现代 C++ 语法的代码中强制对枚举类型进行静态转换。