我试图理解过载解析.
首先让我们考虑第一种情况:
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
不含糊. Why?
现在考虑第二种情况,它非常相似,我只是替换了int&
by 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 至 5.0)、MSVC 19 2017 RTW、Zapcc 190308(Clang 衍生品)、ellcc(0.1.33、0.1.34)(Clang 衍生品)=> 调用
g
is 模糊的;
- GCC(4.8.1 至 7.2)、icc(16 至 18)=> 调用
g
is 不含糊.
什么是正确的分析以及哪个编译器是正确的?
您能否具体说明为什么以下规则不适用,或者何时适用?
[over.best.ics]/10:
如果存在多个不同的转换序列,每个序列都将参数转换为参数类型,则
与参数关联的隐式转换序列被定义为唯一的转换序列
指定了
不明确的转换序列
。为了将隐式转换序列排序为
如16.3.3.2所述,不明确的转换序列被视为用户定义的转换序列
这与任何其他用户定义的转换序列没有区别
这两个例子都是更简单的基本概念的更复杂的表示:
void f(int& ); // #1
void f(int const& ); // #2
void g(int&& ); // #3
void g(int const& ); // #4
int i;
f(i); // calls #1
g(0); // calls #3
对于第一次通话,我们赞成less cv-合格类型 http://eel.is/c++draft/over#ics.rank-3.2.6, so int&
比int const&
。对于第二次通话,我们赞成绑定到右值引用 http://eel.is/c++draft/over#ics.rank-3.2.3过度绑定到左值引用,所以int&&
比int const&
.
在特定示例中,这些偏好通过隐式对象参数使用的转换函数的选择来体现。对于第一个示例,因为我们将隐式对象参数绑定到int1&
用于转换为int&
, but int1 const&
用于转换为int const&
。同样,在第二个示例中,我们将隐式对象参数绑定到int2&&
用于转换为int&&
, but int2 const&
用于转换为int const&
.
我称其为 clang bug。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)