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

模板参数不完全类型何时完整?C++多编译器行为差异及程序预期

C++ 不完整类型与概念约束的编译器行为分歧问题

当检查a<b>默认构造函数的约束条件时,类型d——进而类型b——是否应被视为完整类型?GCC允许构造b类型的对象,但Clang和MSVC均拒绝该操作。
不仅构造b对象会出现此结果,即使只是为嵌套类型b::d创建别名(即using w = b::d;),也会出现同样的编译器行为差异。
奇怪的是,这种编译器行为差异仅在用户为a类型提供默认构造函数并以c<d>约束时才会出现。请问这段程序的预期执行结果是什么?

template<typename T>
concept c = requires { sizeof(T); };

template<typename B>
struct a {
    struct d : B {};
    a() requires c<d> = default;
};
struct b : a<b> {};
auto v = b{}; // clang 报错, gcc 通过, msvc 报错

Clang 错误信息

<source>:6:16: 错误:基类类型不完整
    6 |     struct d : B {};
      |                ^
<source>:2:24: 注意:此处请求实例化成员类 'a<b>::d'
    2 | concept c = requires { sizeof(T); };
      |                        ^
<source>:2:24: 注意:此处实例化需求
    2 | concept c = requires { sizeof(T); };
      |                        ^~~~~~~~~
<source>:2:13: 注意:在此处将模板参数代入约束表达式时
    2 | concept c = requires { sizeof(T); };
      |             ^~~~~~~~~~~~~~~~~~~~~~~
<source>:7:18: 注意:在此处检查概念 'c<a<b>::d>' 的满足性时
    7 |     a() requires c<d> = default;
      |                  ^~~~
<source>:7:18: 注意:在此处将模板参数代入约束表达式时
    7 |     a() requires c<d> = default;
      |                  ^~~~
<source>:7:5: 注意:在此处检查函数 'a' 的约束满足性时
    7 |     a() requires c<d> = default;
      |     ^
<source>:9:12: 注意:在此处请求实例化模板类 'a<b>' 时
    9 | struct b : a<b> {};
      |            ^
<source>:9:8: 注意:'b' 的定义直到闭合 '}' 才完成
    9 | struct b : a<b> {};
      |        ^
<source>:10:12: 错误:没有匹配的构造函数用于初始化 'a<b>'
   10 | auto v = b{};
      |            ^
<source>:7:5: 注意:候选构造函数不可行:约束未满足
    7 |     a() requires c<d> = default;
      |     ^
<source>:7:18: 注意:因为 'd' 不满足 'c'
    7 |     a() requires c<d> = default;
      |                  ^~~~
<source>:2:24: 注意:因为 'sizeof(T)' 无效
    2 | concept c = requires { sizeof(T); };
      |                        ^
<source>:5:8: 注意:候选构造函数(隐式复制构造函数)不可行:需要1个参数,但提供了0个
    5 | struct a {
      |        ^
<source>:5:8: 注意:候选构造函数(隐式移动构造函数)不可行:需要1个参数,但提供了0个
    5 | struct a {
      |        ^

MSVC 错误信息

<source>(6): 错误 C2504: “b”: 基类未定义
<source>(6): 注意:模板实例化上下文(最早的在前)是
<source>(7): 注意:在评估概念 'c<a<b>::d>' 时
<source>(6): 注意:在编译类 'a<b>::d' 时

预期执行结果

根据C++标准规则,这段程序应该编译失败,Clang和MSVC的行为符合标准,GCC的行为存在偏差。

具体原因:

  1. 定义struct b : a<b> {};时,实例化基类a<b>的阶段,b的定义尚未完成(要到闭合的}才会成为完整类型),此时b属于不完整类型。
  2. a<B>::d继承自B(即b),而C++要求继承操作的基类必须是完整类型。检查默认构造函数的约束c<d>时,需要验证sizeof(d)的有效性,这要求d是完整类型,但此时d的基类b仍不完整,导致d无法成为完整类型,sizeof(d)操作非法。
  3. 因此c<d>的约束无法满足,a<b>的默认构造函数不可用,而b的默认构造函数依赖于基类的默认构造函数,最终无法初始化b对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:58:12