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

CRTP非可拷贝层级中使用大括号初始化对象的编译错误

问题原因解析

这个编译错误的核心是C++17对聚合类型和初始化规则的调整,结合友元权限的作用范围导致的,具体拆解如下:

1. C++版本间的聚合定义差异

  • C++11/14:聚合类型不能包含基类,因此MyCRTP不属于聚合。此时MyCRTP a{};会触发值初始化,编译器会自动生成MyCRTP的隐式默认构造函数。该构造函数作为MyCRTP的成员函数,由于MyCRTP被声明为Base<MyCRTP>的友元,能合法调用Base的私有构造函数,因此编译通过。
  • C++17:聚合类型的定义被放宽,允许包含public基类的类成为聚合。MyCRTP满足聚合的所有条件(无用户声明的构造函数、无私有/保护非静态数据成员、无虚函数/虚基类),因此MyCRTP a{};会触发聚合初始化。

2. 聚合初始化的权限限制

聚合初始化是直接在当前作用域(比如main函数)初始化对象的每个基类子对象和成员,而非通过派生类的构造函数。此时初始化Base<MyCRTP>子对象的代码属于外部作用域,不具备Base的友元权限,因此无法调用Base的私有默认构造函数,最终触发编译错误。

3. 其他场景正常编译的原因

  • MyCRTP a;声明对象:这是默认初始化,编译器会调用MyCRTP的隐式默认构造函数。该构造函数是MyCRTP的成员,拥有Base的友元权限,能合法访问Base的私有构造函数。
  • 移除NonCopyable继承:此时Base不再有私有基类,编译器对MyCRTP的聚合判断或初始化路径发生变化,会 fallback 到调用隐式默认构造函数,友元权限生效。
  • 改为公有继承NonCopyable:当Base公有继承NonCopyable时,Base的基类访问权限变为public,此时MyCRTP的聚合初始化过程中,编译器会认可MyCRTP作为Base友元的权限,或者调整初始化路径为调用隐式构造函数,从而避免权限错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 03:20:10