C++14 value-initialization with deleted constructor

北城以北 提交于 2019-12-08 22:55:20

问题


I have some misunderstanding:

Let's mark default constructor of struct A as deleted:

struct A
{
  A() = delete;
};

The next instruction is well-formed and what's that effect?:

A a{};

From cppreference value initilization:

1) If T is a class type with no default constructor or with a user-provided default constructor or with a deleted default constructor, the object is default-initialized.

but then the effect of default initialization is:

If T is a class type, the default constructor is called to provide the initial value for the new object.

Or it's aggregate initialization? Thanks!


回答1:


Your struct A is :

  • a class type that has:
    • no user-provided constructors1,
    • no private or protected non-static data members,
    • no base classes,
    • no virtual member functions.

It therefore qualifies as an aggregate type, according to the definition provided by § 8.5.1/1.

Then comes the priority of aggregate initialization over value initialization. The standard says that aggregate initialization has precedence over value intialization (draft N3936, § 8.5.4/3, page 201) (emphasis mine)

List-initialization of an object or reference of type T is defined as follows:

  • If T is an aggregate, aggregate initialization is performed (8.5.1).
  • Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
  • [... more rules...]

(1) As requested in the comments on why a deleted constructor does not count as user-defined, here is what the standard says (draft N3936, § 8.4.2/5, page 198):

A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.




回答2:


It is well formed. A is an aggregate1, and, according to draft N3936, an empty initializer list used in direct-list initialization of an aggregate results in aggregate initialization:

From § 8.5.4/3 List-initialization [dcl.init.list]:

List-initialization of an object or reference of type T is defined as follows:

— If T is an aggregate, aggregate initialization is performed (8.5.1).

[ Example:

struct S2 { int m1; double m2, m3; };

....

S2 s23{}; // OK: default to 0,0,0

....

— end example ]

....

The relevant changes between C++11 and C++1y are a change in the precedence of aggregate vs. value initialization for the case of aggregates:

C++11 leads with

List-initialization of an object or reference of type T is defined as follows:

— If the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.

— Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1)....

followed by the example above.

C++1y gives priority to aggregate initialization:

List-initialization of an object or reference of type T is defined as follows:

— If T is an aggregate, aggregate initialization is performed (8.5.1).

....

— Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.


1 Why is A an aggregate?

It is an aggregate both in C++11 and C++14.

C++1y:

8.5.1 Aggregates [dcl.init.aggr]

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

The only part that is not obvious is whether the defaulted constructor is user-provided or not. It isn't:

In § 8.4.2 [dcl.fct.def.default]:

A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.



来源:https://stackoverflow.com/questions/23882409/c14-value-initialization-with-deleted-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!