如何将结构体/类的静态成员字段设为constexpr?
将3D向量结构体的静态成员设为constexpr的正确方式
问题背景
我有一个表示3D向量的Vec结构体,想要把它的静态成员Zero设置为constexpr。
最初的代码如下,静态常量Zero在单独的.cpp文件中定义:
struct Vec { double X; double Y; double Z; static const Vec Zero; // 在单独的.cpp文件中定义 // ... 一些函数和运算符 };
我尝试在结构体内部直接定义static constexpr Vec Zero{ 0.0, 0.0, 0.0 },但编译报错*incomplete type is not allowed*。
随后我把定义移到结构体外部并放在头文件中,代码编译通过,但链接阶段出现*duplicate symbol Vec::Zero*错误(因为Vec所在的头文件被多个.cpp文件包含)。
请问将Vec::Zero设为constexpr的正确方式是什么?是否可行?
可行方案(C++17及以上)
正如@Artyer指出,在C++17中可以使用inline关键字解决这个问题,可行代码如下:
struct Vec { double X; double Y; double Z; static const Vec Zero; }; inline constexpr Vec Vec::Zero{ 0.0, 0.0, 0.0 }; // 该定义放在头文件中,而非.cpp文件
原理说明
- 结构体内部直接定义
constexpr静态成员时,此时Vec类型还未完成定义(结构体尚未闭合),因此编译器会抛出“不允许不完整类型”的错误。 - 若在头文件中直接定义非
inline的constexpr静态成员,每个包含该头文件的.cpp都会生成一份Vec::Zero的定义,链接时就会出现重复符号错误。 - C++17新增的
inline变量特性,允许在头文件中定义变量,保证整个程序中该变量仅存在一个实例,同时满足constexpr的编译期常量要求。
内容的提问来源于Stack Exchange,提问作者Eugene
相关产品推荐
相关产品推荐

