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

Why no ambiguity in this function call?

本文关键字:歧义 函数调用 为什么      更新时间:2023-10-16

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

#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

有一个隐式转换序列的排序,如[over.ics.rank]中所定义,emphasis mine:

当比较隐式转换序列的基本形式时
-标准转换序列(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)都是可行的。第一个将涉及根据[conv.mem]的"null成员指针转换",并且是标准转换序列。第二个将匹配省略号,并且是省略号转换序列。按[超过.ics.rank],前者优先。没有歧义,一个绝对比另一个好。

如果我们有两个等价的转换序列,而编译器无法在这两个序列之间做出决定,则会出现不明确的重载。考虑一下我们是否有这样的东西:

static char testFun(int* ) { return 0; }
static int testFun(char* ) { return 0; }
testFun(0);

现在,就转换序列而言,两个重载都是等效的,所以我们有两个可行的候选者。

您有一个标准转换与省略号转换。该标准规定,标准转换是比后者更好的转换序列。[over.ics.rank]/p2:

标准转换序列(13.3.3.1.1)是比用户定义的转换更好的转换序列序列或省略号转换序列

指向成员转换的指针是标准转换序列。0是一个空指针常量,可以转换为指向成员的指针。[conv.mem]/p1:

空指针常量(4.10)可以转换为指向成员类型的指针;结果是null成员该类型的指针值,并且可以与任何指向非空指针创建的成员的指针区分开来常数这种转换称为空成员指针转换。

因此,第一过载是优选的。

13.3.2可行功能参数少于m的候选函数只有在其参数列表中有省略号时才可行(8.3.5)。为了解决过载问题,任何没有相应参数的参数都被视为"匹配省略号"(13.3.3.1.3)。

还有

可行功能给定如上所述构造的候选函数集,过载解决的下一步是检查自变量和参数,以将该集简化为可行函数集要包含在可行函数集中,候选函数必须满足以下条件:
1) 如果有M个参数,则恰好具有M个参数的候选函数是可行的
2) 如果候选函数的参数少于M个,但有省略号参数,则它是可行的
[…]
过载分辨率

空指针文字0应该与接受函数指针的函数完全匹配,并被视为比匹配任何内容都强(...)。