std:: exchange
|
Definido en el encabezado
<utility>
|
||
|
template
<
class
T,
class
U
=
T
>
T exchange ( T & obj, U && new_value ) ; |
(desde C++14)
(constexpr desde C++20) (condicionalmente noexcept desde C++23) |
|
Reemplaza el valor de obj con new_value y devuelve el valor anterior de obj .
Contenidos |
Parámetros
| obj | - | objeto cuyo valor reemplazar |
| new_value | - | el valor a asignar a obj |
| Requisitos de tipo | ||
-
T
debe cumplir con los requisitos de
MoveConstructible
. Además, debe ser posible asignar por movimiento objetos de tipo
U
a objetos de tipo
T
.
|
||
Valor de retorno
El valor antiguo de obj .
Excepciones
|
(ninguno) |
(hasta C++23) |
|
noexcept
especificación:
noexcept
(
std::
is_nothrow_move_constructible_v
<
T
>
&&
|
(desde C++23) |
Implementación posible
template<class T, class U = T> constexpr // Desde C++20 T exchange(T& obj, U&& new_value) noexcept( // Desde 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; } |
Notas
std::exchange
puede utilizarse al implementar
move constructors
y, para los miembros que no requieren
special cleanup
,
move assignment operators
:
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); // Mover n, dejando cero en other.n // Nota: en caso de auto-asignación de movimiento, n permanece sin cambios // También nota: si n es un identificador de recurso opaco que requiere // limpieza especial, el recurso tiene una fuga. return *this; } };
| Macro de prueba de características | Valor | Std | Característica |
|---|---|---|---|
__cpp_lib_exchange_function
|
201304L
|
(C++14) |
std::exchange
|
Ejemplo
#include <iostream> #include <iterator> #include <utility> #include <vector> class stream { public: using flags_type = int; public: flags_type flags() const { return flags_; } // Reemplaza flags_ por newf, y devuelve el valor anterior. 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; // Dado que el segundo parámetro de plantilla tiene un valor por defecto, es posible // usar una lista de inicialización entre llaves como segundo argumento. La expresión a continuación // es equivalente a 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)(); // El valor por defecto del parámetro de plantilla también hace posible usar una // función normal como segundo argumento. La expresión a continuación es equivalente a // std::exchange(fun, static_cast<void(*)()>(f)) std::exchange(fun, f); fun(); std::cout << "\n\nSecuencia de Fibonacci: "; for (int a{0}, b{1}; a < 100; a = std::exchange(b, a + b)) std::cout << a << ", "; std::cout << "...\n"; }
Salida:
0 0 12 1, 2, 3, 4, f() Secuencia de Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
Véase también
|
intercambia los valores de dos objetos
(plantilla de función) |
|
|
(C++11)
(C++11)
|
reemplaza atómicamente el valor del objeto atómico con argumento no atómico y devuelve el valor anterior del atómico
(plantilla de función) |