Implicitly defined constructor deleted due to variant member, N3690/N4140 vs N4659/N4727










2















My story starts off the same as this person's here:



Unions in C++11: default constructor seems to be deleted



The resolution here (now about three years old) is a bit unsatisfactory, because the "Digging into the standard" that the author did ended up with concluding that the behavior was as described in the standard, but unfortunately the quote is from a Note, and those are supposed to be non-normative (I've been told). Anyways, there's a link to an old bug report on gcc that is claimed to be fixed, and they also claim that the code compiles in clang, however I'm having issues (with the same and similar code). The matter boils down to a whether or not a union-like class with a default initialized variant member should compile whether or not there is another variant member (in the same variant set) that has a non-trivial constructor.



struct X 
X() //non-trivial default constructor
;

struct U
union
X x;
int i0; //default member initializer
;
;

U u; //error: default constructor deleted


These failed with -std=c++14 and -std=c++17 on gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) as well as clang version 6.0.0-1ubuntu2.



There seems to be a history of change in the standard, and so I'll put forth what I've found:




N3690/N4140:

[12.1.4/Constructors]
...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

[9.5.2/Unions]...
[Note:
If any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
— end note]






N4659/N4727:

[15.1.5/Constructors]
...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

[12.3.3/Unions]...
[Note:
Absent default member initializers, if any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
— end note]





Anyways, it seems like at one point this code should have failed, but it was thought to be conforming and that gcc had a bug, and it was claimed to be fixed, but now it should succeed, and it doesn't compile (I may not have the chronology perfect here, it would be interesting to know the full story; figuring it out is one step further than I'd like to take) but I guess I'm just wondering what is the correct behavior?










share|improve this question



















  • 1





    Notes are indeed non-normative. That's a general principle for ISO standards; works the same in ISO C.

    – MSalters
    Nov 15 '18 at 0:45











  • Related Why does a struct, that has another struct wrapped in a union as a member not compile without an explicit default constructor?

    – Shafik Yaghmour
    Nov 15 '18 at 2:43















2















My story starts off the same as this person's here:



Unions in C++11: default constructor seems to be deleted



The resolution here (now about three years old) is a bit unsatisfactory, because the "Digging into the standard" that the author did ended up with concluding that the behavior was as described in the standard, but unfortunately the quote is from a Note, and those are supposed to be non-normative (I've been told). Anyways, there's a link to an old bug report on gcc that is claimed to be fixed, and they also claim that the code compiles in clang, however I'm having issues (with the same and similar code). The matter boils down to a whether or not a union-like class with a default initialized variant member should compile whether or not there is another variant member (in the same variant set) that has a non-trivial constructor.



struct X 
X() //non-trivial default constructor
;

struct U
union
X x;
int i0; //default member initializer
;
;

U u; //error: default constructor deleted


These failed with -std=c++14 and -std=c++17 on gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) as well as clang version 6.0.0-1ubuntu2.



There seems to be a history of change in the standard, and so I'll put forth what I've found:




N3690/N4140:

[12.1.4/Constructors]
...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

[9.5.2/Unions]...
[Note:
If any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
— end note]






N4659/N4727:

[15.1.5/Constructors]
...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

[12.3.3/Unions]...
[Note:
Absent default member initializers, if any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
— end note]





Anyways, it seems like at one point this code should have failed, but it was thought to be conforming and that gcc had a bug, and it was claimed to be fixed, but now it should succeed, and it doesn't compile (I may not have the chronology perfect here, it would be interesting to know the full story; figuring it out is one step further than I'd like to take) but I guess I'm just wondering what is the correct behavior?










share|improve this question



















  • 1





    Notes are indeed non-normative. That's a general principle for ISO standards; works the same in ISO C.

    – MSalters
    Nov 15 '18 at 0:45











  • Related Why does a struct, that has another struct wrapped in a union as a member not compile without an explicit default constructor?

    – Shafik Yaghmour
    Nov 15 '18 at 2:43













2












2








2








My story starts off the same as this person's here:



Unions in C++11: default constructor seems to be deleted



