5

I try to understand the first accepted answer of @bolov to the question Deleted default constructor. Objects can still be created... sometimes [1]

It seems like I found a error there and so it messes up the whole explanation.

@bolov explains why this code SUCCEED to be compiled in c++11:

Scenario A

struct foo {
  foo() = delete;
};

// All bellow OK (no errors, no warnings)
foo f = foo{};
foo f = {};
foo f{}; // will use only this from now on.

And why this code FAILS to be compiled in c++11:

Scenario C

struct foo {
  foo() = delete;
  foo(int) {};
};

foo f{}; // error call to deleted constructor

He says that the point is that the first one foo is an aggregate and the second one foo is not an aggregate.

Then he gives the excerpt from cppreference:

The effects of list initialization of an object of type T are: ...

  • If T is an aggregate type, aggregate initialization is performed. This takes care of scenarios A B D E (and F in C++14)
  • Otherwise the constructors of T are considered in two phases:

    • All constructors that take std::initializer_list ...

    • otherwise [...] all constructors of T participate in overload resolution [...] This takes care of C (and F in C++11) ...

According to the excerpt when you write foo f { }; in scenario A you get aggregate-initialization. An it would be great. But in reality in c++11 (#3337 draft, closest to standard) you have different initialization order:

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)

So foo f { }; in scenario A should result in value-initialization, that is, the DELETED default constructor will be called and the code should fail to be compiled.

Community
  • 1
  • 1
JenyaKh
  • 2,040
  • 17
  • 25
  • 2
    I have no idea what you're asking. – Barry Sep 20 '16 at 08:27
  • Tried to make it more concise. – JenyaKh Sep 20 '16 at 08:42
  • @Quentin, okay, I will try to write better. – JenyaKh Sep 20 '16 at 08:53
  • @Quentin, I have rewritten my question. – JenyaKh Sep 20 '16 at 09:03
  • 1
    Very nice, that improved it a lot ! I'm a bit lost in the different initializations, but the [cppreference page for value initialisation](http://en.cppreference.com/w/cpp/language/value_initialization) states, before any description, that "In all cases, if the empty pair of braces `{}` is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.". – Quentin Sep 20 '16 at 09:11
  • @Quentin, thank you very much for the link! It would be great if this phrase is true but I fail to find this phrase in standard. :( I will try to search better. – JenyaKh Sep 20 '16 at 09:30

1 Answers1

3

As a result of Core Issue 1301, which was a defect against C++11, the precedence for list-initialization changed from:

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)

to:

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 initialize list has no elements and T is a class type with a default constructor, the object is value-initialized.

So foo{} in Scenario A is still aggregate-initialization.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    Yes, I understand BUT this change was in #3367 draft and it was accepted to C++14. But in Wiki I read that the draft #3337 is closest one to c++11. So in c++11 we DON'T have the change and so it looks like compilers when compiling as c++11 should not consider Scenario A as aggregate-initialization, am I right? – JenyaKh Sep 20 '16 at 09:26
  • 3
    @JenyaKh Issue 1301 was a defect against C++11, so a conforming C++11 compiler should implement the change. – Barry Sep 20 '16 at 09:31
  • 4
    @JenyaKh defect reports are backwards-applied onto the corresponding standard. They're patch updates, if you will :) – Quentin Sep 20 '16 at 09:33