c++c++11constructorinherited-constructors

Inheriting constructors and brace-or-equal initializers


I don't understand why you can't compile a class which has both a member (not default constructible) with a brace-or-equal initializer and an inherited constructor. g++ says :

test.cpp:22:15: error: use of deleted function ‘Derived::Derived(float)’
Derived d(1.2f);

test.cpp:16:13: note: ‘Derived::Derived(float)’ is implicitly deleted
because the default definition would be ill-formed:
using Base::Base;

test.cpp:16:13: error: no matching function for call to ‘NoDefCTor::NoDefCTor()’
test.cpp:5:1: note: candidate:
NoDefCTor::NoDefCTor(int) NoDefCTor(int) {}

Code that fails to compile (under g++ 5.1):

struct NoDefCTor
{
    NoDefCTor(int) {}
};

struct Base
{
    Base(float) {}
};

struct Derived : Base
{
    using Base::Base;
    NoDefCTor n2{ 4 };
};

int main()
{
    Derived d(1.2f);
}

Code that compiles, but never uses NoDefCTor's default constructor (despite apparently needing it!):

struct NoDefCTor
{
    NoDefCTor(int) {}
    NoDefCTor() = default;
};

struct Base
{
    Base(float) {}
};

struct Derived : Base
{
    using Base::Base;
    NoDefCTor n2{ 4 };
};

int main()
{
    Derived d(1.2f);
}

I don't really like the idea of having a default constructor when I don't need one. On a side note both versions compile (and behave) just fine on MSVC14.


Solution

  • This is a gcc bug, #67054. Comparing the bug report by alltaken380 to the OP's case:

    // gcc bug report                        // OP
    struct NonDefault                        struct NoDefCTor
    {                                        {
        NonDefault(int) {}                       NoDefCTor(int) {}
    };                                       };
    
    struct Base                              struct Base
    {                                        {
        Base(int) {}                             Base(float) {}
    };                                       };
    
    struct Derived : public Base             struct Derived : Base
    {                                        {
        NonDefault foo = 4;                      NoDefCTor n2{ 4 };
    
        using Base::Base;                        using Base::Base;
    };                                       };
    
    auto test()                              int main()
    {                                        {
        auto d = Derived{ 5 };                   Derived d(1.2f);
    }                                        }
    

    We can even try this on recent gcc 6.0 versions, and it still fails to compile. clang++3.6 and, according to the OP, MSVC14 accept this program.