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

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

本文关键字:工作 有错误 构造函数 默认 gcc 失败 继承 clang      更新时间:2023-10-16

举一个简单的例子。

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;

根据我阅读cppreference的理解,Derived应该继承默认的Base::Base()构造函数,上面的代码应该可以愉快地编译

编辑:我的坏,我链接到的页面告诉完全相反的故事。看来clang已经回归了。

然而,我尝试过的所有版本的gcc都失败了,抱怨Derived没有默认构造函数,而clang做得很好,但只是从3.9.0版本开始;g++-7分段故障,甚至1

你可以自己在godbolt上看到它。

那么,谁的错在这里?为允许它而鼓掌,还是为不允许它而欢呼?


1尽管它似乎只在godbolt上这样做,但我无法在本地复制segfault。

首先,编译器segfault始终是一个编译器错误。你应该报告。

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

对于继承构造函数的候选集合中的每个非模板构造函数,而不是没有参数的构造函数或具有单个参数的复制/移动构造函数,构造函数是用相同的构造函数特性隐式声明的,除非在出现using声明的类中存在具有相同签名的用户声明构造函数。

Base的默认构造函数没有继承到Derived中,因此Derived t的格式应该不正确,因为没有接受零参数的有效构造函数。


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

当调用类型B的构造函数来初始化不同类型D的对象时(即,当继承构造函数时(7.3.3)),初始化过程就像使用默认默认构造函数来初始化D对象和继承构造函数的每个基类子对象一样,但通过调用继承的构造函数来初始化B子对象。

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