不同的编译器使用不同的强制转换操作符

Different casting operators used by different compilers

本文关键字:转换 操作符 编译器      更新时间:2023-10-16

以下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之外的所有编译器抱怨歧义。

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

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

[…可行函数F1被定义为优于另一个可行函数的函数F2如果对于所有参数i, ICSi(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

- ]或者结束,如果不是,

- F1是非模板函数,F2是函数模板专门化,或者,如果不是,

[…]

可以看到,只有当从返回类型(本例中为char)到目的类型(本例中为char)的标准转换序列不优于从非模板重载的返回类型(本例中为int)到目的类型(本例中为char)的标准转换序列时,第一个转换操作符是模板才有意义。

然而,从charchar的标准转换是精确匹配,而从intchar的标准转换不是。因此,§13.3.3/1的第三项不适用,而第二项适用。

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

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

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

一些建议:不要使用模板转换操作符。将其命名为convert_to