The resolution here (now about three years old) is a bit unsatisfactory, because the "Digging into the standard" that the author did ended up with concluding that the behavior was as described in the standard, but unfortunately the quote is from a Note, and those are supposed to be non-normative (I've been told). Anyways, there's a link to an old bug report on gcc that is claimed to be fixed, and they also claim that the code compiles in clang, however I'm having issues (with the same and similar code). The matter boils down to a whether or not a union-like class with a default initialized variant member should compile whether or not there is another variant member (in the same variant set) that has a non-trivial constructor.



struct X 
X() //non-trivial default constructor
;

struct U
union
X x;
int i0; //default member initializer
;
;

U u; //error: default constructor deleted


These failed with -std=c++14 and -std=c++17 on gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) as well as clang version 6.0.0-1ubuntu2.



There seems to be a history of change in the standard, and so I'll put forth what I've found:




N3690/N4140:

[12.1.4/Constructors]
...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

[9.5.2/Unions]...
[Note:
If any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
— end note]






N4659/N4727:

[15.1.5/Constructors]
...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

[12.3.3/Unions]...
[Note:
Absent default member initializers, if any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
— end note]





Anyways, it seems like at one point this code should have failed, but it was thought to be conforming and that gcc had a bug, and it was claimed to be fixed, but now it should succeed, and it doesn't compile (I may not have the chronology perfect here, it would be interesting to know the full story; figuring it out is one step further than I'd like to take) but I guess I'm just wondering what is the correct behavior?










share|improve this question
















My story starts off the same as this person's here:



Unions in C++11: default constructor seems to be deleted



The resolution here (now about three years old) is a bit unsatisfactory, because the "Digging into the standard" that the author did ended up with concluding that the behavior was as described in the standard, but unfortunately the quote is from a Note, and those are supposed to be non-normative (I've been told). Anyways, there's a link to an old bug report on gcc that is claimed to be fixed, and they also claim that the code compiles in clang, however I'm having issues (with the same and similar code). The matter boils down to a whether or not a union-like class with a default initialized variant member should compile whether or not there is another variant member (in the same variant set) that has a non-trivial constructor.



struct X 
X() //non-trivial default constructor
;

struct U
union
X x;
int i0; //default member initializer
;
;

U u; //error: default constructor deleted


These failed with -std=c++14 and -std=c++17 on gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) as well as clang version 6.0.0-1ubuntu2.



There seems to be a history of change in the standard, and so I'll put forth what I've found:




N3690/N4140:

[12.1.4/Constructors]
...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

[9.5.2/Unions]...
[Note:
If any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
— end note]






N4659/N4727:

[15.1.5/Constructors]
...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

[12.3.3/Unions]...
[Note:
Absent default member initializers, if any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
— end note]





Anyways, it seems like at one point this code should have failed, but it was thought to be conforming and that gcc had a bug, and it was claimed to be fixed, but now it should succeed, and it doesn't compile (I may not have the chronology perfect here, it would be interesting to know the full story; figuring it out is one step further than I'd like to take) but I guess I'm just wondering what is the correct behavior?







c++ g++ language-lawyer unions clang++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 1:00









Shafik Yaghmour

126k23327543




126k23327543










asked Nov 15 '18 at 0:15









Nathan ChappellNathan Chappell

1278




1278







  • 1





    Notes are indeed non-normative. That's a general principle for ISO standards; works the same in ISO C.

    – MSalters
    Nov 15 '18 at 0:45











  • Related Why does a struct, that has another struct wrapped in a union as a member not compile without an explicit default constructor?

    – Shafik Yaghmour
    Nov 15 '18 at 2:43












  • 1





    Notes are indeed non-normative. That's a general principle for ISO standards; works the same in ISO C.

    – MSalters
    Nov 15 '18 at 0:45











  • Related Why does a struct, that has another struct wrapped in a union as a member not compile without an explicit default constructor?

    – Shafik Yaghmour
    Nov 15 '18 at 2:43







1




1





Notes are indeed non-normative. That's a general principle for ISO standards; works the same in ISO C.

– MSalters
Nov 15 '18 at 0:45





Notes are indeed non-normative. That's a general principle for ISO standards; works the same in ISO C.

