继承默认构造函数在 gcc 中失败并在 clang 中工作,哪个有错误?
Inheriting default constructor fails in gcc and works in clang, which one's got the bug?
举这个简单的例子。
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 segfaults, even 1.
大家可以在godbolt上自行查看。
那么,这是谁的错?允许它的 Clang,或者不允许它的 gcc(禁止段错误)?
1 虽然似乎只在 godbolt 上这样做,但我无法在本地重现段错误。
首先,编译器段错误始终是编译器错误。你应该报告那个。
其次,默认构造函数永远不会被继承。来自N3242(N3797中的写法类似),[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.
Base
的默认构造函数未继承到 Derived
,因此 Derived t
应该是 ill-formed,因为没有采用零参数的有效构造函数。
在 C++17 中,这仍然是 ill-formed,尽管措辞不同。仍然 [class.inhctor],来自 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.
要调用 Base::Base()
,我们必须从 Derived::Derived()
开始。但是没有Derived::Derived()
。
举这个简单的例子。
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 segfaults, even 1.
大家可以在godbolt上自行查看。
那么,这是谁的错?允许它的 Clang,或者不允许它的 gcc(禁止段错误)?
1 虽然似乎只在 godbolt 上这样做,但我无法在本地重现段错误。
首先,编译器段错误始终是编译器错误。你应该报告那个。
其次,默认构造函数永远不会被继承。来自N3242(N3797中的写法类似),[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.
Base
的默认构造函数未继承到 Derived
,因此 Derived t
应该是 ill-formed,因为没有采用零参数的有效构造函数。
在 C++17 中,这仍然是 ill-formed,尽管措辞不同。仍然 [class.inhctor],来自 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.
要调用 Base::Base()
,我们必须从 Derived::Derived()
开始。但是没有Derived::Derived()
。