继承默认构造函数在gcc中失败并在clang中工作,哪个有错误?

时间:2017-02-03 17:18:41

标签: c++ c++11 inheritance g++ clang++

举个简单的例子。

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;

据我所知,通过阅读cppreferenceDerived应该继承默认的Base::Base()构造函数,上面的代码应该很乐意编译。

编辑:我的不好,我链接的页面告诉了相反的故事。所以似乎铿锵有回归。

然而,我尝试过的所有版本的gcc都失败了,抱怨Derived没有默认构造函数,而clang做得很好,但仅限版本3.9.0 ; g ++ - 7 段错误,甚至 1

你可以在godbolt上看到它。

那么,谁在这里有过错? Clang允许它,或gcc(禁止段错误)不允许它?

1 虽然它似乎仅在godbolt上这样做,但我无法在本地重现段错误。

1 个答案:

答案 0 :(得分:3)

首先,编译器段错误始终是编译器错误。你应该举报。

其次,默认构造函数永远不会被继承。从N3242(N3797中的措辞类似),[class.inhctor]:

  

对于继承构造函数的候选集中的每个非模板构造函数,除了没有参数的构造函数或具有单个参数的复制/移动构造函数之外,构造函数使用相同的构造函数隐式声明除非在出现using声明的类中有一个用户声明的构造函数具有相同的签名。

Base的默认构造函数未继承到Derived,因此Derived t应该是格式错误的,因为没有有效的构造函数接受零参数。

在C ++ 17中,尽管措辞不同,但这仍然是不正确的。仍然是[class.inhctor],来自N4618:

  

当调用类型B的构造函数来初始化不同类型D的对象时(也就是说,当构造函数被继承时(7.3.3)),初始化就像使用默认的默认构造函数初始化D一样进行对象和继承构造函数的每个基类子对象,除了   通过调用继承的构造函数初始化B子对象。

要调用Base::Base(),我们必须从Derived::Derived()开始。但是没有Derived::Derived()