为什么这个函数调用没有歧义?

时间:2015-04-08 13:52:20

标签: c++

我想知道为什么这个函数调用没有歧义:

#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?
}

http://coliru.stacked-crooked.com/a/241ce5ab82b4a018

4 个答案:

答案 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应该与接受函数指针的函数完全匹配,并且被视为比匹配任何东西(...)更强。