C++转换运算符选择:转值和同类型const引用时哪款编译器正确?
结论
GCC的行为符合C++标准规定,Clang和MSVC的处理属于实现偏差。
核心逻辑分析
我们要通过A类型左值a构造B类型对象b,这一步会触发B的构造函数重载决议,候选的构造函数有两个:
- 拷贝构造函数
B(const B&):接收const左值引用参数 - 移动构造函数
B(B&&):接收右值引用参数
接下来需要判断从A左值到两个构造函数入参的转换路径是否存在优先级差异:
- 走
operator B()路径:A左值先调用转换函数得到B类型纯右值,该纯右值可以绑定到移动构造的B&&参数,也可以绑定到拷贝构造的const B&参数 - 走
operator const B&()路径:A左值先调用转换函数得到const B&左值引用,该引用只能绑定到拷贝构造的const B&参数,无法绑定到移动构造的B&&参数
按照C++标准的重载决议规则,用户定义转换的优先级判定中,上述两条可行转换路径的排名完全相同,没有任何一条路径比另一条更优,因此属于转换歧义,编译器理应报错。
示例代码
#include <iostream> struct B {}; static B sb; struct A { operator B() { std::cout << "operator B() "; return sb; } operator const B &() { std::cout << "operator const B &() "; return sb; } }; int main() { A a; [[maybe_unused]] B b(a); }
GCC对应报错信息
<source>:13:27: error: call of overloaded 'B(A&)' is ambiguous 13 | [[maybe_unused]] B b(a); | ^ <source>:3:8: note: candidate: 'constexpr B::B(const B&)' 3 | struct B {}; | ^ <source>:3:8: note: candidate: 'constexpr B::B(B&&)'
内容的提问来源于stack exchange,提问作者Fedor。
相关产品推荐
相关产品推荐

