std::swap
From cppreference.com
| ヘッダー <algorithm> で定義 |
(C++11まで) |
|
| ヘッダ <utility> で定義 |
(C++11以降) |
|
| ヘッダ <string_view> で定義 |
||
| template< class T > void swap( T& a, T& b ); |
(1) | (C++11 以降、条件付きで noexcept) (C++20 以降 constexpr) |
| template< class T2, std::size_t N > void swap( T2 (&a)[N], T2 (&b)[N] ); |
(2) | (C++11 以降、条件付きで noexcept) (C++20 以降 constexpr) |
指定された値を交換します。
1) a と b の値を入れ替えます。
|
このオーバーロードは、std::is_move_constructible_v<T> && std::is_move_assignable_v<T> が true の場合にのみオーバーロード解決に参加します。 |
(C++17以降) |
2) 配列 a と b を交換します。std::swap_ranges(a, a + N, b) と同等です。
|
このオーバーロードは、std::is_swappable_v<T2> が true の場合にのみオーバーロード解決に参加します。 |
(C++17以降) |
目次 |
[編集] パラメータ
| a, b | - | 交換する値 |
| 型要件 | ||
-T は CopyConstructible および CopyAssignable(C++11 まで)MoveConstructible および MoveAssignable(C++11 以降) の要件を満たしている必要があります。 | ||
-T2 は Swappable の要件を満たしている必要があります。 | ||
[編集] 戻り値
(なし)
[編集] 例外
1)
|
(なし) |
(C++11まで) |
|
noexcept 指定:
noexcept( std::is_nothrow_move_constructible<T>::value && |
(C++11以降) |
2)
|
noexcept 指定: 例外指定の識別子 noexcept(noexcept(swap(*a, *b))) swap のルックアップは、通常のルックアップ規則で見つかったものに加えてこの関数テンプレートを見つけ、例外指定を C++17 の std::is_nothrow_swappable と同等にします。 |
(C++11以降) (C++17まで) |
|
noexcept 指定:
noexcept(std::is_nothrow_swappable_v<T2>) |
(C++17以降) |
[編集] 計算量
1) 定数時間。
2) N に対して線形時間。
[編集] 特殊化
|
|
(C++20まで) |
プログラム定義型をスワップ可能にするための期待される方法は、その型と同じ名前空間に非メンバ関数 swap を提供することです。詳細は Swappable を参照してください。
以下のオーバーロードはすでに標準ライブラリによって提供されています
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| std::swap アルゴリズムを特殊化します (function template) | |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| (C++11) |
std::swap アルゴリズムを特殊化します (function template) |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (function template) | |
| std::swap アルゴリズムを特殊化します (function template) | |
| std::swap アルゴリズムを特殊化します (function template) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| (C++11) |
std::swap アルゴリズムを特殊化します (function) |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| (C++14) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| (C++11) |
std::swap アルゴリズムを特殊化します (関数テンプレート) |
| std::swap アルゴリズムを特殊化します (関数テンプレート) | |
| (C++17) |
std::swap アルゴリズムを特殊化します (function template) |
| (C++17) |
std::swap アルゴリズムを特殊化します (関数) |
| (C++17) |
std::swap アルゴリズムを特殊化します (function template) |
| std::swap アルゴリズムを特殊化します (function template) | |
| (C++17) |
std::swap アルゴリズムを特殊化します (関数) |
| (C++23) |
std::swap アルゴリズムを特殊化します (function) |
| (C++20) |
std::swap アルゴリズムを特殊化します (function) |
| std::swap アルゴリズムを特殊化します (関数) | |
| (C++20) |
std::swap アルゴリズムを特殊化します (関数) |
| (C++20) |
std::swap アルゴリズムを特殊化します (関数) |
[編集] 例
このコードを実行
#include <algorithm> #include <iostream> namespace Ns { class A { int id {}; friend void swap(A& lhs, A& rhs) { std::cout << "swap(" << lhs << ", " << rhs << ")\n"; std::swap(lhs.id, rhs.id); } friend std::ostream& operator<<(std::ostream& os, A const& a) { return os << "A::id=" << a.id; } public: A(int i) : id {i} {} A(A const&) = delete; A& operator = (A const&) = delete; }; } int main() { int a = 5, b = 3; std::cout << a << ' ' << b << '\n'; std::swap(a, b); std::cout << a << ' ' << b << '\n'; Ns::A p {6}, q {9}; std::cout << p << ' ' << q << '\n'; // std::swap(p, q); // error, type requirements are not satisfied swap(p, q); // OK, ADL finds the appropriate friend `swap` std::cout << p << ' ' << q << '\n'; }
出力
5 3 3 5 A::id=6 A::id=9 swap(A::id=6, A::id=9) A::id=9 A::id=6
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 227 | C++98 | T が CopyConstructible または DefaultConstructible である必要はなかった(型 T の一時オブジェクトを構築できない可能性がある) |
T は以下も要求されるCopyConstructible であること |
| LWG 809 | C++98 | 配列をスワップできなかった | オーバーロード (2) を追加 |
| LWG 2554 | C++11 | 多次元配列のスワップは決して 名前ルックアップの問題により noexcept にならない |
動作するように修正 |
[編集] 関連項目
| (C++20) |
2つのオブジェクトの値を交換する (カスタマイゼーションポイントオブジェクト) |
| 2つのイテレータが指す要素をスワップする (関数テンプレート) | |
| 2つの要素の範囲を交換する (関数テンプレート) | |
| (C++14) |
引数を新しい値で置き換え、その前の値を返す (関数テンプレート) |