Namespaces
Variants

C++ named requirements: Swappable

From cppreference.net
C++ named requirements

Cualquier lvalue o rvalue de este tipo puede intercambiarse con cualquier lvalue o rvalue de algún otro tipo, usando la llamada de función no calificada swap ( ) en el contexto donde tanto std::swap como las funciones swap ( ) definidas por el usuario son visibles.

Contenidos

Requisitos

El tipo U es intercambiable con el tipo T si, para cualquier objeto u de tipo U y cualquier objeto t de tipo T,

Expresión Requisitos Semántica
#include <algorithm> // until C++11

#include <utility> // since C++11
using std:: swap ;
swap ( u, t ) ;

Después de la llamada, el valor de t es el valor contenido en u antes de la llamada, y el valor de u es el valor contenido en t antes de la llamada. Llama a la función llamada swap ( ) encontrada mediante resolución de sobrecarga entre todas las funciones con ese nombre que se encuentran mediante búsqueda dependiente de argumento y las dos plantillas std::swap definidas en el encabezado <algorithm> (until C++11) <utility> (since C++11) .
#include <algorithm> // until C++11

#include <utility> // since C++11
using std:: swap ;
swap ( t, u ) ;

Igual Igual

Muchas funciones de la biblioteca estándar (por ejemplo, muchos algoritmos) esperan que sus argumentos satisfagan Swappable , lo que significa que cada vez que la biblioteca estándar realiza un swap, utiliza el equivalente de using std:: swap ; swap ( t, u ) ; .

Las implementaciones típicas o bien

1) Defina un swap no miembro en el espacio de nombres envolvente, que puede reenviar a un swap miembro si se requiere acceso a miembros de datos no públicos.
2) Define una función friend dentro de la clase (este enfoque oculta el swap específico de la clase de la búsqueda de nombres excepto ADL).

Notas

No está especificado si <algorithm> (until C++11) <utility> (since C++11) es realmente incluido cuando las funciones de la biblioteca estándar realizan el swap, por lo que el swap ( ) proporcionado por el usuario no debería esperar que esté incluido.

Ejemplo

#include <iostream>
#include <vector>
struct IntVector
{
    std::vector<int> v;
    IntVector& operator=(IntVector) = delete; // no asignable
    void swap(IntVector& other)
    {
        v.swap(other.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 del compilador! std::swap requiere MoveAssignable
    prn();
    std::iter_swap(&v1, &v2); // OK: la biblioteca llama a swap() no calificada
    prn();
    std::ranges::swap(v1, v2); // OK: la biblioteca llama a swap() no calificada
    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 que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 226 C++98 no estaba claro cómo la biblioteca estándar utiliza swap aclarado para usar tanto std:: como swap encontrado por ADL

Véase también

verifica si objetos de un tipo pueden intercambiarse con objetos del mismo tipo o de diferente tipo
(plantilla de clase)
especifica que un tipo puede intercambiarse o que dos tipos pueden intercambiarse entre sí
(concepto)