Skip to main content

std::ranges::is_partitioned() algorithm

// (1)
constexpr bool
is_partitioned( I first, S last, Pred pred, Proj proj = {} );

// (2)
constexpr bool
is_partitioned( R&& r, Pred pred, Proj proj = {} );

The type of arguments are generic and have the following constraints:

  • I - std::input_iterator
  • S - std::sentinel_for<I>
  • R - std::ranges::input_range
  • Pred:
    • (1) - std::indirect_unary_predicate<std::projected<I, Proj>>
    • (2) - std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>>
  • Proj - (none)

The Proj template argument has a default type std::identity for all overloads.

  • (1) Returns true if all elements in the range [first; last) that satisfy the predicate pred after projection appear before all elements that don't.

    Also returns true if [first; last) is empty.

  • (2) Same as (1), but uses r as the 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.

Parameters

first
last

The range of elements to process.

r

The range of elements to process.

pred

The predicate to apply to the projected elemenets.

proj

The projection to apply to the elements.

Return value

If the range is empty or partitioned by p - true.
Otherwise, false.

Complexity

At most ranges::distance(first, last) applications of pred and proj.

Exceptions

(none)

Possible implementation

is_partitioned(1) and is_partitioned(2)
struct is_partitioned_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
constexpr bool operator()(I first, S last, Pred pred, Proj proj = {}) const
{
for (; first != last; ++first)
if (!std::invoke(pred, std::invoke(proj, *first)))
break;

for (; first != last; ++first)
if (std::invoke(pred, std::invoke(proj, *first)))
return false;

return true;
}

template<ranges::input_range R, class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred>
constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
}
};

inline constexpr auto is_partitioned = is_partitioned_fn();

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <numeric>
#include <utility>

int main()
{
std::array<int, 9> v;

auto print = [&v](bool o)
{
for (int x : v)
std::cout << x << ' ';
std::cout << (o ? "=> " : "=> not ") << "partitioned\n";
};

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

std::iota(v.begin(), v.end(), 1); // or std::ranges::iota(v, 1);
print(std::ranges::is_partitioned(v, is_even));

std::ranges::partition(v, is_even);
print(std::ranges::is_partitioned(std::as_const(v), is_even));

std::ranges::reverse(v);
print(std::ranges::is_partitioned(v.cbegin(), v.cend(), is_even));
print(std::ranges::is_partitioned(v.crbegin(), v.crend(), is_even));
}
Possible Output
1 2 3 4 5 6 7 8 9 => not partitioned
2 4 6 8 5 3 7 1 9 => partitioned
9 1 7 3 5 8 6 4 2 => not partitioned
9 1 7 3 5 8 6 4 2 => partitioned
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::ranges::is_partitioned() algorithm

// (1)
constexpr bool
is_partitioned( I first, S last, Pred pred, Proj proj = {} );

// (2)
constexpr bool
is_partitioned( R&& r, Pred pred, Proj proj = {} );

The type of arguments are generic and have the following constraints:

  • I - std::input_iterator
  • S - std::sentinel_for<I>
  • R - std::ranges::input_range
  • Pred:
    • (1) - std::indirect_unary_predicate<std::projected<I, Proj>>
    • (2) - std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>>
  • Proj - (none)

The Proj template argument has a default type std::identity for all overloads.

  • (1) Returns true if all elements in the range [first; last) that satisfy the predicate pred after projection appear before all elements that don't.

    Also returns true if [first; last) is empty.

  • (2) Same as (1), but uses r as the 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.

Parameters

first
last

The range of elements to process.

r

The range of elements to process.

pred

The predicate to apply to the projected elemenets.

proj

The projection to apply to the elements.

Return value

If the range is empty or partitioned by p - true.
Otherwise, false.

Complexity

At most ranges::distance(first, last) applications of pred and proj.

Exceptions

(none)

Possible implementation

is_partitioned(1) and is_partitioned(2)
struct is_partitioned_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
constexpr bool operator()(I first, S last, Pred pred, Proj proj = {}) const
{
for (; first != last; ++first)
if (!std::invoke(pred, std::invoke(proj, *first)))
break;

for (; first != last; ++first)
if (std::invoke(pred, std::invoke(proj, *first)))
return false;

return true;
}

template<ranges::input_range R, class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred>
constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
}
};

inline constexpr auto is_partitioned = is_partitioned_fn();

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <numeric>
#include <utility>

int main()
{
std::array<int, 9> v;

auto print = [&v](bool o)
{
for (int x : v)
std::cout << x << ' ';
std::cout << (o ? "=> " : "=> not ") << "partitioned\n";
};

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

std::iota(v.begin(), v.end(), 1); // or std::ranges::iota(v, 1);
print(std::ranges::is_partitioned(v, is_even));

std::ranges::partition(v, is_even);
print(std::ranges::is_partitioned(std::as_const(v), is_even));

std::ranges::reverse(v);
print(std::ranges::is_partitioned(v.cbegin(), v.cend(), is_even));
print(std::ranges::is_partitioned(v.crbegin(), v.crend(), is_even));
}
Possible Output
1 2 3 4 5 6 7 8 9 => not partitioned
2 4 6 8 5 3 7 1 9 => partitioned
9 1 7 3 5 8 6 4 2 => not partitioned
9 1 7 3 5 8 6 4 2 => partitioned
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.