Inheriting default constructor fails in gcc and works in clang, which one's got the bug?

匆匆过客 提交于 2019-12-11 09:07:10

问题


Take this simple example.

struct Base {
    // Base::Base() defined by the compiler
};

struct Derived: Base { 
    using Base::Base; // Should inherit Base::Base()

    Derived(int value):
        m_value(value)
    {}

private:
    int m_value; // If Base::Base() is invoked, it's default constructed
};

Derived t;

As far as I understand by reading cppreference, Derived should inherit the default Base::Base() constructor and the code above should happily compile.

Edit: my bad, the page I linked to tells exactly the opposite story. So it seems clang's got a regression.

However, all versions of gcc I've tried fail at it, complaining that Derived has no default constructor, whilst clang does it just fine, but only since version 3.9.0; g++-7 segfaults, even1.

You can see it by yourselves on godbolt.

So, who's at fault here? Clang for allowing it, or gcc (bar the segfault) for not allowing it?


1 Although it seems to do so only on godbolt, I cannot reproduce the segfault locally.


回答1:


First, the compiler segfault is always a compiler bug. You should report that.

Second, default constructors are never inherited. From N3242 (the wording in N3797 is similar), [class.inhctor]:

For each non-template constructor in the candidate set of inherited constructors other than a constructor having no parameters or a copy/move constructor having a single parameter, a constructor is implicitly declared with the same constructor characteristics unless there is a user-declared constructor with the same signature in the class where the using-declaration appears.

The default constructor of Base isn't inherited into Derived, so Derived t should be ill-formed since there's no valid constructor taking zero arguments.


In C++17, this is still ill-formed, though the wording is different. Still [class.inhctor], from N4618:

When a constructor for type B is invoked to initialize an object of a different type D (that is, when the constructor was inherited (7.3.3)), initialization proceeds as if a defaulted default constructor were used to initialize the D object and each base class subobject from which the constructor was inherited, except that the B subobject is initialized by the invocation of the inherited constructor.

To invoke Base::Base(), we'd have to start with Derived::Derived(). But there's no Derived::Derived().



来源:https://stackoverflow.com/questions/42029637/inheriting-default-constructor-fails-in-gcc-and-works-in-clang-which-ones-got

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!