为什么我的交换方法会干扰make_move_iterator

Why is my swap method interfering with make_move_iterator?

本文关键字:make move iterator 干扰 我的 交换 方法 为什么      更新时间:2023-10-16

这个让我彻底困惑。在下面的示例中,我收到错误:

错误 C2664: 'void std::unique_ptr<_Ty>::swap(std::unique_ptr<_Ty> &&)' :无法将参数 1 从"const std::unique_ptr<_Ty>"转换为 'std::unique_ptr<_Ty> &&'

我不知道它是如何在我的交换功能上结束的,或者为什么它是一个问题。有趣的是,如果我更改void swap(const one& other)的签名并删除常量以void swap(one& other)一切正常。如果我更改void swap(const one& other)的签名并删除常量以void swap(one& other)它在VS2010中编译,但在GCC中仍然被破坏。如果没有交换重载,则没有问题。

//-----------------------------------------------------------------------------
class one
{
public:
    one(){}
    one(one&& other) : x(std::move(other.x)) {}
    one& operator=(one&& other){ x = std::move(other.x); return *this; }
    void swap(const one& other){ x.swap(other.x); }
    void swap(one&& other){ x.swap(std::move(other.x)); }
private:
    one(const one&);
    one& operator=(const one&);
    std::unique_ptr<int> x;
};
//-----------------------------------------------------------------------------
void swap(one& left, one& right)
{
    left.swap(right);
}
//-----------------------------------------------------------------------------
void swap(one&& left, one& right)
{
    right.swap(std::move(left));
}
//-----------------------------------------------------------------------------
void swap(one& left, one&& right)
{
    left.swap(std::move(right));
}
//-----------------------------------------------------------------------------
class two
{
public:
    two(){}
    two(two&&){}
    two& operator=(two&&){ return *this; }
    operator one(){return one();}
private:
    two(const two&);
    two& operator=(const two&);
};
//-----------------------------------------------------------------------------
int main()
{
    std::vector<two> twos(10);
    std::vector<one> ones(std::make_move_iterator(twos.begin()), std::make_move_iterator(twos.end()));
}

编辑:非恒定性要求是有道理的。完全是我的疏忽。为什么它首先调用交换?

(作为参考,我使用的是VS2010)

它的演示坏了

它的演示仍然损坏,但此"修复"在VS2010中有效

// other can't be const since swap modifies it
void swap(one& other){ x.swap(other.x); }
// Why swapping? (swap on rvalues don't work either since it's pointless.)
//Just move the other
void swap(one&& other){ x = std::move(other.x); }

完整的错误消息如下(我引入了一些换行符来防止水平滚动):

error C2664: 'void std::unique_ptr<_Ty>::swap(std::unique_ptr<_Ty> &&)'
    : cannot convert parameter 1
        from 'const std::unique_ptr<_Ty>'
        to 'std::unique_ptr<_Ty> &&'
with
[
    _Ty=int
]
Conversion loses qualifiers

错误发生在代码的以下行上:

void swap(const one& other){ x.swap(other.x); }

other是常量限定的,但std::unique_ptr::swap需要一个非常量参数。 因此,"转换会失去限定符"(特别是常量限定符)。

这对我来说似乎很简单。交换两个对象时,它们都不是只读的。它们都应该是可修改的,只有这样才能进行交换。

因此,您的swap函数必须采用非常量引用。

请注意,std::unique_ptr<T>没有swap函数,该函数采用右值引用。事实上,拥有一个甚至没有多大意义。VS2010在这方面是非标准的。标准 (§20.7.1.2) 仅要求具有此签名:

void swap(std::unique_ptr<T> &) noexcept;

没有用于右值引用的swap。我还建议您删除采用右值引用的掉期。它增加了代码不必要的复杂性。