- utility[meta header]
- std[meta namespace]
- function template[meta id-type]
- cpp14[meta cpp]
namespace std {
template <class T, class U=T>
T exchange(T& obj, U&& new_val); // C++14
template <class T, class U=T>
constexpr T exchange(T& obj, U&& new_val); // C++20
}
値を書き換え、書き換え前の値を返す。
第1パラメータobj
で受け取った変数への参照に、第2パラメータnew_val
の値をムーブ代入し、代入前のobj
の状態を返す。
以下と等価の効果を持つ:
T old_val = std::move(obj);
obj = std::forward<U>(new_val);
return old_val;
- std::move[link move.md]
- std::forward[link forward.md]
この関数を呼び出す前の、第1パラメータobj
の状態を返す。
この関数は、std::atomic_exchange()
関数の経験から導入された。
#include <iostream>
#include <utility>
int main()
{
int state = 1;
int before = std::exchange(state, 2);
std::cout << "state : " << state << std::endl;
std::cout << "before : " << before << std::endl;
}
- std::exchange[color ff0000]
state : 2
before : 1
#include <iostream>
#include <utility>
#include <vector>
template <class T>
void print_1(const std::vector<T>& v)
{
// カンマ区切りでvectorを出力する。
// 区切り文字は、各要素の後ではなく、前に置くと考える。
// 最初の要素のみ区切り文字を出力しない。
bool first = true;
std::cout << '{';
for (const T& x : v) {
if (!std::exchange(first, false)) {
std::cout << ',';
}
std::cout << x;
}
std::cout << '}' << std::endl;
}
// 別な書き方
template <class T>
void print_2(const std::vector<T>& v)
{
const char* delimiter = "";
std::cout << '{';
for (const T& x : v) {
std::cout << std::exchange(delimiter, ",") << x;
}
std::cout << '}' << std::endl;
}
int main()
{
const std::vector<int> v = {1, 2, 3};
print_1(v);
print_2(v);
}
- std::exchange[color ff0000]
{1,2,3}
{1,2,3}
- C++14
- GCC, C++14 mode: 4.9.0
- Clang, C++14 mode: 3.4
- ICC: ??
- Visual C++: 2015