std::ranges::partition_copy, std::ranges::partition_copy_result - cppreference.com
Namespaces
Variants

std::ranges::partition_copy, std::ranges::partition_copy_result

From cppreference.com
 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Non-modifying sequence operations    
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17)(C++11)
(C++20)(C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
(C++11)    

Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
(C++11)
(C++17)
Lexicographical comparison operations
Permutation operations


 
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Fold operations (Helper templates)
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
       
       
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
       
       
Permutation operations
Specialized <memory> algorithms
Return types
 
Defined in header <algorithm>
Call signature
template< std::input_iterator I, std::sentinel_for<I> S,
          std::weakly_incrementable O1, std::weakly_incrementable O2,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
    requires std::indirectly_copyable<I, O1> &&
             std::indirectly_copyable<I, O2>
constexpr ranges::partition_copy_result<I, O1, O2>
    partition_copy( I first, S last, O1 d_first_true, O2 d_first_false,
                    Pred pred, Proj proj = {} );
(1) (since C++20)
template< ranges::input_range R,
          std::weakly_incrementable O1, std::weakly_incrementable O2,
          class Proj = std::identity,
          std::indirect_unary_predicate
              <std::projected<ranges::iterator_t<R>, Proj>> Pred >
    requires std::indirectly_copyable<ranges::iterator_t<R>, O1> &&
             std::indirectly_copyable<ranges::iterator_t<R>, O2>
constexpr ranges::partition_copy_result<ranges::borrowed_iterator_t<R>, O1, O2>
    partition_copy( R&& r, O1 d_first_true, O2 d_first_false,
                    Pred pred, Proj proj = {} );
(2) (since C++20)
template< /*execution-policy*/ Ep,
          std::random_access_iterator I, std::sized_sentinel_for<I> S,
          std::random_access_iterator O1, std::sized_sentinel_for<O1> OutS1,
          std::random_access_iterator O2, std::sized_sentinel_for<O2> OutS2,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
    requires std::indirectly_copyable<I, O1> && std::indirectly_copyable<I, O2>
ranges::partition_copy_result<I, O1, O2>
    partition_copy( Ep&& policy, I first, S last,
                    O1 d_first_true, OutS1 d_last_true,
                    O2 d_first_false, OutS2 d_last_false,
                    Pred pred, Proj proj = {} );
(3) (since C++26)
template< /*execution-policy*/ Ep, /*sized-random-access-range*/ R,
          /*sized-random-access-range*/ OutR1,
          /*sized-random-access-range*/ OutR2,
          class Proj = std::identity,
          std::indirect_unary_predicate
              <std::projected<ranges::iterator_t<R>, Proj>> Pred >
    requires std::indirectly_copyable<ranges::iterator_t<R>,
                                      ranges::iterator_t<OutR1>> &&
             std::indirectly_copyable<ranges::iterator_t<R>,
                                      ranges::iterator_t<OutR2>>
ranges::partition_copy_result<ranges::borrowed_iterator_t<R>,
                              ranges::borrowed_iterator_t<OutR1>,
                              ranges::borrowed_iterator_t<OutR2>>
    partition_copy( Ep&& policy, R&& r, OutR1&& d_r_true, OutR2&& d_r_false,
                    Pred pred, Proj proj = {} );
(4) (since C++26)
Helper types
template< class I, class O1, class O2 >
using partition_copy_result = ranges::in_out_out_result<I, O1, O2>;
(5) (since C++20)

For the definition of /*execution-policy*/, see this page; for the definition of /*sized-random-access-range*/, see this page.

Copies the elements from the source range [firstlast) or r to the corresponding destination ranges depending on the value returned by the predicate pred after projection by proj.

  • The elements that satisfy the predicate pred are copied to the first destination range.
  • The rest of the elements are copied to the second destination range.
1,2) The first destination range begins at d_first_true, and the second destination range begins at d_first_false.
3,4) Executed according to policy. If any of the destination ranges is exhausted before reaching the end of the source range and next element would be copied to the same destination range, the remaining elements in the source range will not be copied.
3) The first destination range is [d_first_trued_last_true), and the second destination range is [d_first_falsed_last_false).
4) The first destination range is d_r_true, and the second destination range is d_r_false.

If any two ranges among the source and destination ranges overlap, the behavior is undefined.

The function-like entities described on this page are algorithm function objects (informally known as niebloids), that is:

Parameters

