C++ benannte Anforderungen: Swappable
Jeder Lvalue oder Rvalue dieses Typs kann mit jedem Lvalue oder Rvalue eines anderen Typs vertauscht werden, unter Verwendung eines unqualifizierten Funktionsaufrufs swap() im Kontext, in dem sowohl std::swap als auch der benutzerdefinierte swap() sichtbar sind.
Inhalt |
[bearbeiten] Anforderungen
Typ U ist mit Typ T vertauschbar, wenn für jedes Objekt u vom Typ U und jedes Objekt t vom Typ T gilt:
| Ausdruck | Anforderungen | Semantik |
|---|---|---|
| #include <algorithm> // bis C++11 #include <utility> // seit C++11 |
Nach dem Aufruf ist der Wert von t der Wert, den u vor dem Aufruf enthielt, und der Wert von u ist der Wert, den t vor dem Aufruf enthielt. |
Ruft die Funktion mit dem Namen swap() auf, die durch Überladungsauflösung unter allen Funktionen mit diesem Namen gefunden wird, die durch argumentabhängige Suche gefunden werden, sowie die beiden std::swap-Vorlagen, die in der Header-Datei <algorithm>(bis C++11)<utility>(seit C++11) definiert sind. |
| #include <algorithm> // bis C++11 #include <utility> // seit C++11 |
Dasselbe | Dasselbe |
Viele Funktionen der Standardbibliothek (z. B. viele Algorithmen) erwarten, dass ihre Argumente Swappable erfüllen, was bedeutet, dass die Standardbibliothek immer dann, wenn sie einen Tausch durchführt, das Äquivalent von using std::swap; swap(t, u); verwendet.
Typische Implementierungen definieren entweder
[bearbeiten] Anmerkungen
Es ist nicht spezifiziert, ob <algorithm>(bis C++11)<utility>(seit C++11) tatsächlich eingebunden wird, wenn die Funktionen der Standardbibliothek den Tausch durchführen. Daher sollte die vom Benutzer bereitgestellte swap() nicht davon ausgehen, dass sie eingebunden ist.
[bearbeiten] Beispiel
#include <iostream> #include <vector> struct IntVector { std::vector<int> v; IntVector& operator=(IntVector) = delete; // not 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); // Compiler error! std::swap requires MoveAssignable prn(); std::iter_swap(&v1, &v2); // OK: library calls unqualified swap() prn(); std::ranges::swap(v1, v2); // OK: library calls unqualified swap() prn(); }
Ausgabe
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
v1{{2222, 2222}}, v2{{1, 1, 1, 1}};
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 226 | C++98 | Es war unklar, wie die Standardbibliothek swap verwendet |
klarstellung, dass sowohl std:: als auch ADL-gefundene swap verwendet werden |
[bearbeiten] Siehe auch
| (C++17)(C++17)(C++17)(C++17) |
prüft, ob Objekte eines Typs mit Objekten desselben oder eines anderen Typs vertauscht werden können (Klassenvorlage) |
| (C++20) |
gibt an, dass ein Typ vertauscht werden kann oder dass zwei Typen miteinander vertauscht werden können (Konzept) |