具有多个功能和多个转换运算符的过载分辨率

Ang*_*tis 13 c++ overloading conversion-operator language-lawyer overload-resolution

考虑简单的代码:

#include<iostream>

struct A {
    operator double(){
        std::cout<<"Conversion function double chosen."<<std::endl;
        return 1.1;
    }
    operator char(){
        std::cout<<"Conversion function char chosen."<<std::endl;
        return 'a';
    }
} a;

void foo(int){}
void foo (char){}
int main() {
    foo(a);
}
Run Code Online (Sandbox Code Playgroud)

上面的代码工作正常,正如预期的gcc,clang和VC++选择的那样foo(char).

现在让我们稍微修改一下代码:

#include<iostream>

struct A {
    operator double(){
        std::cout<<"Conversion function double chosen."<<std::endl;
        return 1.1;
    }
    operator char(){
        std::cout<<"Conversion function char chosen."<<std::endl;
        return 'a';
    }
} a;

void foo(int){}
void foo (double){} //parameter changed from char to double
int main() {
    foo(a);
}
Run Code Online (Sandbox Code Playgroud)

现在应该选择foo(double),但似乎只有VC++对代码感到满意,而clang和gcc对上面的代码不满意.

main.cpp:11:10: error: call of overloaded 'foo(A&)' is ambiguous
 foo(a);
     ^
main.cpp:8:6: note: candidate: void foo(int)
 void foo(int){}
      ^
main.cpp:9:6: note: candidate: void foo(double)
 void foo (double){} //parameter changed from char to double
      ^
Run Code Online (Sandbox Code Playgroud)

谁有人解释为什么上面的代码失败?还是它的错误?

还有一个问题:gcc和clang是否共享重载解析代码?

T.C*_*.C. 5

A -> char是A -> char.

A -> int 是A -> char -> int(因为char要int为一个促销等摔打double来int转换).

A -> double是A -> double.

两个用户定义的转换序列只有在涉及相同的用户定义转换函数时才具有可比性.因此,A -> char转换序列比转换顺序更好A -> int,因此您的第一种情况是明确的.既不是A -> int也不A -> double比另一个好,所以第二种情况是模棱两可的.


Col*_*mbo 5

TL;DR:区别在于,在第一种情况下,与第二种情况相反,用户定义的转换序列 ( A -> char, A -> int) 调用相同的转换函数 ( operator char)。这使我们能够通过 [over.ics.rank]/(3.3) 打破平局。

\n\n
\n\n

特定函数的最佳转换运算符通过 [over.match.best]/(1.4)选择(比较其返回类型的转换序列)。

\n\n

因此,更好的转换函数 后面跟着的foo(int)是operator char提升到int,而不是operator double后面跟着浮点转换。

\n\n

现在考虑第二个重载的两种变体:

\n\n
    \n
  1. 最好的 ICSfoo(char)也是viaoperator char(比浮点转换更好的恒等式)。因此[over.ics.rank]/(3.3)适用:

    \n\n
    \n

    如果用户定义的转换序列U1包含U2 相同的用户定义的转换函数[\xe2\x80\xa6],并且在任何一种情况下,第二个标准转换序列都优于第二个,则用户定义的转换序列是比另一个用户定义的转换序列U1更好的转换序列标准转换顺序U2。

    \n
    \n\n

    因此,整体转换为F2被认为更好,并且被选择。

  2. \n
  3. 最好的 ICSfoo(double)是通过operator double. 我们最终得到两个使用不同转换函数的转换序列;没有任何东西真正适用,我们只是得到了模糊性。

  4. \n
\n