类模板内定义static constexpr成员:GCC与Clang编译冲突,孰对孰错?
哪款编译器的行为符合C++标准?
测试代码
template <typename T> struct A { static constexpr A a = A{}; }; template <typename T> struct B { T a; }; B<A<int>> b;
编译结果对比
- GCC 13 可正常编译上述代码
- Clang 16 编译报错,错误信息如下:
<source>:3:21: error: constexpr variable cannot have non-literal type 'const A<int>' static constexpr A a = A{}; ^ <source>:9:4: note: in instantiation of template class 'A<int>' requested here T a; ^ <source>:12:11: note: in instantiation of template class 'B<A<int>>' requested here B<A<int>> b; ^ <source>:3:21: note: incomplete type 'const A<int>' is not a literal type static constexpr A a = A{}; ^ <source>:2:8: note: definition of 'A<int>' is not complete until the closing '}' struct A { ^ 1 error generated. Compiler returned: 1
标准符合性分析
Clang的行为符合C++标准,GCC的处理属于非标准扩展。
原因在于:当实例化A<int>时,在类体内部声明static constexpr A a = A{}的时刻,A<int>的类定义尚未完成(还未到达类的闭合}),此时A<int>是不完全类型。根据C++标准,constexpr变量的类型必须是字面类型(literal type),而不完全类型不属于字面类型范畴,因此该声明违反了标准要求。
GCC在这里放宽了限制,允许使用不完全类型初始化constexpr静态成员,这是不符合C++标准的行为。
内容的提问来源于stack exchange,提问作者Nicolas
相关产品推荐
相关产品推荐

