C++17中static const与constexpr模板成员变量输出异常问题咨询
这确实是C++17的有意变更,根源在于内联变量的新规则
你的代码在不同C标准下的输出差异,是C17对constexpr静态成员变量处理逻辑调整导致的,属于有意的标准变更:
在C++11/14中,类内的
static const int TEN;只是一个声明,并没有提供定义和初始值。类外的constexpr int Test<T>::TEN =10;才是这个静态成员的唯一定义,编译器会直接使用这个定义里的初始值10,所以程序输出10。但到了C++17,标准引入了内联变量机制,并且规定
constexpr静态成员变量默认就是内联的。这时候你的代码就出现了冲突:类内的static const int TEN;是一个非内联、非constexpr的声明,而类外的constexpr定义是一个内联变量。编译器会将这两者视为两个独立的实体:类内的const int是未初始化的静态变量(默认值为0),类外的constexpr定义虽然存在,但因为内联变量的规则,没有被正确关联到类内的声明。最终程序引用的是那个未初始化的const int,所以输出0。
修复方案
有两种简单的方式可以解决这个问题:
- 直接在类内用
constexpr声明并初始化(推荐,符合C++17及以上的最佳实践):
#include <iostream> template<typename T> struct Test { static constexpr int TEN = 10; }; int main(int argc, const char * argv[]) { std::cout << Test<int>::TEN << std::endl; return 0; }
- 保持类内
const声明,类外定义去掉constexpr(兼容旧标准的写法):
#include <iostream> template<typename T> struct Test { static const int TEN; }; template<typename T> const int Test<T>::TEN = 10; int main(int argc, const char * argv[]) { std::cout << Test<int>::TEN << std::endl; return 0; }
内容的提问来源于stack exchange,提问作者jtlim
相关产品推荐
相关产品推荐

