Difference between revisions of "cpp/algorithm/swap ranges"
(Wording update.) |
|||
(6 intermediate revisions by 3 users not shown) | |||
Line 2: | Line 2: | ||
{{cpp/algorithm/navbar}} | {{cpp/algorithm/navbar}} | ||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | algorithm}} | + | {{dcl header|algorithm}} |
− | {{dcl | + | {{dcl|num=1|notes={{mark constexpr since c++20}}| |
template< class ForwardIt1, class ForwardIt2 > | template< class ForwardIt1, class ForwardIt2 > | ||
ForwardIt2 swap_ranges( ForwardIt1 first1, ForwardIt1 last1, | ForwardIt2 swap_ranges( ForwardIt1 first1, ForwardIt1 last1, | ||
ForwardIt2 first2 ); | ForwardIt2 first2 ); | ||
− | |||
− | |||
− | |||
− | |||
}} | }} | ||
− | {{dcl | since=c++17 | | + | {{dcl|num=2|since=c++17| |
− | template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > | + | template< class ExecutionPolicy, |
− | ForwardIt2 swap_ranges( ExecutionPolicy&& policy, | + | class ForwardIt1, class ForwardIt2 > |
− | ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2 );}} | + | ForwardIt2 swap_ranges( ExecutionPolicy&& policy, |
+ | ForwardIt1 first1, ForwardIt1 last1, | ||
+ | ForwardIt2 first2 ); | ||
+ | }} | ||
{{dcl end}} | {{dcl end}} | ||
− | @1@ Exchanges elements between range {{ | + | @1@ Exchanges elements between range {{range|first1|last1}} and another range of {{c|std::distance(first1, last1)}} elements starting at {{c|first2}}. |
− | + | ||
− | @2@ Same as {{v|1}}, but executed according to {{ | + | @2@ Same as {{v|1}}, but executed according to {{c|policy}}. |
+ | @@ {{cpp/algorithm/parallel overload precondition}} | ||
+ | |||
+ | If any of the following conditions is satisfied, the behavior is undefined: | ||
+ | * The two ranges overlap. | ||
+ | * There exists a pair of corresponding iterators {{c|iter1}} and {{c|iter2}} in the two ranges such that {{c|*iter1}} is not {{named req|Swappable}} with {{c|*iter2}}. | ||
===Parameters=== | ===Parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par | first1, last1 | the first range of elements to swap}} | + | {{par|first1, last1|the first range of elements to swap}} |
− | {{par | first2 | beginning of the second range of elements to swap}} | + | {{par|first2|beginning of the second range of elements to swap}} |
{{par exec pol}} | {{par exec pol}} | ||
{{par hreq}} | {{par hreq}} | ||
− | {{par req named | ForwardIt1, ForwardIt2 | ForwardIterator | + | {{par req named|ForwardIt1, ForwardIt2|ForwardIterator}} |
− | + | ||
{{par end}} | {{par end}} | ||
===Return value=== | ===Return value=== | ||
− | Iterator to the element past the last element exchanged in the range beginning with {{ | + | Iterator to the element past the last element exchanged in the range beginning with {{c|first2}}. |
===Complexity=== | ===Complexity=== | ||
− | + | Exactly {{c|std::distance(first1, last1)}} swaps. | |
===Exceptions=== | ===Exceptions=== | ||
− | {{cpp/algorithm/ | + | {{cpp/algorithm/parallel exceptions reporting behavior|singular=yes}} |
+ | |||
+ | ===Notes=== | ||
+ | {{cpp/algorithm/notes swap vectorization}} | ||
===Possible implementation=== | ===Possible implementation=== | ||
− | {{eq fun | 1= | + | {{eq fun|1= |
template<class ForwardIt1, class ForwardIt2> | template<class ForwardIt1, class ForwardIt2> | ||
− | constexpr ForwardIt2 swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2) | + | constexpr //< since C++20 |
+ | ForwardIt2 swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2) | ||
{ | { | ||
− | + | for (; first1 != last1; ++first1, ++first2) | |
− | std::iter_swap(first1 | + | std::iter_swap(first1, first2); |
− | + | ||
return first2; | return first2; | ||
} | } | ||
Line 56: | Line 62: | ||
===Example=== | ===Example=== | ||
{{example | {{example | ||
− | + | |Demonstrates swapping of subranges from different containers. | |
− | + | |code= | |
+ | #include <algorithm> | ||
+ | #include <iostream> | ||
#include <list> | #include <list> | ||
#include <vector> | #include <vector> | ||
− | |||
− | |||
− | auto print = [](auto comment, auto const& seq) { | + | auto print = [](auto comment, auto const& seq) |
+ | { | ||
std::cout << comment; | std::cout << comment; | ||
− | for (const auto& e : seq) | + | for (const auto& e : seq) |
+ | std::cout << e << ' '; | ||
std::cout << '\n'; | std::cout << '\n'; | ||
}; | }; | ||
Line 71: | Line 79: | ||
int main() | int main() | ||
{ | { | ||
− | std::vector< | + | std::vector<char> v{'a', 'b', 'c', 'd', 'e'}; |
− | std::list< | + | std::list<char> l{'1', '2', '3', '4', '5'}; |
− | + | ||
print("Before swap_ranges:\n" "v: ", v); | print("Before swap_ranges:\n" "v: ", v); | ||
print("l: ", l); | print("l: ", l); | ||
− | + | ||
− | std::swap_ranges(v.begin(), v.begin()+3, l.begin()); | + | std::swap_ranges(v.begin(), v.begin() + 3, l.begin()); |
− | + | ||
print("After swap_ranges:\n" "v: ", v); | print("After swap_ranges:\n" "v: ", v); | ||
print("l: ", l); | print("l: ", l); | ||
} | } | ||
− | + | |output= | |
Before swap_ranges: | Before swap_ranges: | ||
− | v: | + | v: a b c d e |
− | l: | + | l: 1 2 3 4 5 |
After swap_ranges: | After swap_ranges: | ||
− | v: | + | v: 1 2 3 d e |
− | l: | + | l: a b c 4 5 |
}} | }} | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/algorithm/dsc iter_swap}} | + | {{dsc inc|cpp/algorithm/dsc iter_swap}} |
− | {{dsc inc | cpp/algorithm/dsc swap}} | + | {{dsc inc|cpp/algorithm/dsc swap}} |
− | {{dsc inc | cpp/algorithm/ranges/dsc swap_ranges}} | + | {{dsc inc|cpp/algorithm/ranges/dsc swap_ranges}} |
{{dsc end}} | {{dsc end}} | ||
{{langlinks|de|es|fr|it|ja|pt|ru|zh}} | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} |
Latest revision as of 23:42, 25 March 2024
Defined in header <algorithm>
|
||
template< class ForwardIt1, class ForwardIt2 > ForwardIt2 swap_ranges( ForwardIt1 first1, ForwardIt1 last1, |
(1) | (constexpr since C++20) |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > |
(2) | (since C++17) |
[
first1,
last1)
and another range of std::distance(first1, last1) elements starting at first2.
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true. |
(until C++20) |
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true. |
(since C++20) |
If any of the following conditions is satisfied, the behavior is undefined:
- The two ranges overlap.
- There exists a pair of corresponding iterators iter1 and iter2 in the two ranges such that *iter1 is not Swappable with *iter2.
Contents |
[edit] Parameters
first1, last1 | - | the first range of elements to swap |
first2 | - | beginning of the second range of elements to swap |
policy | - | the execution policy to use. See execution policy for details. |
Type requirements | ||
-ForwardIt1, ForwardIt2 must meet the requirements of LegacyForwardIterator.
|
[edit] Return value
Iterator to the element past the last element exchanged in the range beginning with first2.
[edit] Complexity
Exactly std::distance(first1, last1) swaps.
[edit] Exceptions
The overload with a template parameter named ExecutionPolicy
reports errors as follows:
- If execution of a function invoked as part of the algorithm throws an exception and
ExecutionPolicy
is one of the standard policies, std::terminate is called. For any otherExecutionPolicy
, the behavior is implementation-defined. - If the algorithm fails to allocate memory, std::bad_alloc is thrown.
[edit] Notes
Implementations (e.g. MSVC STL) may enable vectorization when the iterator type satisfies LegacyContiguousIterator and swapping its value type calls neither non-trivial special member function nor ADL-found swap
.
[edit] Possible implementation
template<class ForwardIt1, class ForwardIt2> constexpr //< since C++20 ForwardIt2 swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2) { for (; first1 != last1; ++first1, ++first2) std::iter_swap(first1, first2); return first2; } |
[edit] Example
Demonstrates swapping of subranges from different containers.
#include <algorithm> #include <iostream> #include <list> #include <vector> auto print = [](auto comment, auto const& seq) { std::cout << comment; for (const auto& e : seq) std::cout << e << ' '; std::cout << '\n'; }; int main() { std::vector<char> v{'a', 'b', 'c', 'd', 'e'}; std::list<char> l{'1', '2', '3', '4', '5'}; print("Before swap_ranges:\n" "v: ", v); print("l: ", l); std::swap_ranges(v.begin(), v.begin() + 3, l.begin()); print("After swap_ranges:\n" "v: ", v); print("l: ", l); }
Output:
Before swap_ranges: v: a b c d e l: 1 2 3 4 5 After swap_ranges: v: 1 2 3 d e l: a b c 4 5
[edit] See also
swaps the elements pointed to by two iterators (function template) | |
swaps the values of two objects (function template) | |
(C++20) |
swaps two ranges of elements (niebloid) |