C++ named requirements: Swappable
Любое lvalue или rvalue этого типа может быть обменено с любым lvalue или rvalue другого типа, используя неквалифицированный вызов функции swap ( ) в контексте, где видны как std::swap , так и пользовательские swap ( ) .
Содержание |
Требования
Тип U является заменяемым с типом T, если для любого объекта u типа U и любого объекта t типа T,
| Выражение | Требования | Семантика |
|---|---|---|
|
#include <algorithm> // until C++11
#include <utility> // since C++11
|
После вызова значение
t
равно значению, которое хранилось в
u
до вызова, а значение
u
равно значению, которое хранилось в
t
до вызова.
|
Вызывает функцию с именем swap ( ) найденную с помощью разрешения перегрузки среди всех функций с этим именем, которые найдены с помощью поиска, зависимого от аргументов и двух шаблонов std::swap определённых в заголовке <algorithm> (до C++11) <utility> (начиная с C++11) . |
|
#include <algorithm> // until C++11
#include <utility> // since C++11
|
То же | То же |
Многие функции стандартной библиотеки (например, многие алгоритмы) ожидают, что их аргументы удовлетворяют требованиям Swappable , что означает, что когда стандартная библиотека выполняет обмен, она использует эквивалент using std:: swap ; swap ( t, u ) ; .
Типичные реализации либо
Примечания
Не указано, включается ли на самом деле <algorithm> (until C++11) <utility> (since C++11) при выполнении обмена стандартными библиотечными функциями, поэтому пользовательская реализация swap ( ) не должна рассчитывать на её включение.
Пример
#include <iostream> #include <vector> struct IntVector { std::vector<int> v; IntVector& operator=(IntVector) = delete; // не присваиваемый 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); // Ошибка компиляции! std::swap требует MoveAssignable prn(); std::iter_swap(&v1, &v2); // OK: библиотека вызывает неквалифицированный swap() prn(); std::ranges::swap(v1, v2); // OK: библиотека вызывает неквалифицированный swap() prn(); }
Вывод:
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
v1{{2222, 2222}}, v2{{1, 1, 1, 1}};
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
Отчёты о дефектах
Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 226 | C++98 |
it was unclear how the standard library uses
swap
|
clarified to use both
std::
and ADL-found
swap
|
Смотрите также
|
(C++17)
(C++17)
(C++17)
(C++17)
|
проверяет, можно ли обменивать объекты одного типа с объектами того же или другого типа
(шаблон класса) |
|
(C++20)
|
указывает, что тип можно обменивать или что два типа можно обменивать друг с другом
(концепт) |