【发布时间】:2020-02-29 13:44:22
【问题描述】:
在将常量引用作为成员的类中使用 copy-and-swap idiom 时, 出现上述错误。
示例代码:
#include <iostream>
#include <functional>
using std::reference_wrapper;
class I_hold_reference;
void swap(I_hold_reference& first, I_hold_reference& second);
class I_hold_reference{
inline I_hold_reference(const int& number_reference) : my_reference(number_reference){}
friend void swap(I_hold_reference& first, I_hold_reference& second);
inline I_hold_reference& operator=(I_hold_reference other){
swap(*this, other);
return *this;
}
inline I_hold_reference& operator=(I_hold_reference&& other){
swap(*this, other);
return *this;
}
private:
reference_wrapper<const int> my_reference;
};
void swap(I_hold_reference& first, I_hold_reference& second){
first = I_hold_reference(second.my_reference); //error: use of overloaded operator '=' is ambiguous (with operand types 'I_hold_reference' and 'I_hold_reference')
}
当复制赋值运算符被更改为通过引用而不是按值获取其参数时,该错误已得到修复。
inline I_hold_reference& operator=(I_hold_reference& other){ ... }
为什么这可以修复错误? 一种可能的暗示是链接问题中引用的Important optimization possibility 丢失了。参考文献是这样吗? 这种变化的其他影响是什么?
有一个依赖此运算符的代码库,没有其他成员存在,只有提到的引用。是否需要以某种方式使代码库适应这种变化,或者它是否安全?
【问题讨论】:
-
您通常不(从不?)想要一个按值重载和一个带有右值引用的重载,因为这些在大多数情况下都是模棱两可的(总是?)。参见,例如,stackoverflow.com/questions/28701039/…
-
顺便说一句,这根本不是复制和交换的习惯用法……你基本上会在这里无限递归地运行。您不能在
operator=中使用swap和在交换中使用operator=。您希望您的交换实际执行交换。在你的情况下,交换的主体应该是std::swap(first.my_reference, second.my_reference)。 -
类定义中的成员函数定义隐含
inline。不是错误,但混乱会降低可读性。 -
成员的交换复制与类型无关。这与
void f(int); void f(int&&); int main{ f(1);}的情况相同(即同样“好”的重载)。
标签: c++ copy-and-swap pass-by-const-reference