std::ranges::rotate_copy, std::ranges::rotate_copy_result, std::ranges::rotate_copy_truncated_result - cppreference.com
Namespaces
Variants

std::ranges::rotate_copy, std::ranges::rotate_copy_result, std::ranges::rotate_copy_truncated_result

From cppreference.com
 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Non-modifying sequence operations    
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17)(C++11)
(C++20)(C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
(C++11)    

Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
(C++11)
(C++17)
Lexicographical comparison operations
Permutation operations


 
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Fold operations (Helper templates)
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
       
       
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
       
       
Permutation operations
Specialized <memory> algorithms
Return types
 
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 [firstlast) or r to the destination range beginning at in rotated order.

1) In the destination range beginning at d_first, the elements originally in [firstmiddle) are placed after the elements originally in [middlelast) while the orders of the elements in both ranges are preserved.
2) Same as (1), but uses ranges::begin(r) as first and ranges::end(r) as last.
3) Same as (1), but executed according to policy, and the destination range is [d_firstd_end). If the destination range is exhausted before reaching middle again, the remaining elements in the source range will not be copied.
4) Same as (3), but uses 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:

  • [firstmiddle) or [middlelast) 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 count be ranges::size(first, last) or ranges::size(r):
3) The source range and [d_firstranges::next(d_first, count, d_last)) overlap.
4) The source range and [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:

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

1,2) A ranges::rotate_copy_result object where:
  • The data member in holds the past-the-end iterator of the source range.
  • The data member out holds the past-the-end iterator of the destination range.
3,4) Let count be the number of elements copied, returns a ranges::rotate_copy_truncated_result object where:
  • The data member in1 holds last, or middle + count if count is less than last - middle.
  • The data member in2 holds an iterator past the last copied element in the source range, or first if count is less than or equal to last - 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) or ranges::distance(r),
  • N2 as ranges::distance(d_first, d_last) or ranges::distance(d_r):
1,2) Exactly N1 assignments.
3,4) Exactly min(N1,N2) assignments.

Exceptions

3,4) During the execution process:
  • 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

See also