C++20中无默认构造函数类模板代码编译分歧:哪个编译器正确?
该C++20程序是否合规?编译器行为分析
测试代码
struct not_default_constructible { not_default_constructible() = delete; }; template<typename T> struct C { static constexpr T t{}; }; template<class T> struct myClass { C<T> new_t() { return {}; } }; int main() { myClass<not_default_constructible> d; d.new_t(); }
编译情况
- GCC、Clang在C17和C20模式下均可正常编译
- MSVC在C++20模式下编译失败,报错信息如下:
<source>(6): error C2131: expression did not evaluate to a constant <source>(6): note: failure was caused by call of undefined function or one not declared 'constexpr' <source>(6): note: see usage of 'not_default_constructible::not_default_constructible' <source>(15): note: see reference to class template instantiation 'C<T>' being compiled with [ T=not_default_constructible ]
标准合规性分析
在C++20标准中,static constexpr成员的初始化规则有明确规定:当constexpr静态数据成员的初始化表达式是聚合初始化(此处的T{}属于空聚合初始化),且目标类型T是无成员的聚合类型时,该初始化操作不需要调用T的默认构造函数——因为聚合初始化是直接完成对象初始化(无成员时仅完成对象的内存构造),不会触发默认构造函数的调用流程。
not_default_constructible属于无成员的聚合类型,即使它的默认构造函数被删除,空聚合初始化T{}依然是合法的。MSVC错误地将该初始化判定为需要调用被删除的默认构造函数,这不符合C++20标准的要求。
结论:GCC和Clang的行为符合C++20标准,MSVC的行为不符合标准。
内容的提问来源于stack exchange,提问作者user20562802
相关产品推荐
相关产品推荐

