Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/algorithm/ranges/rotate copy"

From cppreference.com
< cpp‎ | algorithm‎ | ranges
m (See also: ranges::copy)
m (Synopsis: fmt to avoid rev-marks wrapping)
 
(9 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{cpp/ranges/title|rotate_copy}}
+
{{cpp/ranges/title|rotate_copy|rotate_copy_result}}
 
{{cpp/algorithm/ranges/navbar}}
 
{{cpp/algorithm/ranges/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | algorithm}}
+
{{dcl header|algorithm}}
{{dcl h | Call signature}}
+
{{dcl h|Call signature}}
{{dcl | num=1 | since=c++20 |1=
+
{{dcl|num=1|since=c++20|1=
template<std::forward_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
+
template< std::forward_iterator I, std::sentinel_for<I> S,
  requires std::indirectly_copyable<I, O>
+
          std::weakly_incrementable O >
  constexpr ranges::rotate_copy_result<I, O>
+
requires std::indirectly_copyable<I, O>
     ranges::rotate_copy( I first, I middle, S last, O result );
+
constexpr rotate_copy_result<I, O>
 +
     rotate_copy( I first, I middle, S last, O result );
 
}}
 
}}
{{dcl | num=2 | since=c++20 |1=
+
{{dcl|num=2|since=c++20|1=
template<ranges::forward_range R, std::weakly_incrementable O>
+
template< ranges::forward_range R, std::weakly_incrementable O >
  requires std::indirectly_copyable<ranges::iterator_t<R>, O>
+
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
  constexpr ranges::rotate_copy_result<ranges::borrowed_iterator_t<R>, O>
+
constexpr rotate_copy_result<ranges::borrowed_iterator_t<R>, O>
     ranges::rotate_copy( R&& r, ranges::iterator_t<R> middle, O result );
+
     rotate_copy( R&& r, ranges::iterator_t<R> middle, O result );
 
}}
 
}}
{{dcl h | Helper types}}
+
{{dcl h|Helper types}}
{{dcl | num=3 | since=c++20 |1=
+
{{dcl|num=3|since=c++20|1=
template<class I, class O>
+
template< class I, class O >
  using rotate_copy_result = in_out_result<I, O>;
+
using rotate_copy_result = in_out_result<I, O>;
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
@1@ Copies the elements from the source range {{tt|[first, last)}}, to the destination range beginning at {{tt|result}} in such a way, that the element {{tt|middle}} becomes the first element of the destination range and {{tt|middle - 1}} becomes the last element. ''Effect:'' the destination range contains a ''left rotated'' copy of the source range.
+
@1@ Copies the elements from the source range {{range|first|last}}, to the destination range beginning at {{c|result}} in such a way, that the element {{c|*middle}} becomes the first element of the destination range and {{c|*(middle - 1)}} becomes the last element. The result is that the destination range contains a ''left rotated'' copy of the source range.
''Preconditions'' of this function are that {{tt|[first, middle)}} and {{tt|[middle, last)}} are valid ranges, and the source and destination ranges do not overlap.
+
@@ The behavior is undefined if either {{range|first|middle}} or {{range|middle|last}} is not a valid range, or the source and destination ranges overlap.
  
@2@ Same as {{v|1}}, but uses {{tt|r}} as the source range, as if using {{c|ranges::begin(r)}} as {{tt|first}} and {{c|ranges::end(r)}} as {{tt|last}}.
+
@2@ Same as {{v|1}}, but uses {{c|r}} as the source range, as if using {{c|ranges::begin(r)}} as {{c|first}} and {{c|ranges::end(r)}} as {{c|last}}.
  
 
{{cpp/ranges/niebloid}}
 
{{cpp/ranges/niebloid}}
Line 32: Line 33:
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | first, last | the source range of elements to copy from}}
+
{{par|first, last|the source range of elements to copy from}}
{{par | r | the source range of elements to copy from}}
+
{{par|r|the source range of elements to copy from}}
{{par | middle | the element that should appear at the beginning of the destination range}}
+
{{par|middle|the iterator to the element that should appear at the beginning of the destination range}}
{{par | result | beginning of the destination range}}
+
{{par|result|beginning of the destination range}}
 
{{par end}}
 
{{par end}}
  
 
===Return value===
 
===Return value===
@1@ {{c|ranges::rotate_copy_result<I, O>{last, result + N} }}, where {{c|1=N = {last - first} }}.
+
{{c|1= {last, result + N} }}, where {{c|1=N = ranges::distance(first, last)}}.
 
+
@2@ Same as {{v|1}} but the return type is {{c|ranges::rotate_copy_result<ranges::borrowed_iterator_t<R>, O>}}.
+
  
 
===Complexity===
 
===Complexity===
''Linear'': exactly {{tt|last - first}} assignments.
+
''Linear'': exactly {{c|N}} assignments.
<!-- ===Exceptions=== -->
+
  
 
===Notes===
 
===Notes===
In practice, implementations of {{tt|std::ranges::rotate_copy}} avoid multiple assignments and use bulk copy functions such as {{lc|std::memmove}} if the value type is {{named req|TriviallyCopyable}} and the iterator types satisfy {{lconcept|contiguous_iterator}}.
+
If the value type is {{named req|TriviallyCopyable}} and the iterator types satisfy {{lconcept|contiguous_iterator}}, implementations of {{tt|ranges::rotate_copy}} usually avoid multiple assignments by using a "bulk copy" function such as {{lc|std::memmove}}.
  
 
===Possible implementation===
 
===Possible implementation===
<!-- add links to the flagships' implementations -->
+
See also the implementations in [https://github.com/gcc-mirror/gcc/blob/14d8a5ae472ca5743016f37da2dd4770d83dea21/libstdc%2B%2B-v3/include/bits/ranges_algo.h#L1511-L1539 libstdc++] and [https://github.com/microsoft/STL/blob/472161105d596192194d4715ccad307c6c163b4a/stl/inc/algorithm#L4466-L4514 MSVC STL].
{{eq fun | 1=
+
{{eq fun|1=
struct rotate_copy_fn {
+
struct rotate_copy_fn
  template<std::forward_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
+
{
 +
    template<std::forward_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
 
     requires std::indirectly_copyable<I, O>
 
     requires std::indirectly_copyable<I, O>
 
     constexpr ranges::rotate_copy_result<I, O>
 
     constexpr ranges::rotate_copy_result<I, O>
      operator() ( I first, I middle, S last, O result ) const {
+
        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)) };
+
        auto c1 {ranges::copy(middle, std::move(last), std::move(result))};
          return { std::move(c1.in), std::move(c2.out) };
+
        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>
+
    template<ranges::forward_range R, std::weakly_incrementable O>
 
     requires std::indirectly_copyable<ranges::iterator_t<R>, O>
 
     requires std::indirectly_copyable<ranges::iterator_t<R>, O>
 
     constexpr ranges::rotate_copy_result<ranges::borrowed_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 {
+
        operator()(R&& r, ranges::iterator_t<R> middle, O result) const
          return (*this)(ranges::begin(r), std::move(middle),
+
    {
                        ranges::end(r), std::move(result));
+
        return (*this)(ranges::begin(r), std::move(middle),
      }
+
                      ranges::end(r), std::move(result));
 +
    }
 
};
 
};
  
inline constexpr rotate_copy_fn rotate_copy{};
+
inline constexpr rotate_copy_fn rotate_copy {};
 
}}
 
}}
  
 
===Example===
 
===Example===
 
{{example
 
{{example
| code=
+
|code=
 
#include <algorithm>
 
#include <algorithm>
 
#include <iostream>
 
#include <iostream>
Line 85: Line 86:
 
int main()
 
int main()
 
{
 
{
     std::vector<int> src = {1, 2, 3, 4, 5};
+
     std::vector<int> src {1, 2, 3, 4, 5};
 
     std::vector<int> dest(src.size());
 
     std::vector<int> dest(src.size());
 
     auto pivot = std::ranges::find(src, 3);
 
     auto pivot = std::ranges::find(src, 3);
  
 
     std::ranges::rotate_copy(src, pivot, dest.begin());
 
     std::ranges::rotate_copy(src, pivot, dest.begin());
 
+
     for (int i : dest)
     for (const auto &i : dest) {
+
 
         std::cout << i << ' ';
 
         std::cout << i << ' ';
    }
 
 
     std::cout << '\n';
 
     std::cout << '\n';
  
Line 101: Line 100:
 
     std::cout << '\n';
 
     std::cout << '\n';
 
}
 
}
| output=
+
|output=
 
3 4 5 1 2
 
3 4 5 1 2
 
1 2 3 4 5
 
1 2 3 4 5
Line 108: Line 107:
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/algorithm/ranges/dsc rotate}}
+
{{dsc inc|cpp/algorithm/ranges/dsc rotate}}
{{dsc inc | cpp/algorithm/ranges/dsc copy}}
+
{{dsc inc|cpp/algorithm/ranges/dsc copy}}
{{dsc inc | cpp/algorithm/dsc rotate}}
+
{{dsc inc|cpp/algorithm/dsc rotate_copy}}
 
{{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 11:40, 16 April 2023

 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
(C++11)                (C++11)(C++11)

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
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
C library
Numeric operations
Operations on uninitialized memory
 
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
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
Fold operations
Numeric operations
(C++23)            
Operations on uninitialized storage
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 result );
(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 result );
(2) (since C++20)
Helper types
template< class I, class O >
using rotate_copy_result = in_out_result<I, O>;
(3) (since C++20)
1) Copies the elements from the source range [firstlast), to the destination range beginning at result in such a way, that the element *middle becomes the first element of the destination range and *(middle - 1) becomes the last element. The result is that the destination range contains a left rotated copy of the source range.
The behavior is undefined if either [firstmiddle) or [middlelast) is not a valid range, or the source and destination ranges overlap.
2) Same as (1), but uses r as the source range, as if using ranges::begin(r) as first and ranges::end(r) as last.

The function-like entities described on this page are niebloids, that is:

In practice, they may be implemented as function objects, or with special compiler extensions.

Contents

[edit] Parameters

first, last - the source range of elements to copy from
r - the source range of elements to copy from
middle - the iterator to the element that should appear at the beginning of the destination range
result - beginning of the destination range

[edit] Return value

{last, result + N}, where N = ranges::distance(first, last).

[edit] Complexity

Linear: exactly N assignments.

[edit] 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.

[edit] 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::end(r), std::move(result));
    }
};
 
inline constexpr rotate_copy_fn rotate_copy {};

[edit] 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

[edit] See also

rotates the order of elements in a range
(niebloid)[edit]
copies a range of elements to a new location
(niebloid)[edit]
copies and rotate a range of elements
(function template) [edit]