I'm having a hard time trying to understand DR 2084

146 views
Skip to first unread message

Belloc

unread,
Nov 15, 2016, 9:20:27 AM11/15/16
to ISO C++ Standard - Discussion
DR 2084:

2084. NSDMIs and deleted union default constructors

Section: 12.1  [class.ctor]     Status: ready     Submitter: Daveed Vandevoorde     Date: 2015-02-12

According to 12.1 [class.ctor] paragraph 4 says,

A defaulted default constructor for class X is defined as deleted if:

  • X is a union-like class that has a variant member with a non-trivial default constructor,

  • ...

This should make the following example ill-formed:

  struct S {
    S();
  };
  union U {
    S s{};
  } u;

because the default constructor of U is deleted. However, both clang and g++ accept this without error. Should the rule be relaxed for a union with an NSDMI?

Notes from the May, 2015 meeting:

An NSDMI is basically syntactic sugar for a mem-initializer, so the presence of one should be treated as if a user-declared default constructor were present.

Proposed resolution (October, 2015):

Change 12.1 [class.ctor] paragraph 4 as follows:

...A defaulted default constructor for class X is defined as deleted if:

  • X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,

  • X is a union-like non-union class that has a variant member M with a non-trivial default constructor and no variant member of the anonymous union containing M has a default member initializer,

  • ...

I don't understand the reason for the change in the first bullet point above, as the snippet will continue to be ill-formed: U is a union with a variant member (s) with a non-trivial default constructor (the default constructor for S is user-provided) and no variant member of U has a default member initializer (S doesn't have a default member initializer, according to the definition of this term in [class.mem]/8. That is, U will be defined as deleted, as before, and the code should not compile. As a matter of fact VS2015 rejects this code, but clang and g++ accept it. In other words, what was relaxed with the new wording for the first bullet point above?


Nicol Bolas

unread,
Nov 15, 2016, 9:57:06 AM11/15/16
to ISO C++ Standard - Discussion


On Tuesday, November 15, 2016 at 9:20:27 AM UTC-5, Belloc wrote:
DR 2084:

2084. NSDMIs and deleted union default constructors

Section: 12.1  [class.ctor]     Status: ready     Submitter: Daveed Vandevoorde     Date: 2015-02-12

According to 12.1 [class.ctor] paragraph 4 says,

A defaulted default constructor for class X is defined as deleted if:

  • X is a union-like class that has a variant member with a non-trivial default constructor,

  • ...

This should make the following example ill-formed:

  struct S {
    S();
  };
  union U {
    S s{};
  } u;

because the default constructor of U is deleted. However, both clang and g++ accept this without error. Should the rule be relaxed for a union with an NSDMI?

Notes from the May, 2015 meeting:

An NSDMI is basically syntactic sugar for a mem-initializer, so the presence of one should be treated as if a user-declared default constructor were present.

Proposed resolution (October, 2015):

Change 12.1 [class.ctor] paragraph 4 as follows:

...A defaulted default constructor for class X is defined as deleted if:

  • X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,

  • X is a union-like non-union class that has a variant member M with a non-trivial default constructor and no variant member of the anonymous union containing M has a default member initializer,

  • ...

I don't understand the reason for the change in the first bullet point above, as the snippet will continue to be ill-formed: U is a union with a variant member (s) with a non-trivial default constructor (the default constructor for S is user-provided) and no variant member of U has a default member initializer (S doesn't have a default member initializer, according to the definition of this term in [class.mem]/8.

There is no member of S that has a default member initializer, but `U::s` does. And that's what the bullet point is looking for: a member of the union that has a DMI.

Belloc

unread,
Nov 15, 2016, 1:23:23 PM11/15/16
to ISO C++ Standard - Discussion
On Tuesday, November 15, 2016 at 12:57:06 PM UTC-2, Nicol Bolas wrote:


There is no member of S that has a default member initializer, but `U::s` does. And that's what the bullet point is looking for: a member of the union that has a DMI.

First off, the Standard does not define the term DMI. Second, the bullet point does not mention DMI nor NSDMI, but it mentions "default member initializer" which is defined in [class.mem]/8. And last, but not the least, this is not what the bullet point is saying, as far as I can understand:

U is a union that has a variant member (s) with a non-trivial default constructor (this is correct, as the default constructor for S is not user-provided) and no variant member of U (U has just one variant member - s) has a default member initializer.

As s is the sole variant member of U and since S has no default member initializer, we conclude that the defaulted default constructor for U must be defined as deleted.
 

Richard Smith

unread,
Nov 15, 2016, 1:49:26 PM11/15/16
to std-dis...@isocpp.org
As you just said, this is talking about the variant member 's', not 'S'. And 's' has a default member initializer.
 
we conclude that the defaulted default constructor for U must be defined as deleted.
 

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

Nicol Bolas

unread,
Nov 15, 2016, 2:11:55 PM11/15/16
to ISO C++ Standard - Discussion


On Tuesday, November 15, 2016 at 1:23:23 PM UTC-5, Belloc wrote:
On Tuesday, November 15, 2016 at 12:57:06 PM UTC-2, Nicol Bolas wrote:


There is no member of S that has a default member initializer, but `U::s` does. And that's what the bullet point is looking for: a member of the union that has a DMI.

First off, the Standard does not define the term DMI.

Are you really going to quibble about an obvious acronym of the term "default member initializer"?

Second, the bullet point does not mention DMI nor NSDMI, but it mentions "default member initializer" which is defined in [class.mem]/8. And last, but not the least, this is not what the bullet point is saying, as far as I can understand:

U is a union that has a variant member (s) with a non-trivial default constructor (this is correct, as the default constructor for S is not user-provided) and no variant member of U (U has just one variant member - s) has a default member initializer.

