C++类内定义私有非static constexpr编译期常量报错怎么解决
错误原因说明
非静态类成员属于类的每个实例所有,而constexpr要求值必须在编译期完全确定,属于类本身的全局固定属性,因此不能直接用于非静态成员变量声明,这就是你收到编译错误的根本原因。
不同C++标准下的正确实现
C++17及以上版本
C++17开始,static constexpr成员变量默认就是隐式inline的,不需要额外在类外定义,直接按下面的写法就可以满足你的要求:
namespace ns { class bla { private: struct internalStruct { // ... }; // 私有+static constexpr,不会暴露给外部,C++17起默认inline无需额外定义 static constexpr size_t compileConstant = sizeof(internalStruct) * 8; }; }
这种写法完全符合你的需求:
- 常量放在
private区域,外部文件不可访问 - 依赖的
internalStruct也是私有隐藏的,不会暴露 - 是编译期常量,不会产生运行期开销
C++11/14版本
如果需要兼容旧标准,static constexpr成员需要在类外额外提供一次定义(放在对应的cpp文件里即可,不会暴露给其他文件):
头文件写法:
// bla.h namespace ns { class bla { private: struct internalStruct { // ... }; static constexpr size_t compileConstant = sizeof(internalStruct) * 8; // 类内声明初始化 }; }
cpp文件写法:
// bla.cpp #include "bla.h" namespace ns { // C++11/14要求类外定义,因为此时static constexpr不是隐式inline的 constexpr size_t bla::compileConstant; }
补充说明
你提到的「constexpr整型成员应当是inline的」是C17之后的特性,旧标准下只要在cpp文件加一次外部定义就不会有ODR(单一定义规则)问题,也完全不会暴露你的内部实现细节。如果只在类的内部成员函数里用这个常量、不取它的地址的话,C11/14下甚至可以不用写类外的定义,编译器会直接把值展开。
内容的提问来源于stack exchange,提问作者vsuser
相关产品推荐
相关产品推荐

