You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何此处默认构造函数非constexpr?Clang与GCC编译差异谁正确?

问题解答:GCC的行为符合C++标准

先贴出你提供的代码供参考:

#include <type_traits>
template<typename T>
struct MyType {
    constexpr MyType () = default;
    //constexpr MyType () {}
    constexpr bool is_int () const {
        return std::is_same_v<T, int>;
    }
};
constexpr auto foo () {
    MyType<int> retval;
    //MyType<int> retval {};
    return retval;
}
int main () {
    static_assert (foo ().is_int ());
}

核心结论

首先明确:GCC拒绝编译这段代码是符合C++标准的,Clang的接受属于非标准的宽松实现行为。

原因拆解

问题出在constexpr函数里的对象初始化方式,以及MyType默认构造函数的定义:

  1. 你用constexpr MyType() = default;声明了一个平凡(trivial)的constexpr构造函数——因为类没有非静态数据成员,这个构造函数实际上不会执行任何初始化操作,只是“空转”。
  2. 在constexpr函数中,变量的初始化必须是合法的常量表达式。标准要求,constexpr上下文中的对象必须有明确的、可被编译器求值的常量状态;而平凡constexpr构造函数的默认初始化(MyType<int> retval;),编译器无法确认这个对象的状态满足常量表达式的要求,因此GCC会拒绝编译。

为什么取消任意一行注释就能编译?

两种修改都补上了“常量表达式初始化”的合规性:

  • 改成用户提供的构造函数constexpr MyType() {}:
    此时构造函数不再是平凡的——哪怕函数体为空,它也是用户显式定义的constexpr构造函数。编译器会认定这个构造函数的调用是合法的常量表达式,满足constexpr上下文的要求。
  • 改成值初始化MyType<int> retval {};:
    值初始化的语法会强制触发构造函数调用,哪怕构造函数是平凡的,编译器也会将这个初始化过程视为符合constexpr要求的操作,从而通过编译。

内容的提问来源于stack exchange,提问作者levzettelin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:36:12