Constrained algorithms and algorithms on ranges(C++20) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Constrained algorithms, e.g.ranges::copy,ranges::sort, ... | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Execution policies(C++17) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Numeric operations | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Operations on uninitialized memory | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Defined in header <algorithm> | ||
template<class ForwardIt> ForwardIt rotate( ForwardIt first, ForwardIt middle, ForwardIt last); | (1) | (constexpr since C++20) |
template<class ExecutionPolicy,class ForwardIt> ForwardIt rotate( ExecutionPolicy&& policy, | (2) | (since C++17) |
std::rotate
swaps the elements in the range[
first,
last)
in such a way that the elements in[
first,
middle)
are placed after the elements in[
middle,
last)
while the orders of the elements in both ranges are preserved.std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> istrue. | (until C++20) |
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> istrue. | (since C++20) |
If any of the following conditions is satisfied, the behavior is undefined:
[
first,
middle)
or[
middle,
last)
is not avalid range.
| (until C++11) |
| (since C++11) |
Contents |
first, last | - | the pair of iterators defining therange of elements to rotate |
middle | - | the element that should appear at the beginning of the rotated range |
policy | - | theexecution policy to use |
Type requirements | ||
-ForwardIt must meet the requirements ofLegacyForwardIterator. |
The iterator to the element originally referenced by*first, i.e. thestd::distance(middle, last)th next iterator offirst.
At moststd::distance(first, last) swaps.
The overload with a template parameter namedExecutionPolicy
reports errors as follows:
ExecutionPolicy
is one of thestandard policies,std::terminate is called. For any otherExecutionPolicy
, the behavior is implementation-defined.See also the implementations inlibstdc++,libc++, andMSVC STL.
template<class ForwardIt>constexpr// since C++20ForwardIt rotate(ForwardIt first, ForwardIt middle, ForwardIt last){if(first== middle)return last; if(middle== last)return first; ForwardIt write= first; ForwardIt next_read= first;// read position for when “read” hits “last” for(ForwardIt read= middle; read!= last;++write,++read){if(write== next_read) next_read= read;// track where “first” wentstd::iter_swap(write, read);} // rotate the remaining sequence into place rotate(write, next_read, last);return write;} |
std::rotate
has better efficiency on common implementations ifForwardIt
satisfiesLegacyBidirectionalIterator or (better)LegacyRandomAccessIterator.
Implementations (e.g.MSVC STL) may enable vectorization when the iterator type satisfiesLegacyContiguousIterator and swapping its value type calls neither non-trivial special member function norADL-foundswap
.
std::rotate
is a common building block in many algorithms. This example demonstratesinsertion sort.
#include <algorithm>#include <iostream>#include <vector> auto print=[](constauto remark,constauto& v){std::cout<< remark;for(auto n: v)std::cout<< n<<' ';std::cout<<'\n';}; int main(){std::vector<int> v{2,4,2,0,5,10,7,3,7,1}; print("before sort:\t\t", v); // insertion sortfor(auto i= v.begin(); i!= v.end();++i) std::rotate(std::upper_bound(v.begin(), i,*i), i, i+1); print("after sort:\t\t", v); // simple rotation to the left std::rotate(v.begin(), v.begin()+1, v.end()); print("simple rotate left:\t", v); // simple rotation to the right std::rotate(v.rbegin(), v.rbegin()+1, v.rend()); print("simple rotate right:\t", v);}
Output:
before sort:2 4 2 0 5 10 7 3 7 1after sort:0 1 2 2 3 4 5 7 7 10simple rotate left:1 2 2 3 4 5 7 7 10 0simple rotate right:0 1 2 2 3 4 5 7 7 10
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 488 | C++98 | the new location of the element pointed byfirst was not returned | returned |
copies and rotate a range of elements (function template)[edit] | |
(C++20) | rotates the order of elements in a range (algorithm function object)[edit] |