继承类并重用其构造函数问题在基类中缺失



在下面的程序中,struct B有两个用户定义的构造函数:一个来自int,另一个来自int&&(显然这不是很实用)。并且从 l 值创建B对象,该值应明确选择第一个构造函数。然后struct CB通过using-声明继承其构造函数派生,并从相同的 l 值创建C对象:

struct B {
B(int) {}
B(int&&) {}
};
int i = 1;
B b(i); //ok everywhere
struct C : B {
using B::B;
};
C c(i); //ok in Clang only

MSVC在最后一行打印了相当奇怪的错误:

source>(10): error C2668: 'B::B': ambiguous call to overloaded function
<source>(3): note: could be 'B::B(int &&)'
<source>(2): note: or       'B::B(int)'
<source>(10): note: while trying to match the argument list '(int)'

尽管 L 值参数。

GCC错误似乎同意并解释了更多:

source>:13:6: error: use of deleted function 'C::C(int) [inherited from B]'
13 | C c(i);
|      ^
<source>:10:14: note: 'C::C(int) [inherited from B]' is implicitly deleted because the default definition would be ill-formed:
10 |     using B::B;
|              ^
<source>:10:14: error: call of overloaded 'B(int)' is ambiguous

同时,Clang 很好地接受了代码,演示:https://gcc.godbolt.org/z/oGjzrYEhz

哪个编译器就在这里?

在 C++14 中,GCC 拒绝C c(i)是正确的。根据C++14:class.inhctor#8

隐式定义的继承构造函数执行类的一组初始化,该初始化将由

用户编写的内联构造函数为该类执行,该构造函数具有 mem-initializer-list,其唯一的 mem 初始值设定项具有 mem-initializer-id,该 id 命名在 using-声明的嵌套名称说明符和表达式列表中表示的基类,如下所示,并且其函数体中的复合语句为空 ([class.base.init])。如果该用户编写的构造函数格式不正确,则程序格式不正确。表达式列表中的每个表达式都是static_cast<T&&>(p)的形式,其中p是相应构造函数参数的名称,T是声明的p类型。

struct C定义等效于

struct C : B {
C(int p) : B(static_cast<int&&>(p)) {}
C(int&& p) : B(static_cast<int&&>(p)) {}
};

呼叫B(static_cast<int&&>(p))确实模棱两可。

在C++17标准中,措辞发生了变化C++17:class.inhctor.init#1,Clang根据新规则接受该程序是正确的。

最新更新