名前付き要件: Swappable
提供: cppreference.com
(cpp/concept/Swappableから転送)
この型の任意の左辺値または右辺値は、 std::swap とユーザ定義の swap() の両方が可視な分脈において、非修飾の関数呼び出し swap() を使用して、何らかの別の型の任意の左辺値または右辺値とスワップすることができます。
要件
型 U の任意のオブジェクト u および型 T の任意のオブジェクト t について、以下の内容を満たす場合、型 U は型 T とスワップ可能です。
| 式 | 要件 | セマンティクス |
|---|---|---|
#include <utility> using std::swap; swap(u, t);
|
呼び出しの後、 t の値は呼び出し前に u が保持していた値となり、 u の値は呼び出し前に t が保持していた値となる。
|
実引数依存の名前探索およびヘッダ <utility> で定義されている2つの std::swap テンプレートによって見つかった swap という名前を持つすべての関数に渡るオーバーロード解決によって見つかった swap 関数を呼びます。
|
#include <utility> using std::swap; swap(t, u);
|
同上。 | 同上。 |
多くの標準ライブラリの関数 (例えば多くのアルゴリズム) は、その引数が Swappable であることを期待します。 これは、標準ライブラリが swap を行うときは using std::swap; swap(t, u); と同等のコードを使用することを意味します。
一般的な実装は、以下のいずれかです。
1) 囲っている名前空間で非メンバの swap を定義します。 非パブリックデータメンバへのアクセスが必要な場合はメンバの swap に転送するかもしれません。
2) クラス内フレンド関数を定義する (この手法は ADL 以外の名前探索からクラス固有の swap を隠蔽します)。
ノート
標準ライブラリの関数が swap を行うとき、 <utility> が実際にインクルードされるかどうかは未規定です。 そのためユーザ提供の swap() はそれがインクルードされていると期待するべきではありません。
例
Run this code
#include <iostream>
#include <vector>
class IntVector {
std::vector<int> v;
IntVector& operator=(IntVector) = delete; // 代入可能でない。
public:
void swap(IntVector& other) {
v.swap(other.v);
}
};
void swap(IntVector& v1, IntVector& v2) {
v1.swap(v2);
}
int main()
{
IntVector v1, v2;
// std::swap(v1, v2); // コンパイルエラー。 std::swap は MoveAssignable を要求します。
std::iter_swap(&v1, &v2); // OK、ライブラリは非修飾の swap() を呼びます。
}
関連項目
(C++17)(C++17)(C++17)(C++17) |
その型のオブジェクトが同じ型または何らかの別の型のオブジェクトと swap 可能かどうか調べます (クラステンプレート) |