Requisitos denominados de C++: Swappable
De cppreference.com
Cualquier lvalue o rvalue de este tipo puede intercambiarse con cualquier lvalue o rvalue de algún otro tipo, usando una llamada a la función swap() no calificada en el contexto donde tanto std::swap como los swap()s definidos por el usuario son visibles.
Requisitos
Un tipo U es intercambiable con un tipo T si, para cualquier objeto u de tipo U y cualquier objeto t de tipo T,
| Expresión | Requisitos | Semántica |
|---|---|---|
#include <algorithm> // hasta C++11 #include <utility> // desde C++11 using std::swap; swap(u, t);
|
Después de la llamada, el valor de t es el valor mantenido por u antes de la llamada, y el valor de u es el valor mantenido por t antes de la llamada.
|
Llama a la función denominada swap() encontrada mediante la resolución de sobrecarga entre todas las funciones con ese nombre que se encuentran mediante la búsqueda dependiente de argumento y las dos plantillas std::swap definidas en el archivo de encabezado <algorithm> (hasta C++11)<utility> (desde C++11).
|
#include <algorithm> // hasta C++11 #include <utility> // desde C++11 using std::swap; swap(t, u);
|
Los mismos | La misma |
Varias funciones de la biblioteca estándar (por ejemplo, varios algoritmos) esperan que sus argumentos satisfagan a Swappable, lo que significa que en cualquier ocasión en que la biblioteca estándar realiza un intercambio, utiliza el equivalente a usar using std::swap; swap(t, u);.
Implementaciones típicas
1) Definen una función no miembro swap en el espacio de nombres circundante, que puede redirigirse a una función miembro swap si se requiere acceder a miembros de datos que no son públicos.
2) Definen una función amiga dentro de la clase (este enfoque oculta la función miembro swap específica de la clase de una búsqueda de nombre distinta de la búsqueda dependiente de argumento).
Notas
No está especificado si <algorithm> (hasta C++11)<utility> (desde C++11) se incluye realemente cuando las funciones de la biblioteca estándar realizan el intercambio, de tal manera que la función swap() proporcionada por el usuario no debe esperar que se incluya.
Ejemplo
#include <iostream> #include <vector> struct IntVector { std::vector<int> v; IntVector& operator=(IntVector) = delete; // no es asignable void swap(IntVector& otro) { v.swap(otro.v); } void operator()(auto rem, auto term = " ") { std::cout << rem << "{{"; for (int n{}; int e : v) std::cout << (n++ ? ", " : "") << e; std::cout << "}}" << term; } }; void swap(IntVector& v1, IntVector& v2) { v1.swap(v2); } int main() { IntVector v1{{1, 1, 1, 1}}, v2{{2222, 2222}}; auto prn = [&]{ v1("v1", ", "), v2("v2", ";\n"); }; // std::swap(v1, v2); // Error de compilación. std::swap requiere MoveAssignable prn(); std::iter_swap(&v1, &v2); // Correcto: la biblioteca llama a swap() sin calificar prn(); std::ranges::swap(v1, v2); // Correcto: la biblioteca llama a swap() sin calificar prn(); }
Salida:
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
v1{{2222, 2222}}, v2{{1, 1, 1, 1}};
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
| ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 226 | C++98 | no estaba claro cómo la biblioteca estándar utiliza swap
|
Se aclaró el uso tanto de std:: como la búsqueda ADL de swap
|