【发布时间】:2018-05-22 14:48:49
【问题描述】:
我正在尝试了解重载分辨率。
首先让我们考虑第一种情况:
struct int1{
int val;
operator int&()&{
return val;
}
operator const int &() const&{
return val;
}
};
void f(int &){} //f#1
void f(const int&){} //f#2
void test1(){
int1 x;
f(x);
//Conversion sequence for f#1:
// - int_wrapper& --> int1::operator int&
// => Ranking: user defined conversion rank
//Converison sequence for f#2:
// - int1& --> int1::operator int & --> const int&
// - int1& --> const int1 & --> int1::operator const int&
// => Ranking: ambiguous because 2 conversion sequence [over.best.ics]/10
// => user defined conversion rank
//
//=> No best viable overload, 2 user defined conversion rank
}
与我的错误分析不同,编译器同意:对f 的调用没有歧义。为什么?
现在考虑第二种情况,它非常相似,我只是将int& 替换为int &&:
struct int2{
int val;
operator int&&()&&{
return std::move(val);
}
operator const int &() const&{
return val;
}
};
void g(int &&){} // g#1
void g(const int&){} // g#2
void test2(){
int2 x;
g(std::move(x));
//Conversions sequence for g#1
// - int2&& --> int2::operator int&&
// => Ranking: user defined conversion rank
//Conversion sequence for g#2
// - int2&& --> const int2& --> int2::operator const int&
// - int2&& --> int2::operator int&& --> const int&
// => Ranking: ambiguous because 2 conversion sequence [over.best.ics]/10
// => user defined conversion rank
//
//=> No best viable overload, 2 user defined conversion rank
}
我的分析(在这种情况下也肯定是错误的)得出类似的结论,即对g 的调用是模棱两可的。不幸的是,在第二种情况下,编译器不同意:
- Clang (3.4.1 to 5.0), MSVC 19 2017 RTW, Zapcc 190308 (Clang derivate), ellcc (0.1.33, 0.1.34)(Clang derivate) => 对
g的调用是不明确的; - GCC(4.8.1 到 7.2)、icc(16 到 18)=> 对
g的调用没有歧义。
什么是正确的分析,哪个编译器是正确的?
您能否详细说明为什么以下规则不适用,或者何时适用?
[over.best.ics]/10:
如果存在多个不同的转换序列,每个序列都将实参转换为参数类型,则 与参数关联的隐式转换序列被定义为唯一的转换序列 指定的 模棱两可的转换序列 .为了将隐式转换序列排序为 在 16.3.3.2 中描述的模糊转换序列被视为用户定义的转换序列 这与任何其他用户定义的转换序列没有区别
【问题讨论】:
-
您应该提及您使用的编译器版本和命令行选项。
标签: c++ overloading language-lawyer