如何解释这一差别,当我编译#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
加法,表达有什么区别?
TL; DR:Clang和GCC在拒绝您的代码时是错误的。CWG 1630的分辨率使默认初始化的格式正确,而不管是否选择了默认构造函数explicit
。
在您的代码的形式中,i
是private
,A
不是集合,因为它们不能具有私有成员。但是,只要i
是聚合1,并且由于执行了聚合初始化(请参见蓝色框),就不会调用任何构造函数,因此构造函数无关紧要。public
A
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 )。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句