Namespaces
Variants

C++ named requirements: Swappable

From cppreference.net
C++ named requirements

Toute lvalue ou rvalue de ce type peut être échangée avec toute lvalue ou rvalue d'un autre type, en utilisant l'appel de fonction non qualifié swap ( ) dans le contexte où à la fois std::swap et les swap ( ) définis par l'utilisateur sont visibles.

Table des matières

Exigences

Le type U est échangeable avec le type T si, pour tout objet u de type U et tout objet t de type T,

Expression Exigences Sémantique
#include <algorithm> // until C++11

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

Après l'appel, la valeur de t est la valeur détenue par u avant l'appel, et la valeur de u est la valeur détenue par t avant l'appel. Appelle la fonction nommée swap ( ) trouvée par résolution de surcharge parmi toutes les fonctions de ce nom trouvées par recherche dépendante des arguments et les deux modèles std::swap définis dans l'en-tête <algorithm> (jusqu'à C++11) <utility> (depuis C++11) .
#include <algorithm> // until C++11

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

Identique Identique

De nombreuses fonctions de la bibliothèque standard (par exemple, de nombreux algorithmes) attendent que leurs arguments satisfassent la condition Swappable , ce qui signifie qu'à chaque fois que la bibliothèque standard effectue un swap, elle utilise l'équivalent de using std:: swap ; swap ( t, u ) ; .

Les implémentations typiques soit

1) Définissez un swap non-membre dans l'espace de noms englobant, qui peut rediriger vers un swap membre si l'accès aux membres de données non publics est nécessaire.
2) Définissez une friend function dans la classe (cette approche masque le swap spécifique à la classe de la recherche de nom autre que ADL).

Notes

Il n'est pas spécifié si <algorithm> (jusqu'en C++11) <utility> (depuis C++11) est effectivement inclus lorsque les fonctions de la bibliothèque standard effectuent l'échange, donc la fonction swap ( ) fournie par l'utilisateur ne devrait pas s'attendre à ce qu'elle soit incluse.

Exemple

#include <iostream>
#include <vector>
struct IntVector
{
    std::vector<int> v;
    IntVector& operator=(IntVector) = delete; // non assignable
    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); // Erreur de compilation ! std::swap nécessite MoveAssignable
    prn();
    std::iter_swap(&v1, &v2); // OK : la bibliothèque appelle swap() non qualifié
    prn();
    std::ranges::swap(v1, v2); // OK : la bibliothèque appelle swap() non qualifié
    prn();
}

Sortie :

v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
v1{{2222, 2222}}, v2{{1, 1, 1, 1}};
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
LWG 226 C++98 il n'était pas clair comment la bibliothèque standard utilise swap clarifié pour utiliser à la fois std:: et swap trouvé par ADL

Voir aussi

vérifie si les objets d'un type peuvent être échangés avec des objets du même type ou d'un type différent
(modèle de classe)
spécifie qu'un type peut être échangé ou que deux types peuvent être échangés l'un avec l'autre
(concept)