Difference between revisions of "cpp/algorithm/swap"
From cppreference.com
m (→Parameters) |
(Added LWG issue #227 DR.) |
||
Line 2: | Line 2: | ||
{{cpp/algorithm/navbar}} | {{cpp/algorithm/navbar}} | ||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | algorithm | notes={{mark until c++11}}}} | + | {{dcl header|algorithm|notes={{mark until c++11}}}} |
− | {{dcl header | utility | notes={{mark since c++11}}}} | + | {{dcl header|utility|notes={{mark since c++11}}}} |
− | {{dcl header | string_view | notes={{mark since c++17}}}} | + | {{dcl header|string_view|notes={{mark since c++17}}}} |
− | {{dcl rev multi | num=1| until1=c++11 | dcl1= | + | {{dcl rev multi|num=1|until1=c++11|dcl1= |
template< class T > | template< class T > | ||
void swap( T& a, T& b ); | void swap( T& a, T& b ); | ||
Line 16: | Line 16: | ||
constexpr void swap( T& a, T& b ) noexcept(/* see below */); | constexpr void swap( T& a, T& b ) noexcept(/* see below */); | ||
}} | }} | ||
− | {{dcl rev multi | num=2 | since1=c++11 | until1=c++20 |dcl1= | + | {{dcl rev multi|num=2|since1=c++11|until1=c++20|dcl1= |
− | + | ||
template< class T2, std::size_t N > | template< class T2, std::size_t N > | ||
− | void swap( T2 (&a)[N], T2 (&b)[N]) noexcept(/* see below */); | + | void swap( T2 (&a)[N], T2 (&b)[N] ) noexcept(/* see below */); |
− | + | ||
|dcl2= | |dcl2= | ||
template< class T2, std::size_t N > | template< class T2, std::size_t N > | ||
− | constexpr void swap( T2 (&a)[N], T2 (&b)[N]) noexcept(/* see below */); | + | constexpr void swap( T2 (&a)[N], T2 (&b)[N] ) noexcept(/* see below */); |
}} | }} | ||
{{dcl end}} | {{dcl end}} | ||
Line 29: | Line 27: | ||
Exchanges the given values. | Exchanges the given values. | ||
− | @1@ Swaps the values {{ | + | @1@ Swaps the values {{c|a}} and {{c|b}}. {{rev inl|since=c++17|This overload does not participate in overload resolution unless {{c|std::is_move_constructible_v<T> && std::is_move_assignable_v<T>}} is {{c|true}}.}} |
− | @2@ Swaps the arrays {{ | + | @2@ Swaps the arrays {{c|a}} and {{c|b}}. In effect calls {{c|std::swap_ranges(a, a + N, b)}}. {{rev inl|since=c++17|This overload does not participate in overload resolution unless {{c|std::is_swappable_v<T2>}} is {{c|true}}.}} |
===Parameters=== | ===Parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par | a, b | the values to be swapped}} | + | {{par|a, b|the values to be swapped}} |
{{par hreq}} | {{par hreq}} | ||
− | {{par req | {{tt|T}} must meet the requirements of {{rev inl|until=c++11|{{named req|CopyConstructible}} and {{named req|CopyAssignable}}}}{{rev inl|since=c++11|{{named req|MoveConstructible}} and {{named req|MoveAssignable}}}}}} | + | {{par req|{{tt|T}} must meet the requirements of {{rev inl|until=c++11|{{named req|CopyConstructible}} and {{named req|CopyAssignable}}}}{{rev inl|since=c++11|{{named req|MoveConstructible}} and {{named req|MoveAssignable}}}}}} |
− | {{par req named | T2 | Swappable }} | + | {{par req named|T2|Swappable}} |
{{par end}} | {{par end}} | ||
Line 138: | Line 136: | ||
===Example=== | ===Example=== | ||
{{example | {{example | ||
− | + | |<!-- should demo proper use of swap with generic types, as in void swap(T& other) {using std::swap; swap(member, other.member);} , not just trivialities --> | |
− | + | |code= | |
#include <algorithm> | #include <algorithm> | ||
#include <iostream> | #include <iostream> | ||
− | namespace Ns { | + | namespace Ns |
− | class A | + | { |
− | int id{}; | + | class A |
− | + | { | |
− | + | int id{}; | |
− | std::cout << "swap(" << lhs << ", " << rhs << ")\n"; | + | |
− | + | friend void swap(A& lhs, A& rhs) | |
− | + | { | |
− | + | std::cout << "swap(" << lhs << ", " << rhs << ")\n"; | |
− | + | std::swap(lhs.id, rhs.id); | |
− | return os << "A::id=" << a.id; | + | } |
− | + | ||
− | + | friend std::ostream& operator<< (std::ostream& os, A const& a) | |
− | public: | + | { |
− | + | return os << "A::id=" << a.id; | |
− | + | } | |
− | + | ||
− | }; | + | public: |
+ | A(int i) : id{i} {} | ||
+ | A(A const&) = delete; | ||
+ | A& operator = (A const&) = delete; | ||
+ | }; | ||
} | } | ||
Line 167: | Line 169: | ||
int a = 5, b = 3; | int a = 5, b = 3; | ||
std::cout << a << ' ' << b << '\n'; | std::cout << a << ' ' << b << '\n'; | ||
− | std::swap(a,b); | + | std::swap(a, b); |
std::cout << a << ' ' << b << '\n'; | std::cout << a << ' ' << b << '\n'; | ||
Line 173: | Line 175: | ||
std::cout << p << ' ' << q << '\n'; | std::cout << p << ' ' << q << '\n'; | ||
// std::swap(p, q); // error, type requirements are not satisfied | // std::swap(p, q); // error, type requirements are not satisfied | ||
− | swap(p, q); | + | swap(p, q); // OK, ADL finds the appropriate friend `swap` |
std::cout << p << ' ' << q << '\n'; | std::cout << p << ' ' << q << '\n'; | ||
} | } | ||
− | + | |output= | |
5 3 | 5 3 | ||
3 5 | 3 5 | ||
Line 184: | Line 186: | ||
}} | }} | ||
− | === Defect reports === | + | ===Defect reports=== |
{{dr list begin}} | {{dr list begin}} | ||
− | {{dr list item|wg=lwg|dr=2554|std=C++11|before=swapping multi-dimensional arrays can never be {{tt|noexcept}} due to name lookup problems|after=made to work}} | + | {{dr list item|wg=lwg|dr=227|std=C++98|before={{tt|T}} was not required to be {{named req|CopyConstructible}} or {{named req|DefaultConstructible}}<br>(a temporary object of type {{tt|T}} might not be able to be constructed)|after={{tt|T}} is also required to<br>be {{named req|CopyConstructible}}}} |
+ | {{dr list item|wg=lwg|dr=2554|std=C++11|before=swapping multi-dimensional arrays can never<br>be {{tt|noexcept}} due to name lookup problems|after=made to work}} | ||
{{dr list end}} | {{dr list end}} | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/utility/ranges/dsc swap}} | + | {{dsc inc|cpp/utility/ranges/dsc swap}} |
− | {{dsc inc | cpp/algorithm/dsc iter_swap}} | + | {{dsc inc|cpp/algorithm/dsc iter_swap}} |
− | {{dsc inc | cpp/algorithm/dsc swap_ranges}} | + | {{dsc inc|cpp/algorithm/dsc swap_ranges}} |
− | {{dsc inc | cpp/utility/dsc exchange}} | + | {{dsc inc|cpp/utility/dsc exchange}} |
{{dsc end}} | {{dsc end}} | ||
{{langlinks|de|es|fr|it|ja|pt|ru|zh}} | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} |
Revision as of 23:32, 10 October 2022
Defined in header <algorithm>
|
(until C++11) |
|
Defined in header <utility>
|
(since C++11) |
|
Defined in header <string_view>
|
(since C++17) |
|
(1) | ||
template< class T > void swap( T& a, T& b ); |
(until C++11) | |
template< class T > void swap( T& a, T& b ) noexcept(/* see below */); |
(since C++11) (until C++20) |
|
template< class T > constexpr void swap( T& a, T& b ) noexcept(/* see below */); |
(since C++20) | |
(2) | ||
template< class T2, std::size_t N > void swap( T2 (&a)[N], T2 (&b)[N] ) noexcept(/* see below */); |
(since C++11) (until C++20) |
|
template< class T2, std::size_t N > constexpr void swap( T2 (&a)[N], T2 (&b)[N] ) noexcept(/* see below */); |
(since C++20) | |
Exchanges the given values.
1) Swaps the values a and b. This overload does not participate in overload resolution unless std::is_move_constructible_v<T> && std::is_move_assignable_v<T> is true.(since C++17)
2) Swaps the arrays a and b. In effect calls std::swap_ranges(a, a + N, b). This overload does not participate in overload resolution unless std::is_swappable_v<T2> is true.(since C++17)
Contents |
Parameters
a, b | - | the values to be swapped |
Type requirements | ||
-T must meet the requirements of CopyConstructible and CopyAssignable(until C++11)MoveConstructible and MoveAssignable(since C++11)
| ||
-T2 must meet the requirements of Swappable.
|
Return value
(none)
Exceptions
1)
(none) |
(until C++11) |
noexcept specification:
noexcept( std::is_nothrow_move_constructible<T>::value && |
(since C++11) |
2)
noexcept specification:
The lookup for the identifier noexcept(noexcept(swap(*a, *b))) swap in the exception specification finds this function template in addition to anything found by the usual lookup rules, making the exception specification equivalent to C++17 std::is_nothrow_swappable.
|
(since C++11) (until C++17) |
noexcept specification:
noexcept(std::is_nothrow_swappable_v<T2>) |
(since C++17) |
Complexity
1) Constant
2) Linear in
N
Specializations
|
(until C++20) |
The expected way to make a program-defined type swappable is to provide a non-member function swap in the same namespace as the type: see Swappable for details.
The following overloads are already provided by the standard library:
(C++11) |
specializes the std::swap algorithm (function template) |
(C++11) |
specializes the std::swap algorithm (function template) |
(C++11) |
specializes the std::swap algorithm (function template) |
(C++11) |
specializes the std::swap algorithm (function template) |
(C++11) |
specializes the std::swap algorithm (function template) |
(C++11) |
specializes the std::swap algorithm (function template) |
specializes the std::swap algorithm (function template) | |
(C++11) |
specializes the std::swap algorithm (function template) |
specializes the std::swap algorithm (function template) | |
(C++11) |
specializes the std::swap algorithm (function template) |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
(C++11) |
specializes the std::swap algorithm (function template) |
specializes the std::swap algorithm (function template) | |
(C++11) |
specializes the std::swap algorithm (function template) |
(C++11) |
specializes the std::swap algorithm (function template) |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
specializes the std::swap algorithm (function template) | |
(C++11) |
specializes the std::swap algorithm (function template) |
specializes the std::swap algorithm (function template) | |
(C++11) |
specializes the std::swap algorithm (function) |
(C++11) |
specializes the std::swap algorithm (function template) |
(C++14) |
specializes the std::swap algorithm (function template) |
(C++11) |
specializes the std::swap algorithm (function template) |
specializes the std::swap algorithm (function template) | |
(C++17) |
specializes the std::swap algorithm (function template) |
(C++17) |
specializes the std::swap algorithm (function) |
(C++17) |
specializes the std::swap algorithm (function template) |
specializes the std::swap algorithm (function template) | |
(C++17) |
specializes the std::swap algorithm (function) |
(C++23) |
specializes the std::swap algorithm (function) |
(C++20) |
specializes the std::swap algorithm (function) |
specializes the std::swap algorithm (function) | |
(C++20) |
specializes the std::swap algorithm (function) |
(C++20) |
specializes the std::swap algorithm (function) |
Example
Run this code
#include <algorithm> #include <iostream> namespace Ns { class A { int id{}; friend void swap(A& lhs, A& rhs) { std::cout << "swap(" << lhs << ", " << rhs << ")\n"; std::swap(lhs.id, rhs.id); } friend std::ostream& operator<< (std::ostream& os, A const& a) { return os << "A::id=" << a.id; } public: A(int i) : id{i} {} A(A const&) = delete; A& operator = (A const&) = delete; }; } int main() { int a = 5, b = 3; std::cout << a << ' ' << b << '\n'; std::swap(a, b); std::cout << a << ' ' << b << '\n'; Ns::A p{6}, q{9}; std::cout << p << ' ' << q << '\n'; // std::swap(p, q); // error, type requirements are not satisfied swap(p, q); // OK, ADL finds the appropriate friend `swap` std::cout << p << ' ' << q << '\n'; }
Output:
5 3 3 5 A::id=6 A::id=9 swap(A::id=6, A::id=9) A::id=9 A::id=6
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 227 | C++98 | T was not required to be CopyConstructible or DefaultConstructible(a temporary object of type T might not be able to be constructed)
|
T is also required tobe CopyConstructible |
LWG 2554 | C++11 | swapping multi-dimensional arrays can never be noexcept due to name lookup problems
|
made to work |
See also
(C++20) |
swaps the values of two objects (customization point object) |
swaps the elements pointed to by two iterators (function template) | |
swaps two ranges of elements (function template) | |
(C++14) |
replaces the argument with a new value and returns its previous value (function template) |