Именованные требования C++: Swappable
Любое lvalue или rvalue этого типа можно обменять с любым lvalue или rvalue некоторого другого типа с помощью неквалифицированного вызова функции swap() в контексте, где видны как std::swap, так и определённые пользователем swap()ы.
Требования
Тип U является Swappable с типом T, если для любого объекта u типа U и любого объекта t типа T
| Выражение | Требования | Семантика |
|---|---|---|
#include <algorithm> // until C++11 #include <utility> // since C++11 using std::swap; swap(u, t); | После вызова значение t является значением, которое имел u до вызова, а значение u является значением, которое имел t до вызова. | Вызывает функцию с именем swap(), найденную разрешением перегрузки среди всех функций с таким именем, обнаруженных посредством поиска, зависящего от аргументов, и двух шаблонов std::swap, определённых в заголовочном файле <algorithm>(до C++11)<utility>(начиная с C++11). |
#include <algorithm> // until C++11 #include <utility> // since C++11 using std::swap; swap(t, u); | То же | То же |
Многие функции стандартной библиотеки (например, многие алгоритмы) требуют, чтобы их аргументы удовлетворяли требованиям Swappable, то есть при каждой операции обмена, выполняемой стандартной библиотекой, используется эквивалент using std::swap; swap(t, u);.
Типичные реализации либо
Примечания
Не указано, включается ли <algorithm>(до C++11)<utility>(начиная с C++11) фактически при выполнении обмена функциями стандартной библиотеки, поэтому функция swap(), предоставленная пользователем, не должна рассчитывать на её включение.
Пример
#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();
}
Вывод:
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 | Применяется к | Поведение согласно опубликованной версии | Правильное поведение |
|---|---|---|---|
| LWG 226 | C++98 | не было ясно, как стандартная библиотека использует swap | уточнено, что используются как std::, так и найденная посредством ADL функция swap |
См. также
|
(C++17)(C++17)(C++17)(C++17) | проверяет, можно ли обменивать объекты типа с объектами того же или другого типа (шаблон класса) |
|
(C++26)(C++26)(C++26)(C++26) | проверяет, можно ли обменивать объекты одного отражённого типа с объектами того же или другого отражённого типа (функция) |
|
(C++20)(C++20) | задаёт требование, что тип может быть обменян или что два типа могут быть обменяны друг с другом (концепт) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/named_req/Swappable