Skip to main content

std::partition_point() algorithm

template< class ForwardIt, class UnaryPredicate >
constexpr ForwardIt partition_point( ForwardIt first, ForwardIt last, UnaryPredicate p );

Examines the partitioned (as if by std::partition) range [first; last) and locates the end of the first partition, that is, the first element that does not satisfy p or last if all elements satisfy p.

Parameters

first
last

The partitioned range of elements to examine

policy

The execution policy to use. See execution policy for details.

p

Unary predicate which returns true for the required element.

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 InputIt, 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).

Type requirements

ForwardItLegacyForwardIterator
UnaryPredicatePredicate

Return value

The iterator past the end of the first partition within [first; last) or last if all elements satisfy p.

Complexity

Given N as std::distance(first, last):

Performs O(log(N)) applications of the predicate p.

However, for non-LegacyRandomAccessIterators, the number of iterator increments is O(N).

Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

Possible implementation

partition_point (1)
template<class ForwardIt, class UnaryPredicate>
constexpr //< since C++20
ForwardIt partition_point(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
for (auto length = std::distance(first, last); 0 < length; )
{
auto half = length / 2;
auto middle = std::next(first, half);
if (p(*middle))
{
first = std::next(middle);
length -= (half + 1);
}
else
length = half;
}

return first;
}

Notes

This algorithm is a more general form of std::lower_bound, which can be expressed in terms of std::partition_point with the predicate [&](auto const& e) { return e < value; });.

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>

auto print_seq = [](auto rem, auto first, auto last)
{
for (std::cout << rem; first != last; std::cout << *first++ << ' ') {}
std::cout << '\n';
};

int main()
{
std::array v {1, 2, 3, 4, 5, 6, 7, 8, 9};

auto is_even = [](int i) { return i % 2 == 0; };

std::partition(v.begin(), v.end(), is_even);
print_seq("After partitioning, v: ", v.cbegin(), v.cend());

const auto pp = std::partition_point(v.cbegin(), v.cend(), is_even);
const auto i = std::distance(v.cbegin(), pp);
std::cout << "Partition point is at " << i << "; v[" << i << "] = " << *pp << '\n';

print_seq("First partition (all even elements): ", v.cbegin(), pp);
print_seq("Second partition (all odd elements): ", pp, v.cend());
}
Output
After partitioning, v: 8 2 6 4 5 3 7 1 9
Partition point is at 4; v[4] = 5
First partition (all even elements): 8 2 6 4
Second partition (all odd elements): 5 3 7 1 9
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::partition_point() algorithm

template< class ForwardIt, class UnaryPredicate >
constexpr ForwardIt partition_point( ForwardIt first, ForwardIt last, UnaryPredicate p );

Examines the partitioned (as if by std::partition) range [first; last) and locates the end of the first partition, that is, the first element that does not satisfy p or last if all elements satisfy p.

Parameters

first
last

The partitioned range of elements to examine

policy

The execution policy to use. See execution policy for details.

p

Unary predicate which returns true for the required element.

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 InputIt, 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).

Type requirements

ForwardItLegacyForwardIterator
UnaryPredicatePredicate

Return value

The iterator past the end of the first partition within [first; last) or last if all elements satisfy p.

Complexity

Given N as std::distance(first, last):

Performs O(log(N)) applications of the predicate p.

However, for non-LegacyRandomAccessIterators, the number of iterator increments is O(N).

Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

Possible implementation

partition_point (1)
template<class ForwardIt, class UnaryPredicate>
constexpr //< since C++20
ForwardIt partition_point(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
for (auto length = std::distance(first, last); 0 < length; )
{
auto half = length / 2;
auto middle = std::next(first, half);
if (p(*middle))
{
first = std::next(middle);
length -= (half + 1);
}
else
length = half;
}

return first;
}

Notes

This algorithm is a more general form of std::lower_bound, which can be expressed in terms of std::partition_point with the predicate [&](auto const& e) { return e < value; });.

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>

auto print_seq = [](auto rem, auto first, auto last)
{
for (std::cout << rem; first != last; std::cout << *first++ << ' ') {}
std::cout << '\n';
};

int main()
{
std::array v {1, 2, 3, 4, 5, 6, 7, 8, 9};

auto is_even = [](int i) { return i % 2 == 0; };

std::partition(v.begin(), v.end(), is_even);
print_seq("After partitioning, v: ", v.cbegin(), v.cend());

const auto pp = std::partition_point(v.cbegin(), v.cend(), is_even);
const auto i = std::distance(v.cbegin(), pp);
std::cout << "Partition point is at " << i << "; v[" << i << "] = " << *pp << '\n';

print_seq("First partition (all even elements): ", v.cbegin(), pp);
print_seq("Second partition (all odd elements): ", pp, v.cend());
}
Output
After partitioning, v: 8 2 6 4 5 3 7 1 9
Partition point is at 4; v[4] = 5
First partition (all even elements): 8 2 6 4
Second partition (all odd elements): 5 3 7 1 9
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.