first, last - the iterator-sentinel pair defining the source range
r - the source range
d_first_true - the beginning of the first destination range
d_last_true - the sentinel of the first destination range
d_r_true - the first destination range
d_first_false - the beginning of the second destination range
d_last_false - the sentinel of the second destination range
d_r_false - the second destination range
pred - the predicate to be applied to the (projected) elements
proj - the projection to be applied to the elements
policy - the execution policy to use

Return value

A ranges::partition_copy_result object where:

  • The data member in holds an iterator past the last copied element in the source range, or an iterator to the beginning of the source range is no element is copied.
  • The data member out1 holds an iterator past the last assigned element in the first destination range, or an iterator to the beginning of the first destination range is no element is assigned in that range.
  • The data member out2 holds an iterator past the last assigned element in the second destination range, or an iterator to the beginning of the second destination range is no element is assigned in that range.

Complexity

Given N as ranges::distance(first, last) or ranges::distance(r):

1,2) Exactly N applications of pred and proj.
3,4) 𝓞(N) applications of pred and proj.

Exceptions

3,4) During the execution process:
  • If the temporary memory resources required for parallelization are not available, std::bad_alloc is thrown.
  • If an uncaught exception is thrown while accessing objects via an algorithm argument, the behavior is determined by the execution policy (for standard policies, std::terminate is invoked).

Notes

For overloads (3,4), there may be a performance cost if the value type of I or R does not model copy_constructible.

Possible implementation

struct partition_copy_fn
{
    template<std::input_iterator I, std::sentinel_for<I> S,
             std::weakly_incrementable O1, std::weakly_incrementable O2,
             class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
        requires std::indirectly_copyable<I, O1> && std::indirectly_copyable<I, O2>
    constexpr ranges::partition_copy_result<I, O1, O2>
        operator()(I first, S last, O1 d_first_true, O2 d_first_false,
                   Pred pred, Proj proj = {}) const
    {
        for (; first != last; ++first)
            if (!!std::invoke(pred, std::invoke(proj, *first)))
                *d_first_true = *first, ++d_first_true;
            else
                *d_first_false = *first, ++d_first_false;
        return {std::move(first), std::move(d_first_true), std::move(d_first_false)};
    }
    
    template<ranges::input_range R,
             std::weakly_incrementable O1, std::weakly_incrementable O2,
             class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<iterator_t<R>, Proj>> Pred>
        requires std::indirectly_copyable<ranges::iterator_t<R>, O1> &&
                 std::indirectly_copyable<ranges::iterator_t<R>, O2>
    constexpr ranges::partition_copy_result<ranges::borrowed_iterator_t<R>, O1, O2>
        operator()(R&& r, O1 d_first_true, O2 d_first_false,
                   Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r),
                       std::move(d_first_true), std::move(d_first_false),
                       std::move(pred), std::move(proj));
    }
    
    template<ranges::forward_range R,
             std::weakly_incrementable O1, std::weakly_incrementable O2,
             class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<iterator_t<R>, Proj>> Pred>
        requires std::indirectly_copyable<ranges::iterator_t<R>, O1> &&
                 std::indirectly_copyable<ranges::iterator_t<R>, O2>
    constexpr ranges::partition_copy_result<ranges::borrowed_iterator_t<R>, O1, O2>
        operator()(R&& r, O1 d_first_true, O2 d_first_false,
                   Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r),
                       ranges::next(ranges::begin(r), ranges::end(r)),
                       std::move(d_first_true), std::move(d_first_false),
                       std::move(pred), std::move(proj));
    }
};

inline constexpr partition_copy_fn partition_copy{};

Example

#include <algorithm>
#include <cctype>
#include <iostream>
#include <iterator>
#include <vector>

int main()
{
    const auto in = {'N', '3', 'U', 'M', '1', 'B', '4', 'E', '1', '5', 'R', '9'};
    std::vector<int> o1(size(in)), o2(size(in));
    
    auto pred = [](char c) { return std::isalpha(c); };
    auto ret = std::ranges::partition_copy(in, o1.begin(), o2.begin(), pred);
    
    std::ostream_iterator<char> cout{std::cout, " "};
    std::cout << "in = ";
    std::ranges::copy(in, cout);
    std::cout << "\no1 = ";
    std::copy(o1.begin(), ret.out1, cout);
    std::cout << "\no2 = ";
    std::copy(o2.begin(), ret.out2, cout);
    std::cout << '\n';
}

Output:

in = N 3 U M 1 B 4 E 1 5 R 9
o1 = N U M B E R
o2 = 3 1 4 1 5 9

See also