我想知道为什么这个函数调用没有歧义:
#include <iostream>
#include <vector>
template <class T>
class C
{
public:
typedef char c;
typedef double d;
int fun() {}
static c testFun( decltype(&C::fun) ) {return c();}
static d testFun(...) { return d(); }
};
int main() {
C<int>::testFun(0); // Why no ambiguity?
}
答案 0 :(得分:4)
隐含转换序列的排名,如[over.ics.rank]中所定义,强调我的:
比较隐式转换序列的基本形式时...
- 标准转换序列(13.3.3.1.1)比用户定义的转换更好的转换序列 序列或省略号转换序列,和 - 用户定义的转换序列(13.3.3.1.2)是比省略号转换更好的转换序列 序列(13.3.3.1.3)。
所以我们有两个功能:
static char testFun( int (C::*)() ) { return char(); }
static double testFun( ... ) { return double(); }
testFun(0)
这两个函数都可行。第一个涉及&#34;空成员指针转换&#34;根据[conv.mem],是标准转换序列。第二个匹配省略号并且是省略号转换序列。通过[over.ics.rank],前者是首选。没有歧义,一个严格要好于另一个。
如果我们有两个编译器无法决定的等效转换序列,则会出现模糊的重载。考虑一下我们是否有类似的东西:
static char testFun(int* ) { return 0; }
static int testFun(char* ) { return 0; }
testFun(0);
现在两个重载都等同于转换序列,所以我们有两个可行的候选者。
答案 1 :(得分:3)
您有标准转换与省略号转换。标准说标准转换是比后者更好的转换顺序。 [over.ics.rank] / P2:
标准转换序列(13.3.3.1.1)是比用户定义的转换更好的转换序列 序列或省略号转换序列
指向成员的转换是标准转换序列。 0
是一个空指针常量,可以转换为指向成员的指针。 [conv.mem] / P1:
空指针常量(4.10)可以转换为指向成员类型的指针;结果是null成员 该类型的指针值,可以与任何不是从空指针创建的成员的指针区分开来 不变。这种转换称为空成员指针转换。
因此首选超载。
答案 2 :(得分:0)
13.3.2可行的功能 具有少于m个参数的候选函数仅在其参数列表(8.3.5)中具有省略号时才可行。出于重载解析的目的,任何没有相应参数的参数都被认为是“匹配省略号”(13.3.3.1.3)。
还
可行的功能 给定如上所述构造的候选函数集,重载决策的下一步是检查参数和参数以将集合减少到可行函数集合 要包含在可行功能集中,候选功能必须满足以下要求:
1)如果有M个参数,那么具有正好M个参数的候选函数是可行的 2)如果候选函数具有少于M个参数,但具有省略号参数,则它是可行的 [...]
Overloading resolution
答案 3 :(得分:0)
空指针文字0应该与接受函数指针的函数完全匹配,并且被视为比匹配任何东西(...
)更强。