1

这让我彻底糊涂了。在下面的示例中,我收到错误:

错误 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)并将 const 删除,void swap(one& other)一切正常。如果我更改签名void swap(const one& other)并删除 const ,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 中有效

4

3 回答 3

2
// 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); }
于 2013-01-23T18:05:23.200 回答
2

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

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是 const 限定的,但std::unique_ptr::swap需要一个非常量参数。因此,“转换丢失限定符”(特别是 const 限定符)。

于 2013-01-23T18:05:31.470 回答
1

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

所以你的swap函数必须采用非常量引用。

请注意,std::unique_ptr<T>它没有swap采用右值引用的功能。事实上,拥有一个甚至没有多大意义。VS2010 在这方面是非标准的。标准(§20.7.1.2)只需要一个带有这个签名的:

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

没有swap右值引用。我还建议您删除需要右值引用的交换。它为您的代码增加了不必要的复杂性。

于 2013-01-23T18:07:48.660 回答