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











up vote
1
down vote

favorite












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 i{0}; //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 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 at 2:43















up vote
1
down vote

favorite












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 i{0}; //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 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 at 2:43













up vote
1
down vote

favorite









up vote
1
down vote

favorite











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 i{0}; //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 i{0}; //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 at 1:00









Shafik Yaghmour

124k23316522




124k23316522










asked Nov 15 at 0:15









Nathan Chappell

1127




1127








  • 1




    Notes are indeed non-normative. That's a general principle for ISO standards; works the same in ISO C.
    – MSalters
    Nov 15 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 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 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 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 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 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 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 at 2:43












1 Answer
1






active

oldest

votes

















up vote
1
down vote













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',
    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








    up vote
    1
    down vote













    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



























      up vote
      1
      down vote













      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

























        up vote
        1
        down vote










        up vote
        1
        down vote









        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 at 5:57

























        answered Nov 15 at 0:29









        Shafik Yaghmour

        124k23316522




        124k23316522






























            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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







            Popular posts from this blog

            mysqli_query(): Empty query in /home/lucindabrummitt/public_html/blog/wp-includes/wp-db.php on line 1924

            How to change which sound is reproduced for terminal bell?

            Can I use Tabulator js library in my java Spring + Thymeleaf project?