std::stable_partition(3)
π std::stable_partition β the C++ Standard Library's little reordering icon
okay so bestie, welcome to std::stable_partition(3) from the C++ Standard Library β¨ this one's a <algorithm> girlie and she's lowkey one of the most useful little functions in the whole header. let's get into it π
πΈ NAME πΈ
std::stable_partition β literally std::stable_partition. yes the name is the name, we love a self-titled queen π
β¨ SYNOPSIS β¨
she lives in the header <algorithm>, as all the good ones do π
template< class BidirIt, class UnaryPred >
BidirIt stable_partition( BidirIt first, BidirIt last, (1)
(constexpr since C++26)
UnaryPred p );
template< class ExecutionPolicy, class BidirIt, class UnaryPred >
BidirIt stable_partition( ExecutionPolicy&& policy, (2) (since C++17)
BidirIt first, BidirIt last,
UnaryPred p );
so here's the tea on the two overloads π«
- Reorders the elements in the range
[first, last)in such a way that all elements for which the predicatepreturnstrueprecede the elements for which predicatepreturnsfalse. And bestie β the relative order of the elements is preserved. that's the stable part, that's her whole brand π - Same as (1), but executed according to
policy.
this overload only participates in overload resolution if:
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)
β οΈ and now the scary part β if ANY of these conditions is satisfied, the behavior is undefined π like genuinely undefined, do not test her: - The type of*firstis notSwappable. (until C++11) -BidirItis notValueSwappable. - The type of*firstis notMoveConstructible. (since C++11) - The type of*firstis notMoveAssignable.
π¦ 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.
okay the p situation has rules and we're gonna respect them π the expression p(v) must be convertible to bool for every argument v of type (possibly const) VT, where VT is the value type of BidirIt, regardless of value category, and must not modify v. Thus, a parameter type of VT& is not allowed, nor is VT unless for VT a move is equivalent to a copy (since C++11). no cap, that's the whole vibe check on predicates π
π§ Type requirements π§
BidirItmust meet the requirements of LegacyBidirectionalIterator.UnaryPredmust meet the requirements of Predicate.
both of them, no exceptions, she's picky and honestly? respect π
π Return value π
Iterator to the first element of the second group. that's it, that's the gift π
π₯ Complexity π₯
Given (\scriptsize N)N as std::distance(first, last):
- Exactly (\scriptsize N)N applications of
p. (\scriptsize O(N))O(N) swaps if there is enough extra memory, otherwise at most (\scriptsize N \cdot log_{2}(N))Nβ log 2(N) swaps. - (\scriptsize O(N))O(N) applications of
p. (\scriptsize N \cdot log(N))Nβ log(N) swaps.
so like... she's doing math but make it fashion π the logarithms are real and we are NOT pretending otherwise π
π 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.
yeah so std::terminate is not a vibe, be careful out there π«Ά
π Notes π
This function attempts to allocate a temporary buffer. If the allocation fails, the less efficient algorithm is chosen. she tries her best, and honestly? that's main character energy β¨
Implementations in libc++ and libstdc++ also accept ranges denoted by LegacyForwardIterators as an extension. cute bonus feature, iykyk π
Feature-test macro time, she's got a whole table and everything:
__cpp_lib_constexpr_algorithmsβ value202306L, Std column: blank, feature: constexpr stable sorting β
π Example π
// Run this code
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{0, 0, 3, -1, 2, 4, 5, 0, 7};
std::stable_partition(v.begin(), v.end(), [](int n) { return n > 0; });
for (int n : v)
std::cout << n << ' ';
std::cout << '\n';
}
Output:
3 2 4 5 7 0 0 -1 0
look at her go π positives first, in the exact order they came in, then the rest, untouched. ICONIC. she ate and left no crumbs π
π Defect reports π
The following behavior-changing defect reports were applied retroactively to previously published C++ standards. history revisionism but make it standards-compliant πΈ
LWG 2150β Applied to: C++98- Behavior as published:
std::stable_partitionwas only required to place one element satisfyingpbefore one element not satisfyingp. - Correct behavior: corrected the requirement.
- Behavior as published:
so yeah, pre-LWG 2150 the requirement was lowkey slacking and they fixed it. glow-up π¦
π See also π
partitionβ divides a range of elements into two groups (function template)ranges::stable_partition(C++20) β divides elements into two groups while preserving their relative order (niebloid)
both of them are serving, pick whichever matches your vibe β¨
aaaand that's the page bestie π source and version credits: this all comes from http://cppreference.com, dated 2024.06.10, for std::stable_partition(3) β go forth and partition stably, you've got this π«Άπ·
π¦ 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