[英]Explicit defaulted default constructor and aggregates
当我编译以下代码的#if 0
和#if 1
版本时,如何解释差异:
#include <cstdlib>
struct A
{
explicit A() = default; // explicitly defaulted or deleted constructors are allowed for aggregates (since C++11)
#if 1
private :
#endif
int i;
};
int
main()
{
A a = {};
return EXIT_SUCCESS;
}
#if 0
一切都很好,编译成功。 #if 1
编译失败,错误消息:
错误:选择的构造函数在复制初始化中是显式的
表达式A a = {};
什么区别A a = {};
取决于A
是否是万能?
TL; DR:Clang和GCC拒绝您的代码是错误的。 无论选择的默认构造函数是否explicit
CWG 1630的分辨率都使得默认初始化格式良好。
在i
private
代码的变体中, A
不是聚合,因为它们不能拥有私有成员。 但是,只要i
是public
, A
就是聚合1 ,并且由于执行了聚合初始化而没有调用构造函数(参见蓝框),所以你的构造函数是explicit
是无关紧要的。
但是,只要您引入私有成员,就需要根据红色框进行值初始化。 因此[dcl.init] /(8.2)适用:
[dcl.init] /(7.1)定义了这种情况的默认初始化:
并且§13.3.1.3给出
对于默认初始化,候选函数是正在初始化的对象的类的所有构造函数。
在任何时候都不考虑原始上下文 - 复制或直接初始化。 (§13.3.1.7也不适用。)事实上,这是有意的; 见CWG#1518 :
问题1630的解决方案解决了这个问题 : 默认初始化现在使用13.3.1.3 [over.match.ctor],现在允许显式构造函数进行默认初始化。
Clang和GCC(以及VC ++)尚未实现相应的DR,因此在拒绝C ++ 14模式中的代码时是不正确的。
1)您的类具有用户声明的构造函数,但它不是用户提供的 ,即不会阻止您的类成为聚合。 回想一下[dcl.init.aggr] / 1中的定义:
聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3) )。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.