Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/algorithm/ranges/partition copy"

From cppreference.com
< cpp‎ | algorithm‎ | ranges
m (Example: reducing the code size with ostream_iterator<char>)
m (Possible implementation: fmt)
 
(8 intermediate revisions by 5 users not shown)
Line 2: Line 2:
 
{{cpp/algorithm/ranges/navbar}}
 
{{cpp/algorithm/ranges/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | algorithm}}
+
{{dcl header|algorithm}}
{{dcl h | Call signature}}
+
{{dcl h|Call signature}}
{{dcl | since=c++20 | num=1 |1=
+
{{dcl|since=c++20|num=1|1=
template <std::input_iterator I, std::sentinel_for<I> S,
+
template< std::input_iterator I, std::sentinel_for<I> S,
        std::weakly_incrementable O1, std::weakly_incrementable O2,
+
          std::weakly_incrementable O1, std::weakly_incrementable O2,
        class Proj = std::identity, std::indirect_unary_predicate<
+
          class Proj = std::identity,
        std::projected<I, Proj>> Pred>
+
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
requires std::indirectly_copyable<I, O1> && std::indirectly_copyable<I, O2>
+
requires std::indirectly_copyable<I, O1> &&
constexpr ranges::partition_copy_result<I, O1, O2>
+
        std::indirectly_copyable<I, O2>
ranges::partition_copy( I first, S last, O1 out_true, O2 out_false, Pred pred, Proj proj = {} );
+
constexpr partition_copy_result<I, O1, O2>
 +
    partition_copy( I first, S last, O1 out_true, O2 out_false,
 +
                    Pred pred, Proj proj = {} );
 
}}
 
}}
{{dcl | since=c++20 | num=2 |1=
+
{{dcl|since=c++20|num=2|1=
template<ranges::input_range R, std::weakly_incrementable O1, std::weakly_incrementable O2,
+
template< ranges::input_range R,
        class Proj = std::identity,
+
          std::weakly_incrementable O1, std::weakly_incrementable O2,
        std::indirect_unary_predicate<std::projected<iterator_t<R>, Proj>> Pred>
+
          class Proj = std::identity,
 +
          std::indirect_unary_predicate<std::projected<iterator_t<R>, Proj>> Pred >
 
requires std::indirectly_copyable<ranges::iterator_t<R>, O1> &&
 
requires std::indirectly_copyable<ranges::iterator_t<R>, O1> &&
 
         std::indirectly_copyable<ranges::iterator_t<R>, O2>
 
         std::indirectly_copyable<ranges::iterator_t<R>, O2>
constexpr ranges::partition_copy_result<ranges::borrowed_iterator_t<R>, O1, O2>
+
constexpr partition_copy_result<ranges::borrowed_iterator_t<R>, O1, O2>
ranges::partition_copy( R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {} );
+
    partition_copy( R&& r, O1 out_true, O2 out_false,
 +
                    Pred pred, Proj proj = {} );
 
}}
 
}}
{{dcl h | Helper types}}
+
{{dcl h|Helper types}}
{{dcl | num=3 | since=c++20 |1=
+
{{dcl|num=3|since=c++20|1=
template<class I, class O1, class O2>
+
template< class I, class O1, class O2 >
 
using partition_copy_result = ranges::in_out_out_result<I, O1, O2>;
 
using partition_copy_result = ranges::in_out_out_result<I, O1, O2>;
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
@1@ Copies the elements from the input range {{tt|[first, last)}} to two different output ranges depending on the value returned by the predicate {{tt|pred}}. The projected by {{tt|proj}} elements that satisfy the predicate {{tt|pred}} are copied to the range beginning at {{tt|out_true}}. The rest of the elements are copied to the range beginning at {{tt|out_false}}.
+
@1@ Copies the elements from the input range {{range|first|last}} to two different output ranges depending on the value returned by the predicate {{c|pred}}. The elements that satisfy the predicate {{c|pred}} after projection by {{c|proj}} are copied to the range beginning at {{c|out_true}}. The rest of the elements are copied to the range beginning at {{c|out_false}}. The behavior is undefined if the input range overlaps either of the output ranges.
  
@@''Precondition:'' the input range does not overlap either of the output ranges.
+
@2@ Same as {{v|1}}, but uses {{c|r}} as the source range, as if using {{c|ranges::begin(r)}} as {{c|first}}, and {{c|ranges::end(r)}} as {{c|last}}.
 
+
@2@ Same as {{v|1}}, but uses {{tt|r}} as the soruce range, as if using {{c|ranges::begin(r)}} as {{tt|first}}, and {{c|ranges::end(r)}} as {{tt|last}}.
+
  
 
{{cpp/ranges/niebloid}}
 
{{cpp/ranges/niebloid}}
Line 39: Line 41:
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | first, last | the input range of elements to copy from}}
+
{{par|first, last|the input range of elements to copy from}}
{{par | r | the input range of elements to copy from}}
+
{{par|r|the input range of elements to copy from}}
{{par | out_true | the beginning of the output range for the elements that satisfy {{tt|pred}} }}
+
{{par|out_true|the beginning of the output range for the elements that satisfy {{c|pred}}}}
{{par | out_false | the beginning of the output range for the elements that do not satisfy {{tt|pred}} }}
+
{{par|out_false|the beginning of the output range for the elements that do not satisfy {{c|pred}}}}
{{par | pred | predicate to apply to the projected elements}}
+
{{par|pred|predicate to apply to the projected elements}}
{{par | proj | projection to apply to the elements.}}
+
{{par|proj|projection to apply to the elements}}
 
{{par end}}
 
{{par end}}
  
 
===Return value===
 
===Return value===
An object equal to {{tt|{last, o1, o2},}} where {{tt|o1}} and {{tt|o2}} are the ends of the output ranges respectivelly, after the copying is complete.
+
{{c|{last, o1, o2} }}, where {{tt|o1}} and {{tt|o2}} are the ends of the output ranges respectively, after the copying is complete.
  
 
===Complexity===
 
===Complexity===
Exactly {{c|ranges::distance(first, last)}} applications of the corresponding predicate {{tt|comp}} and any projection {{tt|proj}}.
+
Exactly {{c|ranges::distance(first, last)}} applications of the corresponding predicate {{c|comp}} and any projection {{c|proj}}.
  
 
<!-- ===Exceptions=== -->
 
<!-- ===Exceptions=== -->
 
===Possible implementation===
 
===Possible implementation===
{{eq fun | 1=
+
{{eq fun|1=
struct partition_copy_fn {
+
struct partition_copy_fn
  template <std::input_iterator I, std::sentinel_for<I> S,
+
{
          std::weakly_incrementable O1, std::weakly_incrementable O2,
+
    template<std::input_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity, std::indirect_unary_predicate<
+
            std::weakly_incrementable O1, std::weakly_incrementable O2,
          std::projected<I, Proj>> Pred>
+
            class Proj = std::identity, std::indirect_unary_predicate<
  requires std::indirectly_copyable<I, O1> && std::indirectly_copyable<I, O2>
+
            std::projected<I, Proj>> Pred>
  constexpr ranges::partition_copy_result<I, O1, O2>
+
    requires std::indirectly_copyable<I, O1> && std::indirectly_copyable<I, O2>
  operator()( I first, S last, O1 out_true, O2 out_false, Pred pred, Proj proj = {} ) const {
+
    constexpr ranges::partition_copy_result<I, O1, O2>
      for (; first != last; ++first)
+
        operator()(I first, S last, O1 out_true, O2 out_false,
          if (!!std::invoke(pred, std::invoke(proj, *first)))
+
                  Pred pred, Proj proj = {}) const
              *out_true = *first, ++out_true;
+
    {
          else
+
        for (; first != last; ++first)
              *out_false = *first, ++out_false;
+
            if (!!std::invoke(pred, std::invoke(proj, *first)))
      return {std::move(first), std::move(out_true), std::move(out_false)};
+
                *out_true = *first, ++out_true;
  }
+
            else
 +
                *out_false = *first, ++out_false;
 +
        return {std::move(first), std::move(out_true), std::move(out_false)};
 +
    }
  
  template<ranges::input_range R, std::weakly_incrementable O1, std::weakly_incrementable O2,
+
    template<ranges::input_range R,
          class Proj = std::identity,
+
            std::weakly_incrementable O1, std::weakly_incrementable O2,
          std::indirect_unary_predicate<std::projected<iterator_t<R>, Proj>> Pred>
+
            class Proj = std::identity,
  requires std::indirectly_copyable<ranges::iterator_t<R>, O1> &&
+
            std::indirect_unary_predicate<std::projected<iterator_t<R>, Proj>> Pred>
          std::indirectly_copyable<ranges::iterator_t<R>, O2>
+
    requires std::indirectly_copyable<ranges::iterator_t<R>, O1> &&
  constexpr ranges::partition_copy_result<ranges::borrowed_iterator_t<R>, O1, O2>
+
            std::indirectly_copyable<ranges::iterator_t<R>, O2>
  operator()( R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {} ) const {
+
    constexpr ranges::partition_copy_result<ranges::borrowed_iterator_t<R>, O1, O2>
      return (*this)(ranges::begin(r), ranges::end(r), std::move(out_true),
+
        operator()(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {}) const
                    std::move(out_false), std::move(pred), std::move(proj));
+
    {
  }
+
        return (*this)(ranges::begin(r), ranges::end(r), std::move(out_true),
 +
                      std::move(out_false), std::move(pred), std::move(proj));
 +
    }
 
};
 
};
  
inline constexpr partition_copy_fn partition_copy{};
+
inline constexpr partition_copy_fn partition_copy {};
 
}}
 
}}
  
Line 92: Line 99:
 
#include <cctype>
 
#include <cctype>
 
#include <iostream>
 
#include <iostream>
#include <vector>
 
 
#include <iterator>
 
#include <iterator>
 +
#include <vector>
  
 
int main()
 
int main()
Line 101: Line 108:
 
     std::vector<int> o1(size(in)), o2(size(in));
 
     std::vector<int> o1(size(in)), o2(size(in));
  
     auto pred = [](char c){ return std::isalpha(c); };
+
     auto pred = [](char c) { return std::isalpha(c); };
  
 
     auto ret = std::ranges::partition_copy(in, o1.begin(), o2.begin(), pred);
 
     auto ret = std::ranges::partition_copy(in, o1.begin(), o2.begin(), pred);
Line 114: Line 121:
 
     std::cout << '\n';
 
     std::cout << '\n';
 
}
 
}
| output=
+
|output=
 