As s is the sole variant member of U and since S has no default member initializer, we conclude that the defaulted default constructor for U must be defined as deleted.

Types cannot have DMIs; members of types have default member initializer. `U::s` is a "variant member of U". And `U::s` has a DMI.

Belloc

unread,
Nov 15, 2016, 2:37:25 PM11/15/16
to ISO C++ Standard - Discussion


On Tuesday, November 15, 2016 at 5:11:55 PM UTC-2, Nicol Bolas wrote:

Are you really going to quibble about an obvious acronym of the term "default member initializer"?

I'm laughing now. I didn't realize DMI was an acronym for "default member initializer".
 

Types cannot have DMIs; members of types have default member initializer. `U::s` is a "variant member of U". And `U::s` has a DMI.

 You're right. Please accept my apologies.

Richard Smith

unread,
Nov 15, 2016, 5:39:15 PM11/15/16
to std-dis...@isocpp.org
On Tue, Nov 15, 2016 at 11:11 AM, Nicol Bolas <jmck...@gmail.com> wrote:


On Tuesday, November 15, 2016 at 1:23:23 PM UTC-5, Belloc wrote:
On Tuesday, November 15, 2016 at 12:57:06 PM UTC-2, Nicol Bolas wrote:


There is no member of S that has a default member initializer, but `U::s` does. And that's what the bullet point is looking for: a member of the union that has a DMI.

First off, the Standard does not define the term DMI.

Are you really going to quibble about an obvious acronym of the term "default member initializer"?

Given that part of the motivation for introducing the term "default member initializer" was to try to stop people using an opaque initialism for it, this doesn't seem like such an unreasonable complaint. Does it really help our discourse to abbreviate this term?

Second, the bullet point does not mention DMI nor NSDMI, but it mentions "default member initializer" which is defined in [class.mem]/8. And last, but not the least, this is not what the bullet point is saying, as far as I can understand:

U is a union that has a variant member (s) with a non-trivial default constructor (this is correct, as the default constructor for S is not user-provided) and no variant member of U (U has just one variant member - s) has a default member initializer.

As s is the sole variant member of U and since S has no default member initializer, we conclude that the defaulted default constructor for U must be defined as deleted.

Types cannot have DMIs; members of types have default member initializer. `U::s` is a "variant member of U". And `U::s` has a DMI.

--

Belloc

unread,
Nov 15, 2016, 5:49:05 PM11/15/16
to ISO C++ Standard - Discussion
Could you explain to me why the code below doesn't compile in clang and g++?

struct S {
    S
();
};
union U {

    S s
;
   
int i = 1;
} u;

U is a union with a variant member (s) with a non-trivial default constructor, but there is a variant member of U that has a default member initializer (i). Shouldn't this compile?

Richard Smith

unread,
Nov 15, 2016, 7:17:50 PM11/15/16
to std-dis...@isocpp.org
Core issue 2084 was only voted into the standard earlier this year, and apparently neither compiler has implemented it yet. 

Belloc

unread,
Nov 18, 2016, 12:00:49 PM11/18/16
to ISO C++ Standard - Discussion
Please find below, what appears to be an inconsistency between these two statements in the Standard. 

[class.union]/3 contains the following note:

Note: If any non-static data member of a union has a non-trivial default constructor ([class.ctor]), copy constructor ([class.copy]), move constructor ([class.copy]), copy assignment operator ([class.copy]), move assignment operator ([class.copy]), or destructor ([class.dtor]), the corresponding member function of the union must be user-provided or it will be implicitly deleted ([dcl.fct.def.delete]) for the union.  — end note ]

[class.ctor]/5 and its first bullet point are as follows:

A defaulted default constructor for class X is defined as deleted if:

  • X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,
I think the Note in [class.union]/3 is not in accordance with the first bullet point above. The note says that if any non-static data member of a union has a non-trivial default constructor, the union's default constructor must be user-provided or it will be implicitly deleted for the union. Therefore, if the constructor for the union is a defaulted default constructor, it will be deleted if the union has a non-static data member with a non-trivial default constructor, and this misses the last part of the bullet point, i.e., 
and no variant member of X has a default member initializer,. In other words, the Note is less strict than the bullet point, when determining whether the unions's defaulted default constructor is deleted.

Nicol Bolas

unread,
Nov 18, 2016, 3:05:50 PM11/18/16
to ISO C++ Standard - Discussion

No, the Note is more strict than the bullet point. The note specifies more types that will have deleted default constructors than the actual specification. The Note is more restrictive than the normative text.

So the notation should be changed or removed.

Belloc

unread,
Nov 18, 2016, 6:46:37 PM11/18/16
to ISO C++ Standard - Discussion


On Friday, November 18, 2016 at 6:05:50 PM UTC-2, Nicol Bolas wrote:
No, the Note is more strict than the bullet point. The note specifies more types that will have deleted default constructors than the actual specification. The Note is more restrictive than the normative text.

So the notation should be changed or removed.

When I used the words "less strict" in my comment, I was thinking in terms of the comprehensiveness of the rule itself, i.e., the Note is less strict than the bullet point because it has to satisfy just one condition ( that is, a union with a variant member with a non-trivial default constructor), whereas in the bullet point, there are two conditions to be satisfied, the previous one and the fact that no variant member of the union has a default initializer. 

Richard Smith

unread,
Nov 18, 2016, 8:15:22 PM11/18/16
to std-dis...@isocpp.org

--

Belloc

unread,
Nov 19, 2016, 6:03:36 AM11/19/16
to ISO C++ Standard - Discussion
On Friday, November 18, 2016 at 11:15:22 PM UTC-2, Richard Smith wrote:

It's nice to have this kind of feedback. Thanks.
Reply all
Reply to author
Forward
0 new messages