通过显式转换函数初始化枚举类类型的静态constexpr类成员

时间:2014-01-07 13:16:59

标签: c++ c++11 constexpr enum-class

我在g ++ 4.8.1和clang ++ 3.4的行为之间存在差异。

我有一个文字类型的A,其explicit constexpr转化函数可以输入enum class E

Gcc允许我在某些情况下使用转换函数从类型constexpr的常量表达式初始化E类型的A变量,但不能在变量是静态类成员时(e2以下)

Clang拒绝所有上下文中的初始化(e1e2e3)。

根据[over.match.conv]p1使用显式转换功能就可以了

enum class E { e };
struct A { explicit constexpr operator const E() const noexcept { return E::e; } };

constexpr E e1{A{}};                      // Gcc: OK, Clang: Error
struct B { static constexpr E e2{A{}}; }; // Gcc: Error, Clang: Error
void f() { static constexpr E e3{A{}}; }  // Gcc: OK, Clang: Error

我在转换为另一个文字类类型而不是枚举类型时看到了类似的模式 - g ++拒绝s1的初始化,clang拒绝s1s2和{的初始化{1}}。根据{{​​1}},我认为这些也应该是有效的。

s3

哪个编译器(如果有的话)是对的?


编辑:有几件有趣的事情需要注意:

  1. clang-3.4和clang-svn的结果不同,请参阅下面的评论。
  2. 当使用parens进行初始化而不是大括号时,[over.match.copy]p1 / struct S { constexpr S(){} constexpr S(const S&){}}; struct A { explicit constexpr operator S() const noexcept { return S(); } }; constexpr S s1{A{}}; // Gcc: OK, Clang: Error struct B { static constexpr S s2{A{}}; }; // Gcc: Error, Clang: Error void f() { static constexpr S s3{A{}}; } // Gcc: OK, Clang: Error e2 / s2 / e1 / {之间仍存在差异{1}},请参阅http://coliru.stacked-crooked.com/a/daca396a63425c6b。 gcc和clang-svn同意,但我不相信拒绝e2和s2是正确的。

1 个答案:

答案 0 :(得分:3)

奇怪的是,Clang在拒绝这些方面似乎是正确的。

原因是C ++ 11标准中存在一个错误,其中{}不适用于复制构造函数。这就是()构造函数工作的原因,但{}构造函数不起作用。

Bjarne Stroustrup在errata for his book下说它已在C ++ 14中修复