通过显式转换函数初始化枚举类类型的静态constexpr类成员
Initialization of a static constexpr class member of enum-class type by explicit conversion function
我在g++4.8.1和clang++3.4的行为之间存在差异。
我有一个文本类型的类A
,它有一个explicit
constexpr
到类型enum class E
的转换函数。
Gcc允许我在某些情况下使用转换函数从A
类型的常量表达式初始化E
类型的constexpr
变量,但当变量是静态类成员(下面的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
和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
哪一个编译器是正确的?
编辑:需要注意的几件有趣的事情:
- clang-3.4和clang-svn的结果不同,请参阅下面的评论
- 当使用parens而不是大括号进行初始化时,
e2
/s2
和e1
/e3
/s1
/s3
之间仍然存在差异,请参见http://coliru.stacked-crooked.com/a/daca396a63425c6b.gcc和clang-svn同意,但我不相信拒绝e2和s2是正确的
原因是C++11标准中存在一个错误,其中{}
不适用于复制构造函数。这就是为什么()
构造函数有效,而{}
构造函数无效。
Bjarne Stroustrup在他的书的勘误表下说,它是在C++14 中修复的
相关文章:
- 静态自动 constexpr t = { "red" , "black" , "green" } 是什么类型;派生到?
- 使用constexpr + auto作为返回和参数类型的奇怪类型推导
- 从非类型模板参数声明 constexpr 数组的可移植方法
- 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数
- 如何将用户定义的文字放在C++相同类型的 constexpr 类中?
- Boost.Hana:在 constexpr 上下文中将值元组转换为相应类型的元组
- 是否可以使用"if constexpr"来声明具有不同类型和init-expr的变量
- 在通用 lambda 中使用 constexpr-if 来确定参数的类型
- 在 Mac OS x 中制造期间出现错误未知类型名称"constexpr"
- C++ constexpr 列表及其类型的大小
- 有没有办法根据运行时值的类型返回 constexpr 对象
- constexpr检查一种类型
- MSVC 错误,将 constexpr 数组作为模板非类型参数
- constexpr如果使用非模板类型
- 我可以将C 17 Capture lambda ConstexPR转换操作符的结果用作函数指针模板非类型参数吗?
- 将 constexpr 数组扩展为一组非类型模板参数
- 为什么我不能使用 constexpr 全局变量来初始化 constexpr 引用类型
- 尝试传递 constexpr lambda 并使用它来显式指定返回类型
- 类类型的静态constexpr字段在g++中给出链接时间错误
- clang vs gcc CRTP:constexpr 变量不能有非文字类型