5

MyClass::MyData appears to be default constructible, but std::is_default_constructible_v<MyClass::MyData>() returns false. Is this a GCC bug? Code on godbolt at https://godbolt.org/z/qrfz8c7h8.

#include <variant>
#include <type_traits>

class MyClass
{
public:
    
    struct MyData
    {
        // It doesn't matter if there is a default constructor here.
        MyData() = default;

        // Fix: Instead of using "= default", if you explicitly 
        // define an empty constructor everything works. (However,
        // eliminating the constructor altogether does not fix
        // the issue.)
        //MyData() { }

        const char* m_name{ nullptr };
    };


    std::variant<MyData> m_var;

    // Using this line instead will fix the problem.
    //std::variant<MyData> m_var{ MyData{} };

    // Or, commenting out this constructor will fix the problem.
    MyClass()
    {
    }
};

// Notice the inconsistency here.  I can clearly make a default x,
// but the static assert fails.
MyClass::MyData x;
static_assert(std::is_default_constructible_v<MyClass::MyData>);

MyClass y;
static_assert(std::is_default_constructible_v<MyClass>);

int main()
{
    return 0;
}

Note from original poster: The duplicate shown does answer the question, although this is a slightly different case.

  • The first time std::is_default_constructible is checked is when the variant is declared.
  • At that time, the containing class is not fully declared, and so std::is_default_constructible_v is false (at least in gcc).
  • When the static assert is checked later, the declaration is complete. The class can now be default constructed, but unfortunately, std::is_default_constructible_v must stay the same and is still false.

It isn't completely clear to me whether this is a gcc bug (erroring on valid code) or a Microsoft bug (accepting invalid code), but the question is definitely a duplicate.

Rob L
  • 2,351
  • 13
  • 23
  • 2
    The static assert you point at does not in fact fail. Only the variant chokes, and that is touched upon in the dupe. – StoryTeller - Unslander Monica Jul 14 '22 at 15:06
  • 1
    `MyData() noexcept = default;` and all's well – Ted Lyngmo Jul 14 '22 at 15:07
  • 1
    @TedLyngmo That makes sense. However, if I don't put a constructor at all, the problem is there. Here's a simplified godbolt: https://godbolt.org/z/z716rr4KE. It seems that the variant declaration screws up the class definition somehow? Ok, I now see the dupe. the variant declaration causes is_default_constructible_v() to be called prematurely and the value gets cached. – Rob L Jul 14 '22 at 15:10
  • Clang also fails to compile this, MSVC accepts – YurkoFlisk Jul 14 '22 at 15:23
  • Linked duplicate doesn't fit to this scenario. Please try different versions `0-2` https://godbolt.org/z/rr838xdcP (note moved default constructor outside) - so reopening. – Marek R Jul 14 '22 at 15:39
  • 2
    Sigh... there will always be a busybody... posting the duplicate link again https://stackoverflow.com/q/69050558/817643 – StoryTeller - Unslander Monica Jul 14 '22 at 16:46
  • 3
    @MarekR in what way is that different than the duplicate? The duplicate seems spot on. – Jeff Garrett Jul 14 '22 at 17:15
  • From the original poster, the cause is the same as the dupe. I accept that. I'll see if I can make an edit to clarify. – Rob L Jul 18 '22 at 18:58

0 Answers0