我有一些代码如下:
class bar;
class foo
{
public:
operator bar() const;
};
class bar
{
public:
bar(const foo& foo);
};
void baz() {
foo f;
bar b = f; // [1]
const foo f2;
bar b2 = f2; // [2]
}
GCC在[2]处给出错误,但不是[1]。 Clang给出了两个错误,显然MSVC都没有给出错误。谁没错?
答案 0 :(得分:2)
歧义。 (另外,如果你停在tl; dr,那么language-lawyer
标签可能不是你的茶杯。^ _ ^)
两个候选人都有一个const foo&
参数,它与const foo
或foo
参数同等地绑定。没有其他规则可能更喜欢一种或另一种功能。
在这两种情况下
T
是初始化的类型,在这两种情况下都是bar
。
S
是初始化表达式的类型,分别是foo
和const foo
两种情况。
T
的构造函数是候选者([over.match.copy]/1.1)
bar::bar(const foo& foo);
是候选人_cv_ S
,因此会考虑非显式conversion functions :( [over.match.copy]/1.2)
foo::operator bar() const
未隐藏在foo
内或const foo
内,并产生与bar
相同的T
,因此是候选人。< / LI>
所以我们的候选人名单在两种情况下都是相同的:
bar::bar(const foo& foo)
foo::operator bar() const
在这两种情况下,我们都有user-defined conversion组成的:
如果我们选择构造函数,“结果类型”是“结构对象由构造函数初始化的目标类型的cv非限定版本的prvalue”([dcl.init]/17.6.3),因此对于两个候选函数,第二个标准转换是身份(bar
- &gt; bar
)。
Per [dcl.init]/17.6.3,初始化表达式将成为所选调用的参数,分别为foo
和const foo
两种情况。
bar::bar(const foo& foo)
foo
和const foo
到const foo&
([over.match.viable]/4)const foo
与foo
和const foo
都具有参考兼容性,因为const
比const
更符合cv资格且没有任何内容。 [dcl.init.ref]/4 const foo&
直接绑定到左值foo
和左值const foo
。 [dcl.init.ref]/5 foo::operator bar() const
const foo&
([over.match.funcs]/4)foo
和const foo
到const foo&
([over.match.viable]/4)两者都是 Identity =&gt;用户定义的转换=&gt;身份,即user-defined conversion sequences。
我们可以在序列之间建立排名吗?仅在one of the following applies
时转换序列难以区分,即既不好也不差
这两种功能都是“更好”的功能吗?仅在one of the following applies
时bar
的构造函数,但另一个不是bar
([over.match.best]/1.9)基类的构造函数两者都不是“更好”的功能,因此呼叫形式不正确。 [over.match.best]/2