gcc C++11中允许的枚举器初始化器类型是什么?

wpx232ag  于 2023-05-07  发布在  其他
关注(0)|答案(1)|浏览(140)

下面的代码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的作用域枚举,因此其底层类型 fixedint

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范围内的枚举,如果没有显式转换,则无法将其转换为基础类型的常量表达式。所以这个程序是病态的。

7cwmlq89

7cwmlq891#

这似乎只是GCC版本中的一个bug。它似乎在GCC 6中得到了修复。我同意你的推理如果需要整型的转换常量表达式,则不能使用范围枚举类型的值。
CWG 977澄清了枚举何时是完整的(特别是,具有固定底层类型的枚举在其 enum-base 之后,在看到任何枚举器之前就变得完整了),这已经太晚了,不能包含在C11中。但是,即使我们假设GCC的特定版本将枚举视为不完整,它仍然是GCC版本中的一个错误。我在已发布的C11标准中没有看到任何东西可以证明将这种情况视为IFNDR。虽然我们经常会得到UB/IFNDR,当库中使用不完整的类型时,或者当不完整的类型后来变成完整的与模板交互时。

相关问题