继承默认构造函数在gcc中失败并在clang中工作,哪一个有bug? [英] Inheriting default constructor fails in gcc and works in clang, which one's got the bug?
问题描述
以这个简单的例子为例。
struct Base {
// Base: :Base()由编译器
定义;
结构派生:基准{
使用Base :: Base; //应该继承Base :: Base()
Derived(int value):
m_value(value)
{}
private:
int m_value; //如果调用了Base :: Base(),则默认构造为
};
衍生t;
据我了解,通过阅读 cppreference , 派生
应该继承默认的 Base :: Base()
构造函数,并且上面的代码应该会愉快地编译。
编辑 :我的错,我链接到的页面却恰恰相反。
但是,我尝试过的所有gcc版本都失败了,抱怨 Derived
没有默认构造函数,而clang很好,但是仅自版本3.9.0起; g ++-7 段故障,甚至 1 。
您可以自己查看在 godbolt 上。
所以,谁在这是错吗
1 尽管它似乎只能在Godbolt上执行,但是我无法在本地重现该段错误。
首先,编译器段错误始终是编译器错误。您应该报告。
第二,默认构造函数从不继承。从N3242(N3797中的措辞类似)中,[class.inhctor]:
对于候选集合中的每个非模板构造函数继承的构造器除了没有参数的构造器或具有单个参数的复制/移动构造器之外,除非在用户声明的构造器中具有相同的签名,否则将隐式声明具有相同构造器特性的构造器。
Base
的默认构造函数不会继承到 Derived
中,因此 Derived t
应该格式错误,因为没有有效的构造函数接受零参数。
在C ++ 17中,尽管措辞不同,但这仍然是错误的形式。仍然是[class.inhctor],来自N4618:
当调用类型B的构造函数初始化不同类型D的对象时(也就是说,当继承构造函数(7.3.3)时,初始化将进行,就像使用默认的默认构造函数初始化D对象和继承该构造函数的每个基类子对象一样,除了
B通过调用继承的构造函数来初始化子对象。
要调用 Base :: Base()
,我们必须以 Derived :: Derived()
开头。但是没有 Derived :: Derived()
。
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, even 1.
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.
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()
.
这篇关于继承默认构造函数在gcc中失败并在clang中工作,哪一个有bug?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!