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); }

otherconst修飾されていstd::unique_ptr::swapますが、非const引数が必要です。したがって、「変換は修飾子を失います」(具体的には、const修飾子)。

于 2013-01-23T18:05:31.470 に答える
1

それは私にはかなり簡単に思えます。2つのオブジェクトを交換すると、いずれも読み取り専用になりません。両方とも変更可能である必要があります。そうしないと、スワップを実行できません。

したがって、swap関数は非定数参照を取得する必要があります。

右辺値参照をとる関数std::unique_ptr<T>がないことに注意してください。実際、それを持っていることはあまり意味がありません。VS2010はその点で非標準です。標準(§20.7.1.2)では、次の署名が1つだけ必要です。swap

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

swaprvalue-referenceはありません。また、右辺値参照をとるスワップを削除することをお勧めします。それはあなたのコードに不必要な複雑さを追加します。

于 2013-01-23T18:07:48.660 に答える