namespace std {
template <class T>
void swap(T& a, T& b); // (1) C++03 in <algorithm> header
template <class T>
void swap(T& a, T& b) noexcept(see below); // (1) C++11
template <class T>
constexpr void swap(T& a, T& b) noexcept(see below); // (1) C++20
template <class T, size_t N>
void swap(T (&a)[N], T (&b)[N])
noexcept(noexcept(swap(*a, *b))); // (2) C++11
template <class T, size_t N>
constexpr void swap(T (&a)[N], T (&b)[N])
noexcept(noexcept(swap(*a, *b))); // (2) C++20
}
概要
2つの値を入れ替える。
要件
- 値版:型
T
はMoveConstructible
かつMoveAssignable
でなければならない。 - 配列版:範囲
[0, N)
内の全てのi
において、a[i]
とb[i]
はSwappable
でなければならない。
効果
値版の振る舞いは、以下のコードと等価である:
template <class T>
void swap(T& a, T& b) {
T t = std::move(a);
a = std::move(b);
b = std::move(t);
}
配列版の振る舞いは、以下のコードと等価である:
template <class T, size_t N>
void swap(T (&a)[N], T (&b)[N]) {
for (std::size_t i = 0; i < N; ++i) {
swap(a[i], b[i]);
}
}
つまり、範囲[0, N)
内の全てのi
について、 swap(a[i], b[i]);
を呼び出す。
この関数の内部におけるswap()
呼び出しは、 std::swap(a[i], b[i]);
という形ではなく、 swap(a[i], b[i]);
という形で行われる。すなわち、T
型に対してオーバーロードされたswap()
関数がある場合には、常にそちらが呼ばれる。
そのため、swap()
関数を呼び出す場合は、直接std::swap(a, b);
と呼び出すのではなく、
using std::swap;
swap(a, b);
のように呼び出し、各クラスに対し個別に定義された swap がある場合には そちらが呼ばれるようにするべきである。
戻り値
なし
例外
- 値版:
noexcept
中の式は、以下と等価である:is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value
- 配列版:配列の要素型
T
に対するswap()
操作が例外を投げない場合、この関数もまた例外を投げない
備考
C++03では<algorithm>
ヘッダに定義されていた。
例
#include <iostream>
#include <utility>
template <class Array>
void print(const Array& ar)
{
std::cout << '[';
bool first = true;
for (auto x : ar) {
if (first) {
first = false;
}
else {
std::cout << ',';
}
std::cout << x;
}
std::cout << ']';
}
int main()
{
// 値版
{
int a = 1;
int b = 2;
using std::swap;
swap(a, b);
std::cout << a << ", " << b << std::endl;
}
// 配列版
{
int a[] = {1, 2, 3};
int b[] = {4, 5, 6};
using std::swap;
swap(a, b);
print(a);
std::cout << ", ";
print(b);
std::cout << std::endl;
}
}
48
std::cout << a << ", " << b << std::endl;
#include <iostream>
#include <utility>
template <class Array>
void print(const Array& ar)
{
std::cout << '[';
bool first = true;
for (auto x : ar) {
if (first) {
first = false;
}
else {
std::cout << ',';
}
std::cout << x;
}
std::cout << ']';
出力
2, 1
[4,5,6], [1,2,3]
バージョン
言語
- C++11
処理系
- Clang: ??
- GCC: 4.7.0 ✅
- ICC: ??
- Visual C++: 2012 ✅, 2013 ✅, 2015 ✅
- 値版はそれより前から実装されている。
関連項目
参照
- LWG Issue 809.
std::swap
should be overloaded for array types- C++11で、配列に対するオーバーロードが追加された経緯のレポート
- P0879R0 Constexpr for
swap
andswap
related functions