含静态constexpr成员的结构体模板出现链接错误如何解决
错误产生原因
该链接错误是C++14及更早版本的ODR(单一定义规则)要求导致的,核心原因如下:
- GCC 10.2默认使用的C编译标准为C14,在C++17之前,类内完成初始化的
static constexpr成员变量,只要被取地址、被引用等ODR使用场景(你代码中取pattern_raw的地址传入Eigen::Map就属于ODR使用),必须额外提供类外的定义,否则链接阶段会找不到对应的符号。 - 你只给静态成员
pattern2提供了类外定义,没有给pattern_raw补充类外定义,因此链接器抛出undefined reference to visnav::Pattern24<float>::pattern_raw的报错。
修复方案
有两种可选修复方案:
- 方案一:升级C编译标准到C17及以上
该方案改动最小,C++17开始static constexpr类成员默认是隐式inline的,不需要额外提供类外定义。如果使用CMake构建项目,只需要在CMakeLists.txt中添加如下配置即可:set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) - 方案二:保持现有C标准,补充
pattern_raw的类外定义
如果你暂时不能升级C标准,只需要在头文件中pattern2的类外定义之前,补充pattern_raw的模板类外定义即可,完整修改后的代码如下:template <class Scalar> struct Pattern24 { // 00 01 // // 02 03 04 05 // // 06 07 08 09 10 11 // // 12 13 14 15 16 17 // // 18 19 20 21 // // 22 23 // // -----> x // | // | // y static constexpr Scalar pattern_raw[][2] = { {-1, 5}, {1, 5}, {-3, 3}, {-1, 3}, {1, 3}, {3, 3}, {-5, 1}, {-3, 1}, {-1, 1}, {1, 1}, {3, 1}, {5, 1}, {-5, -1}, {-3, -1}, {-1, -1}, {1, -1}, {3, -1}, {5, -1}, {-3, -3}, {-1, -3}, {1, -3}, {3, -3}, {-1, -5}, {1, -5} }; static constexpr int PATTERN_SIZE = sizeof(pattern_raw) / (2 * sizeof(Scalar)); typedef Eigen::Matrix<Scalar, 2, PATTERN_SIZE> Matrix2P; static const Matrix2P pattern2; }; // 新增:pattern_raw的类外定义 template <class Scalar> constexpr Scalar Pattern24<Scalar>::pattern_raw[][2]; template <class Scalar> const typename Pattern24<Scalar>::Matrix2P Pattern24<Scalar>::pattern2 = Eigen::Map<Pattern24<Scalar>::Matrix2P>((Scalar*) Pattern24<Scalar>::pattern_raw);
内容的提问来源于stack exchange,提问作者Yiğit Aras Tunalı
相关产品推荐
相关产品推荐

