std::ranges::rotate_copy, std::ranges::rotate_copy_result, std::ranges::rotate_copy_truncated_result
| Defined in header <algorithm>
|
||
| Call signature |
||
template< std::forward_iterator I, std::sentinel_for<I> S,
std::weakly_incrementable O >
requires std::indirectly_copyable<I, O>
constexpr rotate_copy_result<I, O>
rotate_copy( I first, I middle, S last, O d_first );
|
(1) | (since C++20) |
template< ranges::forward_range R, std::weakly_incrementable O >
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr rotate_copy_result<ranges::borrowed_iterator_t<R>, O>
rotate_copy( R&& r, ranges::iterator_t<R> middle, O d_first );
|
(2) | (since C++20) |
template< /*execution-policy*/ Ep,
std::random_access_iterator I, std::sized_sentinel_for<I> S,
std::random_access_iterator O, std::sized_sentinel_for<O> OutS >
requires std::indirectly_copyable<I, O>
ranges::rotate_copy_truncated_result<I, O>
rotate_copy( Ep&& policy, I first, I middle, S last,
O d_first, OutS d_last );
|
(3) | (since C++26) |
template< /*execution-policy*/ Ep,
/*sized-random-access-range*/ R,
/*sized-random-access-range*/ OutR >
requires std::indirectly_copyable<ranges::iterator_t<R>,
ranges::iterator_t<OutR>>
ranges::rotate_copy_truncated_result<ranges::borrowed_iterator_t<R>,
ranges::borrowed_iterator_t<OutR>>
rotate_copy( Ep&& policy, R&& r, ranges::iterator_t<R> middle,
OutR&& d_r );
|
(4) | (since C++26) |
| Helper types |
||
template< class I, class O >
using rotate_copy_result = ranges::in_out_result<I, O>;
|
(5) | (since C++20) |
template< class I, class O >
using rotate_copy_truncated_result = ranges::in_in_out_result<I, I, O>;
|
(6) | (since C++26) |
For the definition of /*execution-policy*/, see this page; for the definition of /*sized-random-access-range*/, see this page.
Copies elements from the source range [first, last) or r to the destination range beginning at in rotated order.
d_first, the elements originally in [first, middle) are placed after the elements originally in [middle, last) while the orders of the elements in both ranges are preserved.ranges::begin(r) as first and ranges::end(r) as last.policy, and the destination range is [d_first, d_end). If the destination range is exhausted before reaching middle again, the remaining elements in the source range will not be copied.ranges::begin(r) as first and ranges::begin(r) + ranges::distance(r) as last, and the destination range is d_r.If any of the following conditions is satisfied, the behavior is undefined:
[first,middle)or[middle,last)is not a valid range.- For the non-parallel overloads (1,2), the source and destination ranges overlap.
- For the parallel overloads (3,4), let
countberanges::size(first, last)orranges::size(r):
[d_first, ranges::next(d_first, count, d_last)) overlap.[d_r.begin(), ranges::next(d_r.begin(), count, d_r.end()) overlap.The function-like entities described on this page are algorithm function objects (informally known as niebloids), that is:
- Explicit template argument lists cannot be specified when calling any of them.
- None of them are visible to argument-dependent lookup.
- When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.
Parameters
| first, last | - | the iterator-sentinel pair defining the source range |
| r | - | the source range |
| middle | - | the beginning of the part that should appear at the beginning of the destination range |
| d_first | - | the beginning of the destination range |
| d_end | - | the sentinel of the destination range |
| d_r | - | the destination range |
| policy | - | the execution policy to use |
Return value
ranges::rotate_copy_result object where:
count be the number of elements copied, returns a ranges::rotate_copy_truncated_result object where:
- The data member in1 holds
last, ormiddle + countifcountis less thanlast - middle. - The data member in2 holds an iterator past the last copied element in the source range, or
firstifcountis less than or equal tolast - middle. - The data member out holds an iterator past the last assigned element in the destination range, or an iterator to the beginning of the destination range if no element is assigned.
Complexity
Given
- N1 as
ranges::distance(first, last)orranges::distance(r), - N2 as
ranges::distance(d_first, d_last)orranges::distance(d_r):
Exceptions
- If the temporary memory resources required for parallelization are not available, std::bad_alloc is thrown.
- If an uncaught exception is thrown while accessing objects via an algorithm argument, the behavior is determined by the execution policy (for standard policies, std::terminate is invoked).
Notes
If the value type is TriviallyCopyable and the iterator types satisfy contiguous_iterator, implementations of ranges::rotate_copy usually avoid multiple assignments by using a "bulk copy" function such as std::memmove.
Possible implementation
See also the implementations in libstdc++ and MSVC STL.
struct rotate_copy_fn
{
template<std::forward_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
requires std::indirectly_copyable<I, O>
constexpr ranges::rotate_copy_result<I, O>
operator()(I first, I middle, S last, O result) const
{
auto c1{ranges::copy(middle, std::move(last), std::move(result))};
auto c2{ranges::copy(std::move(first), std::move(middle), std::move(c1.out))};
return {std::move(c1.in), std::move(c2.out)};
}
template<ranges::forward_range R, std::weakly_incrementable O>
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr ranges::rotate_copy_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, ranges::iterator_t<R> middle, O result) const
{
return (*this)(ranges::begin(r), std::move(middle),
ranges::next(ranges::begin(r), ranges::end(r)),
std::move(result));
}
};
inline constexpr rotate_copy_fn rotate_copy{};
|
Example
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> src{1, 2, 3, 4, 5};
std::vector<int> dest(src.size());
auto pivot = std::ranges::find(src, 3);
std::ranges::rotate_copy(src, pivot, dest.begin());
for (int i : dest)
std::cout << i << ' ';
std::cout << '\n';
// copy the rotation result directly to the std::cout
pivot = std::ranges::find(dest, 1);
std::ranges::rotate_copy(dest, pivot, std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}
Output:
3 4 5 1 2
1 2 3 4 5
