我在g ++ 4.8.1和clang ++ 3.4的行为之间存在差异。
我有一个文字类型的A
,其explicit
constexpr
转化函数可以输入enum class E
。
Gcc允许我在某些情况下使用转换函数从类型constexpr
的常量表达式初始化E
类型的A
变量,但不能在变量是静态类成员时(e2
以下)
Clang拒绝所有上下文中的初始化(e1
,e2
和e3
)。
根据[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拒绝s1
,s2
和{的初始化{1}}。根据{{1}},我认为这些也应该是有效的。
s3
哪个编译器(如果有的话)是对的?
编辑:有几件有趣的事情需要注意:
[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是正确的。答案 0 :(得分:3)
奇怪的是,Clang在拒绝这些方面似乎是正确的。
原因是C ++ 11标准中存在一个错误,其中{}
不适用于复制构造函数。这就是()
构造函数工作的原因,但{}
构造函数不起作用。
Bjarne Stroustrup在errata for his book下说它已在C ++ 14中修复