C++20中constexpr数组无法用constexpr函数初始化问题求助
C++20 constexpr数组初始化问题及解决方法
问题现象
在C++20环境下使用clangd作为LSP开发时,遇到以下问题:
- 无法通过constexpr函数初始化constexpr数组,直接赋值常量列表则正常工作
- clangd返回错误:
Constexpr variable must be initialized by a constant expression - 编译时提示:
constexpr T IpRange::getMaskValues() [with T = std::array<unsigned int, 33>]’ used before its definition
原始代码(IpRange.h)
class IpRange { inline static constexpr uint32_t getMaskValue(const ushort shortForm) { return 2^(32 - shortForm) - 1; } template <typename T> inline static constexpr T getMaskValues() { auto masks = T(); for (ushort i = 0; i < 33 ; i++) { masks[i] = getMaskValue(i); } return masks; } static constexpr std::array<uint32_t, 33> maskValues { getMaskValues<std::array<uint32_t, 33>>() }; // 触发错误:Constexpr variable 'maskValues' must be initialized by a constant expression // 编译错误:constexpr T IpRange::getMaskValues() [with T = std::array<unsigned int, 33>]’ used before its definition // static constexpr std::array<uint32_t, 33> maskValues { 1, 2, 3 }; // 直接赋值常量列表可正常工作 };
解决方法:迁移至独立类
将掩码相关逻辑抽离到独立类中,通过constexpr构造函数完成初始化:
#define MASK_VAL_NUM 33 class MaskValues { using MaskValA = std::array<uint32_t, MASK_VAL_NUM>; inline static constexpr uint32_t getMaskValue(const ushort shortForm) { return 2^(32 - shortForm) - 1; } inline static constexpr MaskValA getMaskValues() { auto masks = MaskValA(); for (ushort i = 0; i < MASK_VAL_NUM ; i++) { masks[i] = getMaskValue(i); } return masks; } const std::array<uint32_t, MASK_VAL_NUM> maskValues; public: constexpr MaskValues(): maskValues{getMaskValues()} { } const uint32_t& operator[](std::size_t idx) const { return this->maskValues[idx]; } }; class IpRange { static constexpr MaskValues maskValues {}; };
问题原因
类内部的静态constexpr成员初始化受声明顺序限制:maskValues的初始化语句位于getMaskValues模板函数的声明之后,但在C++类作用域中,静态成员初始化时,模板函数的定义需要在初始化点之前完全可见,否则编译器会判定函数未定义就被使用。
而将逻辑迁移到独立类后,通过constexpr构造函数触发初始化,此时getMaskValues函数的定义已经在类内部完成,构造函数初始化时可以正确解析并调用该constexpr函数,满足常量表达式的要求。
注意:代码中
2^(32 - shortForm)是位异或运算,如果意图是计算2的幂,应改为(1U << (32 - shortForm)) - 1,避免逻辑错误。
内容的提问来源于stack exchange,提问作者Matexer
相关产品推荐
相关产品推荐

