考えられる定義は次のstd::swap
とおりです。
template<class T>
void swap(T& a, T& b) {
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
私は信じている
std::swap(v,v)
効果がないことが保証されており、std::swap
上記のように実装できます。
次の引用は、これらの信念が矛盾していることを暗示しているように私には思えます。
17.6.4.9関数の引数[res.on.arguments]
1以下のそれぞれは、特に明記されていない限り、C++標準ライブラリで定義されている関数のすべての引数に適用されます。
..。
- 関数の引数が右辺値参照パラメーターにバインドする場合、実装は、このパラメーターがこの引数への一意の参照であると想定する場合があります。[注:パラメーターがT &&形式のジェネリックパラメーターであり、タイプAの左辺値がバインドされている場合、引数は左辺値参照(14.8.2.1)にバインドされるため、前の文ではカバーされません。— end note] [注:プログラムが左辺値をライブラリ関数に渡すときに左辺値をx値にキャストする場合(たとえば、引数move(x)を使用して関数を呼び出すことにより)、プログラムはその関数にその左辺値を処理するように効果的に要求します。一時的なものとして。実装は、引数が左辺値である場合に必要になる可能性のあるエイリアシングチェックを自由に最適化できます。—文末脚注]
(見積もりを提供してくれたHoward Hinnantに感謝します)
標準v
テンプレートライブラリから取得したいくつかの移動可能なタイプのオブジェクトであり、呼び出しを検討しますstd::swap(v, v)
。上記の行a = std::move(b);
では、その内部のケースでT::operator=(T&& t)
あるthis == &b
ため、パラメーターは一意の参照ではありません。これは上記の要件に違反しているため、a = std::move(b)
から呼び出されたときに行は未定義の動作を呼び出しますstd::swap(v, v)
。
ここでの説明は何ですか?