– MSalters
Nov 15 '18 at 0:45













Related Why does a struct, that has another struct wrapped in a union as a member not compile without an explicit default constructor?

– Shafik Yaghmour
Nov 15 '18 at 2:43





Related Why does a struct, that has another struct wrapped in a union as a member not compile without an explicit default constructor?

– Shafik Yaghmour
Nov 15 '18 at 2:43












1 Answer
1






active

oldest

votes


















2














I believe you are correct, this should be valid code now.



The original wording for the non-normative note that descirbes the old behavior comes from n2544: Unrestricted Unions (Revision 2).



That change you note in the normative section comes from Core defect report 2048: NSDMIs and deleted union default constructors which says:




According to 15.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?




and modified [class.default.ctor]p2 as you referenced from N4659/N4727. Additionally we can see that the case mentioned in the DR does indeed work for gcc and clang but not for MSVC see it live on godbolt.



This feels like a bug since [class.default.ctor]p2.1 should cover this case and make it will-formed since the member i has a default member initializer:




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,







share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53310690%2fimplicitly-defined-constructor-deleted-due-to-variant-member-n3690-n4140-vs-n46%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    I believe you are correct, this should be valid code now.



    The original wording for the non-normative note that descirbes the old behavior comes from n2544: Unrestricted Unions (Revision 2).



    That change you note in the normative section comes from Core defect report 2048: NSDMIs and deleted union default constructors which says:




    According to 15.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?




    and modified [class.default.ctor]p2 as you referenced from N4659/N4727. Additionally we can see that the case mentioned in the DR does indeed work for gcc and clang but not for MSVC see it live on godbolt.



    This feels like a bug since [class.default.ctor]p2.1 should cover this case and make it will-formed since the member i has a default member initializer:




    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,







    share|improve this answer





























      2














      I believe you are correct, this should be valid code now.



      The original wording for the non-normative note that descirbes the old behavior comes from n2544: Unrestricted Unions (Revision 2).



      That change you note in the normative section comes from Core defect report 2048: NSDMIs and deleted union default constructors which says:




      According to 15.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?




      and modified [class.default.ctor]p2 as you referenced from N4659/N4727. Additionally we can see that the case mentioned in the DR does indeed work for gcc and clang but not for MSVC see it live on godbolt.



      This feels like a bug since [class.default.ctor]p2.1 should cover this case and make it will-formed since the member i has a default member initializer:




      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,







      share|improve this answer



























        2












        2








        2







        I believe you are correct, this should be valid code now.



        The original wording for the non-normative note that descirbes the old behavior comes from n2544: Unrestricted Unions (Revision 2).



        That change you note in the normative section comes from Core defect report 2048: NSDMIs and deleted union default constructors which says:




        According to 15.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?




        and modified [class.default.ctor]p2 as you referenced from N4659/N4727. Additionally we can see that the case mentioned in the DR does indeed work for gcc and clang but not for MSVC see it live on godbolt.



        This feels like a bug since [class.default.ctor]p2.1 should cover this case and make it will-formed since the member i has a default member initializer:




        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,







        share|improve this answer















        I believe you are correct, this should be valid code now.



        The original wording for the non-normative note that descirbes the old behavior comes from n2544: Unrestricted Unions (Revision 2).



        That change you note in the normative section comes from Core defect report 2048: NSDMIs and deleted union default constructors which says:




        According to 15.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?




        and modified [class.default.ctor]p2 as you referenced from N4659/N4727. Additionally we can see that the case mentioned in the DR does indeed work for gcc and clang but not for MSVC see it live on godbolt.



        This feels like a bug since [class.default.ctor]p2.1 should cover this case and make it will-formed since the member i has a default member initializer:




        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,








        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 16 '18 at 5:57

























        answered Nov 15 '18 at 0:29









        Shafik YaghmourShafik Yaghmour

        126k23327543




        126k23327543





























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53310690%2fimplicitly-defined-constructor-deleted-due-to-variant-member-n3690-n4140-vs-n46%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Barbados

            How to read a connectionString WITH PROVIDER in .NET Core?

            Node.js Script on GitHub Pages or Amazon S3