C++20嵌套类constexpr构造函数无法初始化静态成员问题
问题分析:constexpr静态成员初始化报错原因
示例代码
struct Foo { struct Bar { int data = 0; //constexpr Bar() = default; // Doesn't work either constexpr Bar() : data(0) {} }; static constexpr Bar bar = {}; // ERROR //static constexpr Bar bar = {0}; // Works if the ctor from Bar is removed };
问题描述
在Clang和GCC(启用std=c++20)环境下,编译器提示Bar的构造函数未定义,但将constexpr改为inline后即可正常运行,以下是原因解析:
原因解析
constexpr静态成员的ODR规则限制
C++标准中,constexpr静态数据成员允许类内初始化,但如果它被ODR使用(此处初始化时调用自定义构造函数的行为就属于ODR使用),需要确保构造函数有可链接的定义。由于Bar是Foo的嵌套类,其constexpr构造函数的定义仅存在于Foo类内部,编译器处理static constexpr Bar bar = {};时,无法确保构造函数的定义被正确实例化并暴露给链接器,因此报构造函数未定义的错误。inline静态成员的特性解决问题
换成inline static Bar bar = {};后,C++17及以后的标准规定,inline静态成员会自动在类内完成定义(无需类外额外声明),编译器会将成员的定义和构造函数的实例化绑定在一起,确保链接器能找到构造函数的定义,因此可以正常编译运行。聚合初始化的特殊情况
注释中移除Bar的构造函数后,static constexpr Bar bar = {0};能正常工作,是因为此时触发的是聚合初始化——直接初始化Bar的成员data,不需要调用任何自定义构造函数,自然不会涉及构造函数的定义问题。
内容的提问来源于stack exchange,提问作者Newline
相关产品推荐
相关产品推荐

