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

为何我的类无法默认构造?附代码复现与异常现象

奇怪的编译差异?来拆解这个Clang 9的bug

先把你的代码贴出来方便大家看:

#include <type_traits>

template <typename T>
class A {
public:
    static_assert(std::is_default_constructible_v<T>);
};

struct B {
    struct C { int i = 0; };
    A<C> a_m; // 这里编译失败,静态断言触发
};

int main() {
    A<B::C> a; // 这里却能正常编译?
}

你遇到的现象完全合理,这其实是Clang 9.0.0的一个已知bug,和编译器处理嵌套类的类型完整性时机有关。

为什么会出现这种差异?

问题出在编译器对嵌套类的默认构造能力判断时机上:

  • 当编译器处理B内部的A<C> a_m时,虽然C的定义写在前面,但此时C对编译器来说还不是“完全完整”的类型——它没法正确识别到:因为默认成员初始化器int i=0的存在,C会被隐式生成默认构造函数,所以std::is_default_constructible_v<C>错误返回了false,触发了静态断言。
  • 而到了main函数里,B::C已经是完全定义的类型,编译器能正确判断它是默认可构造的,所以静态断言顺利通过。

当你去掉C的默认成员初始化器后,C变成了简单的聚合类,编译器在处理B内的a_m时,能直接识别它可以被默认初始化,所以静态断言不会触发。

怎么解决?

有两个简单的处理方式:

  • 升级Clang版本:这个bug在Clang 10及以后的版本已经被修复,升级后代码就能正常编译,不需要修改任何代码。
  • 给C显式添加默认构造函数:如果暂时没法升级编译器,给C手动声明默认构造函数,让编译器在处理B内的a_m时能明确知道它是默认可构造的:
struct B {
    struct C { 
        int i = 0;
        C() = default; // 显式声明默认构造
    };
    A<C> a_m; // 现在编译正常了
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:51:20