显式默认默认构造函数和聚合

托米洛夫·阿纳托利(Tomilov Anatoliy)

如何解释这一差别,当我编译#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


在您的代码的形式中,iprivateA不是集合,因为它们不能具有私有成员。但是,只要i聚合1,并且由于执行了聚合初始化(请参见蓝色框),就不会调用任何构造函数,因此构造函数无关紧要。publicAexplicit

在此处输入图片说明

但是,一旦引入了私有成员,就需要按照红色框进行值初始化。因此[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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

默认和显式构造函数

显式默认的构造函数做什么?

显式默认模板构造函数

显式删除默认构造函数的目的

隐式与显式默认构造函数调用

C ++ 11:默认构造函数:隐式还是显式?

实现Externalizable时是否需要显式的默认构造函数?

std :: map默认构造函数是否显式?

C ++ 17中的显式默认构造函数

用户定义的构造函数和隐式默认构造函数

具有默认构造函数的VPTR与显式声明的构造函数

默认构造函数与隐式构造函数

如果显式默认或删除了构造函数,为什么自C ++ 20起聚合初始化不再起作用?

显式默认的默认构造函数被隐式删除,因为 unordered_map 与结构一起用作键

为什么不可能显式地默认具有volatile参数的副本构造函数?

如何应用使默认构造函数有条件显式?

显式调用琐碎的默认构造函数会导致额外的赋值调用

显式初始化没有默认构造函数的成员

为什么clang使用libstdc ++删除包含std :: optional的类型上的显式默认构造函数?

为什么std :: in_place_t的构造函数默认且显式?

对于默认构造函数,未定义隐式超级构造函数Num()。必须定义一个显式构造函数,这背后的逻辑是什么

调用隐式删除的默认构造函数

为什么显式默认的构造函数在VS2019中给出“找不到函数定义”警告?

Python构造函数和默认值

Lombok @Builder和JPA默认构造函数

关于默认和复制构造函数

继承和重载默认构造函数

默认移动构造函数和引用成员

结构指针(地址)和默认构造函数