1 /// \file
2 // Range v3 library
3 //
4 //  Copyright Eric Niebler 2014-present
5 //
6 //  Use, modification and distribution is subject to the
7 //  Boost Software License, Version 1.0. (See accompanying
8 //  file LICENSE_1_0.txt or copy at
9 //  http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 #ifndef RANGES_V3_ALGORITHM_PARTITION_COPY_HPP
14 #define RANGES_V3_ALGORITHM_PARTITION_COPY_HPP
15 
16 #include <tuple>
17 
18 #include <meta/meta.hpp>
19 
20 #include <range/v3/range_fwd.hpp>
21 
22 #include <range/v3/algorithm/result_types.hpp>
23 #include <range/v3/functional/identity.hpp>
24 #include <range/v3/functional/invoke.hpp>
25 #include <range/v3/iterator/concepts.hpp>
26 #include <range/v3/iterator/operations.hpp>
27 #include <range/v3/iterator/traits.hpp>
28 #include <range/v3/range/access.hpp>
29 #include <range/v3/range/concepts.hpp>
30 #include <range/v3/range/dangling.hpp>
31 #include <range/v3/range/traits.hpp>
32 #include <range/v3/utility/static_const.hpp>
33 
34 #include <range/v3/detail/prologue.hpp>
35 
36 namespace ranges
37 {
38     /// \addtogroup group-algorithms
39     /// @{
40     template<typename I, typename O0, typename O1>
41     using partition_copy_result = detail::in_out1_out2_result<I, O0, O1>;
42 
RANGES_FUNC_BEGIN(partition_copy)43     RANGES_FUNC_BEGIN(partition_copy)
44 
45         /// \brief function template \c partition_copy
46         template(typename I,
47                  typename S,
48                  typename O0,
49                  typename O1,
50                  typename C,
51                  typename P = identity)(
52             /// \pre
53             requires input_iterator<I> AND sentinel_for<S, I> AND
54                 weakly_incrementable<O0> AND weakly_incrementable<O1> AND
55                 indirectly_copyable<I, O0> AND indirectly_copyable<I, O1> AND
56                 indirect_unary_predicate<C, projected<I, P>>)
57         partition_copy_result<I, O0, O1> RANGES_FUNC(partition_copy)(
58             I first, S last, O0 o0, O1 o1, C pred, P proj = P{})
59         {
60             for(; first != last; ++first)
61             {
62                 auto && x = *first;
63                 if(invoke(pred, invoke(proj, x)))
64                 {
65                     *o0 = (decltype(x) &&)x;
66                     ++o0;
67                 }
68                 else
69                 {
70                     *o1 = (decltype(x) &&)x;
71                     ++o1;
72                 }
73             }
74             return {first, o0, o1};
75         }
76 
77         /// \overload
78         template(typename Rng,
79                  typename O0,
80                  typename O1,
81                  typename C,
82                  typename P = identity)(
83             /// \pre
84             requires input_range<Rng> AND weakly_incrementable<O0> AND
85                 weakly_incrementable<O1> AND indirectly_copyable<iterator_t<Rng>, O0> AND
86                 indirectly_copyable<iterator_t<Rng>, O1> AND
87                 indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
88         partition_copy_result<borrowed_iterator_t<Rng>, O0, O1> //
RANGES_FUNC(partition_copy)89         RANGES_FUNC(partition_copy)(Rng && rng, O0 o0, O1 o1, C pred, P proj = P{})
90         {
91             return (*this)(begin(rng),
92                            end(rng),
93                            std::move(o0),
94                            std::move(o1),
95                            std::move(pred),
96                            std::move(proj));
97         }
98 
99     RANGES_FUNC_END(partition_copy)
100 
101     namespace cpp20
102     {
103         using ranges::partition_copy;
104         using ranges::partition_copy_result;
105     } // namespace cpp20
106     /// @}
107 } // namespace ranges
108 
109 #include <range/v3/detail/epilogue.hpp>
110 
111 #endif
112