带引用限定符的转换运算符:右值引用与const左值引用重载歧义
转换运算符与引用限定符的重载歧义问题
在研究转换运算符结合引用限定符的使用时,发现了一个特殊现象:
存在歧义的代码示例
using P = std::unique_ptr<int>; struct A { P p; operator P() && { return std::move(p); } operator P const&() const& { return p; } }; int main() { A a; P p; p = std::move(a); }
这段代码无法编译,原因是选择转换运算符重载时存在歧义。
可正常编译的修改方案
- 移除第二个重载的
const限定符,修改后代码可正常编译:operator P const&() & { return p; } - 不使用赋值操作,直接构造
P对象,代码也能正常运行:P p = std::move(a);
普通成员函数的对比情况
若改用实现相同功能的普通成员函数,编译完全正常,无歧义:
struct B { P p; P get() && { return std::move(p); } P const& get() const& { return p; } }; int main() { B b; P p; p = std::move(b).get(); }
核心疑问
转换运算符有何特殊之处,会导致上述重载出现歧义,而普通成员函数却不会?
附注
- 将
std::unique_ptr<int>替换为自定义不可拷贝类型,情况并无变化:struct P { P() = default; P(P const&) = delete; P(P&&) = default; P& operator=(P const&) = delete; P& operator=(P&&) = default; }; - MSVC的特殊表现:未提示歧义,仅选择错误的重载;但使用自定义不可拷贝类型时,会判定调用存在歧义。推测这与
std::unique_ptr::operator=有关,若有了解原因的,欢迎解答。
内容的提问来源于stack exchange,提问作者Nelfeal
相关产品推荐
相关产品推荐

