在static_assert中比较静态类字段的指针是否符合C++规范?
结论
你所写的代码符合C17及更高版本的C标准要求,GCC抛出non-constant condition for static assertion错误属于编译器本身的实现缺陷,Clang的编译行为是正确的。
原理说明
- 模板实例化时,
C<0>和C<1>属于完全独立的两个类型,二者的静态成员x是不同的静态存储期对象,地址必然不同,这一结果在编译期完全可以确定。 - C++17标准明确规定:两个具有静态存储期的不同完整对象的地址不等判定结果属于合法的常量表达式,可以作为
static_assert的判断条件。 - C++11/14标准中对这类地址比较是否属于常量表达式的规定存在模糊,因此编译器实现存在差异。
GCC报错原因
该问题是GCC长期存在的已知实现缺陷,GCC目前还未支持将不同静态/全局对象的地址不等比较识别为常量表达式,即使该结果在编译期是确定的。
兼容GCC的替代方案
如果你需要兼容GCC,可以换用不需要比较地址的方式验证模板实例的独立性,写法如下:
#include <type_traits> template<int N> struct C { static int x; }; template<int N> int C<N>::x = 0; int main() { static_assert(!std::is_same_v<C<0>, C<1>>); }
该写法在所有支持C++17的编译器上都可以正常编译通过。
内容的提问来源于stack exchange,提问作者Fedor。
相关产品推荐
相关产品推荐

