下面的代码compiles cleanly与GCC 5.2.1
enum class some_enum
{
first = static_cast<some_enum>(1),
};
但在clang 3.6.2中的fails:
$ clang++ -std=c++11 enum.cpp -c
enum.cpp:15:13: error: value of type 'some_enum' is not implicitly convertible to 'int'
first = static_cast<some_enum>(1),
^~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
根据我对标准的阅读(§7.2,第5段),在这种情况下,枚举器初始化表达式必须与枚举的 * 底层 * 类型具有相同的类型。它恰好是int
,而不是some_enum
。
所以我认为clang拒绝这一点是正确的,这是GCC中的一个bug。在我将此作为一个bug报告给GCC之前,有谁能对标准有更好的理解吗?
编辑:解释我关于标准的推理
以下是我对7.2第5段的理解:
Each enumeration defines a type that is different from all other
types. Each enumeration also has an underlying type. The underlying
type can be explicitly specified using enum-base; if not explicitly
specified, the underlying type of a scoped enumeration type is int. In
these cases, the underlying type is said to be fixed.
因此,由于这是一个没有显式enum-base的作用域枚举,因此其底层类型 fixed 为int
。
Following the closing brace of an enum-specifier, each enumerator
has the type of its enumeration.
换句话说,在enum
主体之外,单个枚举器(即枚举中的命名条目)与整个enum
具有相同的类型。
If the underlying type is fixed, the type of each enumerator prior to
the closing brace is the underlying type...
由于我们处理的是一个有作用域的枚举,它总是有固定的底层类型,所以枚举体中的每个枚举条目的类型都与枚举的底层类型相同。在本例中,在主体中,枚举数的类型为int
。
...and the constant-expression in the enumerator-definition shall
be a converted constant expression of the underlying type (5.19);
if the initializing value of an enumerator cannot be represented
by the underlying type, the program is ill-formed.
在示例中,初始化器的类型为some_enum
,作为C++11范围内的枚举,如果没有显式转换,则无法将其转换为基础类型的常量表达式。所以这个程序是病态的。
1条答案
按热度按时间7cwmlq891#
这似乎只是GCC版本中的一个bug。它似乎在GCC 6中得到了修复。我同意你的推理如果需要整型的转换常量表达式,则不能使用范围枚举类型的值。
CWG 977澄清了枚举何时是完整的(特别是,具有固定底层类型的枚举在其 enum-base 之后,在看到任何枚举器之前就变得完整了),这已经太晚了,不能包含在C11中。但是,即使我们假设GCC的特定版本将枚举视为不完整,它仍然是GCC版本中的一个错误。我在已发布的C11标准中没有看到任何东西可以证明将这种情况视为IFNDR。虽然我们经常会得到UB/IFNDR,当库中使用不完整的类型时,或者当不完整的类型后来变成完整的与模板交互时。