解决过载的步骤为:
通过名称查找查找候选函数。不合格的调用将执行常规的不合格查询以及依赖于参数的查询(如果适用)。
将候选函数集过滤为一组可行函数。一个可行的函数,在调用该函数的参数与该函数采用的参数之间存在隐式转换序列。
void f(char); // (1)
void f(int ) = delete; // (2)
void f(); // (3)
void f(int& ); // (4)
f(4); // 1,2是可行的(即使2被删除了!)
// 3不可行,因为参数列表不匹配
// 4是不可行的,因为我们不能将临时绑定到
// a non-const lvalue reference
选择最佳可行的候选人。一个可行的功能F1比另一个可行的功能更好的功能F2,如果在每个参数的隐式转换序列F1并不比相应的隐式转换序列糟糕F2,和...:
3.1。对于某些参数,该参数中的隐式转换F1顺序比F2或中的该参数的转换顺序更好。
void f(int ); // (1)
void f(char ); // (2)
f(4); // 调用(1),转换顺序更好
3.2。在用户定义的转换中,从返回F1到目标类型的标准转换顺序比F2或返回类型的标准转换顺序更好。
struct A
{
operator int();
operator double();
} a;
int i = a; //a.operatorint()优于a.operatordouble()和转换
float f = a; // 暧昧
3.3。在直接引用绑定中,F1具有相同引用类型的F2不是,或者
struct A
{
operator X&(); // #1
operator X&&(); // #2
};
A a;
X& lx = a; // 呼叫#1
X&& rx = a; // 呼叫#2
3.4。F1不是一个函数模板专业化,但F2是,或
template <class T> void f(T ); // #1
void f(int ); // #2
f(42); // 呼叫#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); // 呼叫#2, more specialized
这里的顺序很重要。更好的转换顺序检查发生在模板检查与非模板检查之前。这会导致转发参考过载的常见错误:
struct A { A(A const& ); // #1 template <class T> A(T&& ); // #2, not constrained }; A a; A b(a); // 呼叫#2! // #1 is not a template but #2 resolves to // A(A& ), which is a less cv-qualified reference than #1 // 这使其成为更好的隐式转换序列
如果最后没有一个最佳可行的候选人,那电话就是模棱两可的:
void f(double ) { } void f(float ) { } f(42); // 错误:模棱两可