std:: exchange
|
Definiert im Header
<utility>
|
||
|
template
<
class
T,
class
U
=
T
>
T exchange ( T & obj, U && new_value ) ; |
(seit C++14)
(constexpr seit C++20) (bedingt noexcept seit C++23) |
|
Ersetzt den Wert von obj durch new_value und gibt den alten Wert von obj zurück.
Inhaltsverzeichnis |
Parameter
| obj | - | Objekt, dessen Wert ersetzt werden soll |
| new_value | - | der Wert, der obj zugewiesen werden soll |
| Typanforderungen | ||
-
T
muss die Anforderungen von
MoveConstructible
erfüllen. Zudem muss es möglich sein, Objekte vom Typ
U
Objekten vom Typ
T
zuzuweisen.
|
||
Rückgabewert
Der alte Wert von obj .
Ausnahmen
|
(keine) |
(bis C++23) |
|
noexcept
Spezifikation:
noexcept
(
std::
is_nothrow_move_constructible_v
<
T
>
&&
|
(seit C++23) |
Mögliche Implementierung
template<class T, class U = T> constexpr // Seit C++20 T exchange(T& obj, U&& new_value) noexcept( // Seit C++23 std::is_nothrow_move_constructible<T>::value && std::is_nothrow_assignable<T&, U>::value ) { T old_value = std::move(obj); obj = std::forward<U>(new_value); return old_value; } |
Hinweise
std::exchange
kann bei der Implementierung von
Move-Konstruktoren
und, für Member, die keine
spezielle Bereinigung
benötigen,
Move-Zuweisungsoperatoren
verwendet werden:
struct S { int n; S(S&& other) noexcept : n{std::exchange(other.n, 0)} {} S& operator=(S&& other) noexcept { n = std::exchange(other.n, 0); // n verschieben, während other.n auf Null gesetzt wird // Hinweis: bei Selbstzuweisung bleibt n unverändert // Weiterer Hinweis: falls n ein undurchsichtiger Ressourcen-Handle ist, // der spezielle Bereinigung erfordert, wird die Ressource verworfen return *this; } };
| Feature-Test Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_exchange_function
|
201304L
|
(C++14) |
std::exchange
|
Beispiel
#include <iostream> #include <iterator> #include <utility> #include <vector> class stream { public: using flags_type = int; public: flags_type flags() const { return flags_; } // Ersetzt flags_ durch newf und gibt den alten Wert zurück. flags_type flags(flags_type newf) { return std::exchange(flags_, newf); } private: flags_type flags_ = 0; }; void f() { std::cout << "f()"; } int main() { stream s; std::cout << s.flags() << '\n'; std::cout << s.flags(12) << '\n'; std::cout << s.flags() << "\n\n"; std::vector<int> v; // Da der zweite Template-Parameter einen Standardwert hat, ist es möglich // eine geschweifte Initialisierungsliste als zweites Argument zu verwenden. Der Ausdruck unten // ist äquivalent zu std::exchange(v, std::vector<int>{1, 2, 3, 4}); std::exchange(v, {1, 2, 3, 4}); std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ", ")); std::cout << "\n\n"; void (*fun)(); // Der Standardwert des Template-Parameters ermöglicht es auch, eine // normale Funktion als zweites Argument zu verwenden. Der Ausdruck unten ist äquivalent zu // std::exchange(fun, static_cast<void(*)()>(f)) std::exchange(fun, f); fun(); std::cout << "\n\nFibonacci-Folge: "; for (int a{0}, b{1}; a < 100; a = std::exchange(b, a + b)) std::cout << a << ", "; std::cout << "...\n"; }
Ausgabe:
0 0 12 1, 2, 3, 4, f() Fibonacci-Folge: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
Siehe auch
|
tauscht die Werte zweier Objekte
(Funktions-Template) |
|
|
(C++11)
(C++11)
|
ersetzt atomar den Wert des atomaren Objekts mit nicht-atomarem Argument und gibt den alten Wert des atomaren Objekts zurück
(Funktions-Template) |