14

以下 C++ 程序在我尝试过的所有编译器(gcc 4.6.3、llvm 3.0、icc 13.1.1、SolarisStudio 12.1/12.3)中编译时没有警告:

struct CClass
{
  template<class T>
  operator T() const { return 1; }

  operator int() const { return 2; }
};

int main(void)
{
  CClass x;
  return static_cast<char>(x);
}

但是,除了 SolarisStudio 编译器之外的所有编译器都返回 2,SolarisStudio(任一版本)都返回 1,我认为这是最合乎逻辑的结果。

return x.operator char();在所有返回 1 的编译器中使用结果。

显然,自从弄清楚这一点以来,我一直在使用后一种表示法。但是,我想知道哪个编译器是正确的以及为什么。(有人会认为多数人规则,但这仍然不能解释为什么。)

这个问题似乎与此处此处此处的 SO 问题有关,但这些“仅”给出了问题的解决方案,没有任何解释(无论如何我都能够应用于我的特定问题)。

请注意,添加一个额外的重载强制转换运算符会operator float() const { return 3; }导致除 SolarisStudio 之外的所有编译器都抱怨歧义。

4

2 回答 2

9

应该选择第一个(模板)重载

C++11 标准的第 13.3.3/1 段规定:

[...] 一个可行函数F1被定义为比另一个可行函数更好的函数, F2如果对于所有参数iICSi(F1)不是比 , 更差的转换序列ICSi(F2),然后

— 对于某些论点j,ICSj(F1)是比 , 更好的转换序列ICSj(F2), 或者, 如果不是,

上下文是通过用户定义的转换(参见 8.5、13.3.1.5 和 13.3.1.6)进行的初始化,从返回类型到目标类型(即,正在初始化的实体的类型)的标准转换序列F1是从 的 返回 类型F2到 目标 类型的 标准 转换 序列 更好 的 转换 序列. [示例

struct A {
    A();
    operator int();
    operator double();
} a;
int i = a; // a.operator int() followed by no conversion
           // is better than a.operator double() followed by
           // a conversion to int
float x = a; // ambiguous: both possibilities require conversions,
             // and neither is better than the other

—<em>结束示例] 或者,如果不是

F1是一个非模板函数并且F2是一个函数模板特化,或者,如果不是,

[...]

如您所见,第一个转换运算符是模板的事实仅在从其返回类型(char在本例中)到目标类型(char在本例中)的标准转换序列优于标准转换时才相关从非模板重载的返回类型(int在本例中为 )到目标类型(char在本例中为 )的序列。

但是,从charto的标准转换charExact Match,而从intto的标准转换char不是。因此,第 13.3.3/1 节的第三项不适用,第二项适用。

这意味着应该选择第一个(模板)重载

于 2013-05-19T14:59:18.853 回答
5

第一个是完全匹配,第二个需要转换。完全匹配优先于转换。

您链接的其他问题大多与您的问题无关。

一些建议:不要使用模板转换运算符。convert_to改为命名。

于 2013-05-19T14:49:20.363 回答