std::partition(3)
π std::partition β NAME π
okay so this is std::partition(3), folded in near the top from the C++ Standard Libary (manual name kept exactly, bestie, typo and all). The name itself is literally: std::partition β std::partition. Thatβs the whole NAME section, and honestly? Iconic minimalism. π
β¨ Synopsis β¨
Defined in header <algorithm>
template< class ForwardIt, class UnaryPred >
ForwardIt partition( ForwardIt first, ForwardIt last, (1)
(constexpr since C++20)
UnaryPred p );
template< class ExecutionPolicy, class ForwardIt, class UnaryPred >
ForwardIt partition( ExecutionPolicy&& policy, (2) (since C++17)
ForwardIt first, ForwardIt last,
UnaryPred p );
Two overloads, bestie, and they are giving overload-resolution drama:
- Reorders the elements in the range
[first, last)in such a way that all elements for which the predicatepreturnstrueprecede all elements for which predicatepreturnsfalse. Relative order of the elements is not preserved. - Same as (1), but executed according to
policy. This overload participates in overload resolution only ifstd::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)
And bestie, if the type of*firstis notSwappable(until C++11) orForwardItis notValueSwappable(since C++11), the behavior is undefined. Not cute. Do not do that. π
π Parameters π
first,lastβ the range of elements to reorder.policyβ the execution policy to use. See execution policy for details.pβ unary predicate which returnstrueif the element should be ordered before other elements. The expressionp(v)must be convertible toboolfor every argumentvof type (possibly const)VT, whereVTis the value type ofForwardIt, regardless of value category, and must not modifyv. Thus, a parameter type ofVT&is not allowed, nor isVTunless forVTa move is equivalent to a copy (since C++11).
π¦ Type requirements π¦
ForwardItmust meet the requirements ofLegacyForwardIterator.UnaryPredmust meet the requirements ofPredicate.
πΈ Return value πΈ
Iterator to the first element of the second group. Thatβs the boundary girlie. π«Ά
π Complexity π
Given N as std::distance(first, last):
- Exactly
Napplications ofp. At mostN/2swaps ifForwardItmeets the requirements ofLegacyBidirectionalIterator, and at mostNswaps otherwise. O(N)applications ofp.O(NΒ·log(N))swaps.
π«Ά 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
ExecutionPolicyis one of the standard policies,std::terminateis called. For any otherExecutionPolicy, the behavior is implementation-defined. - If the algorithm fails to allocate memory,
std::bad_allocis thrown.
π₯ Possible implementation π₯
Implements overload (1) preserving C++11 compatibility.
template<class ForwardIt, class UnaryPred>
ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPred p)
{
first = std::find_if_not(first, last, p);
if (first == last)
return first;
for (auto i = std::next(first); i != last; ++i)
if (p(*i))
{
std::iter_swap(i, first);
++first;
}
return first;
}
π Example π
Run this code, bestie π
#include <algorithm>
#include <forward_list>
#include <iostream>
#include <iterator>
#include <vector>
template<class ForwardIt>
void quicksort(ForwardIt first, ForwardIt last)
{
if (first == last)
return;
auto pivot = *std::next(first, std::distance(first, last) / 2);
auto middle1 = std::partition(first, last, [pivot](const auto& em)
{
return em < pivot;
});
auto middle2 = std::partition(middle1, last, [pivot](const auto& em)
{
return !(pivot < em);
});
quicksort(first, middle1);
quicksort(middle2, last);
}
int main()
{
std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::cout << "Original vector: ";
for (int elem : v)
std::cout << elem << ' ';
auto it = std::partition(v.begin(), v.end(), [](int i) {return i % 2 == 0;});
std::cout << "\nPartitioned vector: ";
std::copy(std::begin(v), it, std::ostream_iterator<int>(std::cout, " "));
std::cout << "* ";
std::copy(it, std::end(v), std::ostream_iterator<int>(std::cout, " "));
std::forward_list<int> fl {1, 30, -4, 3, 5, -4, 1, 6, -8, 2, -5, 64, 1, 92};
std::cout << "\nUnsorted list: ";
for (int n : fl)
std::cout << n << ' ';
quicksort(std::begin(fl), std::end(fl));
std::cout << "\nSorted using quicksort: ";
for (int fi : fl)
std::cout << fi << ' ';
std::cout << '\n';
}
π Possible output π
Original vector: 0 1 2 3 4 5 6 7 8 9
Partitioned vector: 0 8 2 6 4 * 5 3 7 1 9
Unsorted list: 1 30 -4 3 5 -4 1 6 -8 2 -5 64 1 92
Sorted using quicksort: -8 -5 -4 -4 1 1 1 2 3 5 6 30 64 92
π Defect reports π
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
- DR
LWG 498β Applied to:C++98. Behavior as published:std::partitionrequiredfirstandlastto beLegacyBidirectionalIterator. Correct behavior: only required to beLegacyForwardIterator. - DR
LWG 2150β Applied to:C++98. Behavior as published:std::partitionwas only required to place one element satisfyingpbefore one element not satisfyingp. Correct behavior: corrected the requirement.
π See also π
is_partitioned(C++11) β determines if the range is partitioned by the given predicate (function template).stable_partitionβ divides elements into two groups while preserving their relative order (function template).ranges::partition(C++20) β divides a range of elements into two groups (niebloid).
okay thatβs the whole page, bestie π«Ά cute little sign-off time: source is http://cppreference.com, version/date is 2024.06.10, and this was the std::partition(3) page. byeeee πβ¨π
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms