在下面的程序中,struct B
有两个用户定义的构造函数:一个来自int
,另一个来自int&&
(显然这不是很实用)。并且从 l 值创建B
对象,该值应明确选择第一个构造函数。然后struct C
从B
通过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根据新规则接受该程序是正确的。