重载决议的步骤
重载解析的步骤是:
-
通过名称查找查找候选函数。非限定调用将执行常规非限定查找以及依赖于参数的查找(如果适用)。
-
将候选函数集过滤为一组可行的函数。一个可行的函数,在调用函数的参数和函数所使用的参数之间存在隐式转换序列。
void f(char); // (1) void f(int ) = delete; // (2) void f(); // (3) void f(int& ); // (4) f(4); // 1,2 are viable (even though 2 is deleted!) // 3 is not viable because the argument lists don't match // 4 is not viable because we cannot bind a temporary to // a non-const lvalue reference
-
选择最有可行的候选人。如果
F1
中每个参数的隐式转换序列不比F2
中相应的隐式转换序列差,则可行函数F1
是比另一个可行函数F2
更好的函数,并且……:3.1。对于某些参数,
F1
中该参数的隐式转换序列是比F2
中的参数更好的转换序列,或者void f(int ); // (1) void f(char ); // (2) f(4); // call (1), better conversion sequence
3.2。在用户定义的转换中,从
F1
返回到目标类型的标准转换序列是比F2
的返回类型更好的转换序列,或者struct A { operator int(); operator double(); } a; int i = a; // a.operator int() is better than a.operator double() and a conversion float f = a; // ambiguous
3.3。在直接引用绑定中,
F1
与F2
具有相同类型的引用,或者struct A { operator X&(); // #1 operator X&&(); // #2 }; A a; X& lx = a; // calls #1 X&& rx = a; // calls #2
3.4。
F1
不是一个功能模板专业化,但F2
是,或template <class T> void f(T ); // #1 void f(int ); // #2 f(42); // calls #2, the non-template
3.5。
F1
和F2
都是功能模板专业化,但F1
比F2
更专业。template <class T> void f(T ); // #1 template <class T> void f(T* ); // #2 int* p; f(p); // calls #2, more specialized
这里的订购很重要。在模板与非模板检查之前进行更好的转换序列检查。这导致转发引用上的重载常见错误:
struct A {
A(A const& ); // #1
template <class T>
A(T&& ); // #2, not constrained
};
A a;
A b(a); // calls #2!
// #1 is not a template but #2 resolves to
// A(A& ), which is a less cv-qualified reference than #1
// which makes it a better implicit conversion sequence
如果最后没有单一的最佳可行候选人,那么这个调用是不明确的:
void f(double ) { }
void f(float ) { }
f(42); // error: ambiguous