在以常量引用作为成员的类中使用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丢失了。引用曾经是真的吗?
此更改还有哪些其他含义?

有一个依赖于此运算符的代码库,没有其他成员,只有提及的引用。是否需要以某种方式使代码库适应此更改,或者它是安全的吗?

最佳答案

如果仔细遵循链接的描述,您将看到operator=只能重载一次,并且需要按值接受其参数。因此,只需消除operator=(I_hold_reference&&)重载即可使您的代码可编译。

但是,这不是唯一的问题。您的swap不交换!而是将second的副本分配给first,并且保持second不变。

这就是你想要的:

class I_hold_reference
{
    I_hold_reference(const int& number_reference)
     : my_reference(number_reference){}

    friend void swap(I_hold_reference& first, I_hold_reference& second)
    {
        using std::swap;
        swap(first.my_reference, second.my_reference);
    }

    I_hold_reference& operator=(I_hold_reference other)
    {
        swap(*this, other);
        return *this;
    }
private:
    reference_wrapper<const int> my_reference;
};

注意:我删除了不必要的inline,因为成员函数是隐式内联的。我也在类中声明了swap函数。您可以在共享的链接中找到对此的解释。

同样,在此特定示例中,首先不需要使用 copy-and-swap 习惯。 std::reference_wrapper不是手动维护的资源,这意味着它具有适当的内置复制和移动语义。因此,在此特定示例中,编译器生成的复制和移动操作符将具有与此处手动创建的行为完全相同的行为。因此,您应该使用这些而不是以任何方式编写自己的。另一方面,如果这只是一个玩具示例,并且实际类中有更多资源需要手动管理,那么这就是要走的路。

关于c++ - 错误:使用 copy-and-swap 习惯的交换函数中 'operator='的模棱两可的重载,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58690089/

10-13 06:30