in = N 3 U M 1 B 4 E 1 5 R 9
 
in = N 3 U M 1 B 4 E 1 5 R 9
 
o1 = N U M B E R
 
o1 = N U M B E R
Line 122: Line 129:
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/algorithm/ranges/dsc partition}}
+
{{dsc inc|cpp/algorithm/ranges/dsc partition}}
{{dsc inc | cpp/algorithm/ranges/dsc stable_partition}}
+
{{dsc inc|cpp/algorithm/ranges/dsc stable_partition}}
{{dsc inc | cpp/algorithm/ranges/dsc copy}}
+
{{dsc inc|cpp/algorithm/ranges/dsc copy}}
{{dsc inc | cpp/algorithm/ranges/dsc remove_copy}}
+
{{dsc inc|cpp/algorithm/ranges/dsc remove_copy}}
{{dsc inc | cpp/algorithm/dsc partition_copy}}
+
{{dsc inc|cpp/algorithm/dsc partition_copy}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 10:26, 18 December 2023

 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
(C++11)                (C++11)(C++11)

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
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
C library
Numeric operations
Operations on uninitialized memory
 
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
partition_copy
  
Sorting operations
Binary search operations (on sorted ranges)
       
       
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
       
       
Permutation operations
Fold operations
Numeric operations
(C++23)            
Operations on uninitialized storage
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 partition_copy_result<I, O1, O2>
    partition_copy( I first, S last, O1 out_true, O2 out_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<iterator_t<R>, Proj>> Pred >
requires std::indirectly_copyable<ranges::iterator_t<R>, O1> &&
         std::indirectly_copyable<ranges::iterator_t<R>, O2>
constexpr partition_copy_result<ranges::borrowed_iterator_t<R>, O1, O2>
    partition_copy( R&& r, O1 out_true, O2 out_false,

                    Pred pred, Proj proj = {} );
(2) (since C++20)
Helper types
template< class I, class O1, class O2 >
using partition_copy_result = ranges::in_out_out_result<I, O1, O2>;
(3) (since C++20)
1) Copies the elements from the input range [firstlast) to two different output ranges depending on the value returned by the predicate pred. The elements that satisfy the predicate pred after projection by proj are copied to the range beginning at out_true. The rest of the elements are copied to the range beginning at out_false. The behavior is undefined if the input range overlaps either of the output ranges.
2) Same as (1), but uses r as the source 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, that is:

In practice, they may be implemented as function objects, or with special compiler extensions.

Contents

[edit] Parameters

first, last - the input range of elements to copy from
r - the input range of elements to copy from
out_true - the beginning of the output range for the elements that satisfy pred
out_false - the beginning of the output range for the elements that do not satisfy pred
pred - predicate to apply to the projected elements
proj - projection to apply to the elements

[edit] Return value

{last, o1, o2}, where o1 and o2 are the ends of the output ranges respectively, after the copying is complete.

[edit] Complexity

Exactly ranges::distance(first, last) applications of the corresponding predicate comp and any projection proj.

[edit] 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 out_true, O2 out_false,
                   Pred pred, Proj proj = {}) const
    {
        for (; first != last; ++first)
            if (!!std::invoke(pred, std::invoke(proj, *first)))
                *out_true = *first, ++out_true;
            else
                *out_false = *first, ++out_false;
        return {std::move(first), std::move(out_true), std::move(out_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 out_true, O2 out_false, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), std::move(out_true),
                       std::move(out_false), std::move(pred), std::move(proj));
    }
};
 
inline constexpr partition_copy_fn partition_copy {};

[edit] 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

[edit] See also

divides a range of elements into two groups
(niebloid)[edit]
divides elements into two groups while preserving their relative order
(niebloid)[edit]
copies a range of elements to a new location
(niebloid)[edit]
copies a range of elements omitting those that satisfy specific criteria
(niebloid)[edit]
copies a range dividing the elements into two groups
(function template) [edit]