以下最小示例因未初始化数组数据成员而被 Clang 和 GCC 拒绝:
class vector3
{
public:
constexpr vector3() = default;
private:
float m_data[3];
};
constexpr auto vec = vector3{};
这会产生相当直接的错误:
<source>:4:15: error: explicitly defaulted function 'constexpr vector3::vector3()' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr':
4 | constexpr vector3() = default;
| ^~~~~~~
<source>:6:11: note: defaulted default constructor does not initialize 'float vector3::m_data [3]'
6 | float m_data[3];
| ^~~~~~
Live Example https://gcc.godbolt.org/z/Kvh8Wf3P3
上述代码的目标是确保vector3
可以通过值初始化在常量表达式中使用(例如vector3{}
),这会将子元素(m_data
).
该错误的发生是由于使用constexpr
关键字,修复方法只是删除该关键字并允许default
正确推断是否可以在常量表达式中使用:
class vector3
{
public:
vector3() = default;
private:
float m_data[3];
};
constexpr auto vec = vector3{}; // now works?
奇怪的是,这实际上现在有效-- 并且仍然能够产生一个常量表达式,m_data
被零初始化,如 GCC 的程序集中所示(Clang 中存在类似的情况,但使用 XOR 指令):
vec:
.zero 12
Live Example https://gcc.godbolt.org/z/PYod6Y6z1
我的问题是:怎么可能= default
产生一个(有效)constexpr
构造函数,而constexpr ... = default
由于无效而失败constexpr
?
此问题似乎影响 C++20 之前的 C++ 版本(C++11 到 C++17)。 C++20 中对此进行了更改吗?
Live Example https://gcc.godbolt.org/z/38rGedeeE