不同编译器使用的不同强制转换运算符 < >在我尝试的所有编译器中,以下C++程序编译时没有警告(GCC 4.63,LLVM 3,ICC 131.1,SoalISStudio 12.1/12.3): struct类 { 模板 运算符T()常量{return 1;} 运算符int()常量{return 2;} }; 内部主(空) { C类x; 返回静态_-cast(x); } 但是,除了SoaliStudio编译器返回2,SalARISStudio(任一版本)都返回1,我认为这是最合理的结果。p>
使用不同编译器使用的不同强制转换运算符 < >在我尝试的所有编译器中,以下C++程序编译时没有警告(GCC 4.63,LLVM 3,ICC 131.1,SoalISStudio 12.1/12.3): struct类 { 模板 运算符T()常量{return 1;} 运算符int()常量{return 2;} }; 内部主(空) { C类x; 返回静态_-cast(x); } 但是,除了SoaliStudio编译器返回2,SalARISStudio(任一版本)都返回1,我认为这是最合理的结果。p>,c++,templates,casting,operator-overloading,overload-resolution,C++,Templates,Casting,Operator Overloading,Overload Resolution,使用返回x.operator char()将导致所有编译器返回1 显然,自从弄明白这一点后,我一直在使用后一种符号。但是,我想知道哪种编译器是正确的,以及为什么。(有人会认为多数人占统治地位,但这仍然不能解释原因。) 这个问题似乎与SO问题有关,但这些“仅”给出了问题的解决方案,没有解释(我无论如何都能够应用于我的特定问题) 请注意,添加一个额外的重载强制转换操作符,例如操作符float()const{return 3;}会导致除SolarisStudio之外的所有编译器抱怨歧义。第一个是精确匹
返回x.operator char()
将导致所有编译器返回1
显然,自从弄明白这一点后,我一直在使用后一种符号。但是,我想知道哪种编译器是正确的,以及为什么。(有人会认为多数人占统治地位,但这仍然不能解释原因。)
这个问题似乎与SO问题有关,但这些“仅”给出了问题的解决方案,没有解释(我无论如何都能够应用于我的特定问题)
请注意,添加一个额外的重载强制转换操作符,例如
操作符float()const{return 3;}
会导致除SolarisStudio之外的所有编译器抱怨歧义。第一个是精确匹配,第二个需要转换。精确匹配优先于转换
你提到的其他问题大多与你的问题无关
一些建议:不要使用模板转换运算符。改为将其命名为convert\u
。应选择第一个(模板)重载
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
返回到目标类型的返回类型。[示例:
-结束示例]或,如果不是那样
-F1
是一个非模板函数,F2
是一个函数模板专用化,或者,如果不是这样
[……]
如您所见,第一个转换运算符是模板这一事实仅在标准转换序列从其返回类型(char
,在本例中)到目标类型(char
,在本例中)时才变得相关比从非模板重载的返回类型(int
,在本例中)到目标类型(char
,在本例中)的标准转换顺序要好
但是,从char
到char
的标准转换是完全匹配的,而从int
到char
的标准转换则不是。因此,§13.3.3/1第三项不适用,第二项不适用
这意味着应该选择刚刚在我的编译器G++4.8.0中测试的第一个(模板)重载,它返回1。G++4.7.2也返回1。对于
操作符float()
,没有关于任何歧义的抱怨。g++返回一个从4.7开始的值。这是一个糟糕的代码。避免使用一般(非专业或不受限制的[例如,通过std::enable_if
)模板转换运算符,因为这些运算符可能导致不需要的和未预见的转换。+1用于警告模板转换运算符。也许你可以解释一下为什么这是危险的,不是真的。它说模板专门化将被选中。但在op的例子中,没有专门化。编译器甚至不会开始创建模板,因为它已经找到了可以使用的匹配非模板强制转换。只有显式调用模板,或者没有其他匹配重载时,才会创建模板。编译器没有理由开始“猜测”匹配项template@YochaiTimmer:不,那不是真的。它不会实例化模板,但会执行模板参数推断,并查看模板是否是重载解析的可行候选模板。如果这是最可行的候选方案,它将选择并实例化它
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);
}
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