N4296::13.3.1/5 [over.match.funcs]
说:
5在重载解析期间,隐式对象参数为与其他论点没有区别。隐式对象参数,但是,由于相应的转换论点应遵守以下附加规则:
(5.1)-不能引入任何临时对象来保存参数隐式对象参数;和
(5.2)-没有用户定义的转换可以用来实现与它的类型匹配。
最后一个限制对我来说并不明确,因为我认为候选函数集不可能包含两个或多个具有不同隐式对象参数的函数,因此有必要应用隐式转换来选择其中一个。例如:
struct B
{
void foo(int a){ }
};
struct C
{
void foo(int a){ }
};
struct A : B, C{ } a;
int main(){ a.foo(3); }
在示例中,隐式 derived-to-base
类转换只能应用。即使我们定义了显式转换,也不会将其应用于隐式对象参数。
所以不清楚5.2
规则的内容是什么?
5.2点表示存在用户定义转换运算符。您没有出现过这种情况,您只是对存在于两个基类中的成员函数进行了模棱两可的调用,其中涉及派生到基址的引用/指针转换,这是标准转换,而不是用户定义的转换,因此与5.2无关。
此情况适用于5.2:
struct B
{
void foo(int a){ }
};
struct A {
B b;
operator B&() { return b; };
} a;
int main(){
a.foo(3); // ERROR (because of 5.2)
static_cast<B&>(a).foo(3); // OK
}
Point 5.2仅表示编译器无法尝试通过隐式用户定义的转换运算符(operator B&()
成员)来最终找到候选的“ foo”函数。这与foo是像void foo(B&, int)
这样的自由函数并用foo(a,3)
调用的情况形成对比,在这种情况下,编译器可以执行a
到B&
的转换以找到foo函数。成为通话的可接受候选人。之所以这样说是因为成员函数版本与其等效的自由函数版本之间的行为是不同的。
因为我认为候选函数集不可能包含两个或多个具有不同隐式对象参数的函数
BTW,您不必具有“两个或多个”即可创建一组候选函数,一组候选也可以仅由一个函数组成,甚至根本不包含。正如Piotr S.所展示的,在这种特殊情况下,肯定有可能造成多个候选对象可能具有不同的隐式对象参数类型的情况。