Horizon
Loading...
Searching...
No Matches
group_by.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2013-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
14#ifndef RANGES_V3_VIEW_GROUP_BY_HPP
15#define RANGES_V3_VIEW_GROUP_BY_HPP
16
17#include <type_traits>
18#include <utility>
19
20#include <meta/meta.hpp>
21
23
33#include <range/v3/utility/static_const.hpp>
38
39#include <range/v3/detail/config.hpp>
40#include <range/v3/detail/prologue.hpp>
41
42namespace ranges
43{
44 // TODO group_by could support Input ranges by keeping mutable state in
45 // the range itself. The group_by view would then be mutable-only and
46 // Input.
47
50 template<typename Rng, typename Fun>
52 : view_facade<group_by_view<Rng, Fun>,
53 is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
54 {
55 private:
56 friend range_access;
57 Rng rng_;
58 // cached version of the end of the first subrange / start of the second subrange
59 detail::non_propagating_cache<iterator_t<Rng>> second_;
60 semiregular_box_t<Fun> fun_;
61
62 struct pred
63 {
64 iterator_t<Rng> first_;
65 semiregular_box_ref_or_val_t<Fun, false> fun_;
66 bool operator()(range_reference_t<Rng> r) const
67 {
68 return invoke(fun_, *first_, r);
69 }
70 };
71
72 struct cursor
73 {
74 private:
75 friend range_access;
76 friend group_by_view;
77 iterator_t<Rng> cur_;
78 iterator_t<Rng> next_cur_;
79 sentinel_t<Rng> last_;
80 semiregular_box_ref_or_val_t<Fun, false> fun_;
81
82 struct mixin : basic_mixin<cursor>
83 {
84 mixin() = default;
85 #ifndef _MSC_VER
86 using basic_mixin<cursor>::basic_mixin;
87 #else
88 constexpr explicit mixin(cursor && cur)
89 : basic_mixin<cursor>(static_cast<cursor &&>(cur))
90 {}
91 constexpr explicit mixin(cursor const & cur)
93 {}
94 #endif
95 iterator_t<Rng> base() const
96 {
97 return this->get().cur_;
98 }
99 };
100
101 #ifdef _MSC_VER
102 template<typename I = iterator_t<Rng>>
103 subrange<I> read() const
104 {
105 return {cur_, next_cur_};
106 }
107 #else
108 subrange<iterator_t<Rng>> read() const
109 {
110 return {cur_, next_cur_};
111 }
112 #endif
113 void next()
114 {
115 cur_ = next_cur_;
116 next_cur_ = cur_ != last_
117 ? find_if_not(ranges::next(cur_), last_, pred{cur_, fun_})
118 : cur_;
119 }
120
121 bool equal(default_sentinel_t) const
122 {
123 return cur_ == last_;
124 }
125 bool equal(cursor const & that) const
126 {
127 return cur_ == that.cur_;
128 }
129 cursor(semiregular_box_ref_or_val_t<Fun, false> fun, iterator_t<Rng> first,
130 iterator_t<Rng> next_cur, sentinel_t<Rng> last)
131 : cur_(first)
132 , next_cur_(next_cur)
133 , last_(last)
134 , fun_(fun)
135 {}
136
137 public:
138 cursor() = default;
139 };
140 cursor begin_cursor()
141 {
142 auto b = ranges::begin(rng_);
143 auto e = ranges::end(rng_);
144 if(!second_)
145 {
146 second_ = b != e ? find_if_not(ranges::next(b), e, pred{b, fun_}) : b;
147 }
148 return {fun_, b, *second_, e};
149 }
150
151 public:
152 group_by_view() = default;
153 constexpr group_by_view(Rng rng, Fun fun)
154 : rng_(std::move(rng))
155 , fun_(std::move(fun))
156 {}
157 Rng base() const
158 {
159 return rng_;
160 }
161 };
162
163#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
164 template(typename Rng, typename Fun)(
165 requires copy_constructible<Fun>)
166 group_by_view(Rng &&, Fun)
167 ->group_by_view<views::all_t<Rng>, Fun>;
168#endif
169
170 namespace views
171 {
173 {
174 template(typename Rng, typename Fun)(
177 RANGES_DEPRECATED(
178 "views::group_by is deprecated. Please use views::chunk_by instead. "
179 "Note that views::chunk_by evaluates the predicate between adjacent "
180 "elements.")
181 constexpr group_by_view<all_t<Rng>, Fun> operator()(Rng && rng, Fun fun) const
182 {
183 return {all(static_cast<Rng &&>(rng)), std::move(fun)};
184 }
185 };
186
188 {
189 using group_by_base_fn::operator();
190
191 template<typename Fun>
192 RANGES_DEPRECATED(
193 "views::group_by is deprecated. Please use views::chunk_by instead. "
194 "Note that views::chunk_by evaluates the predicate between adjacent "
195 "elements.")
196 constexpr auto operator()(Fun fun) const
197 {
198 return make_view_closure(bind_back(group_by_base_fn{}, std::move(fun)));
199 }
200 };
201
204 RANGES_INLINE_VARIABLE(group_by_fn, group_by)
205 } // namespace views
207} // namespace ranges
208
209#include <range/v3/detail/epilogue.hpp>
210#include <range/v3/detail/satisfy_boost_range.hpp>
211RANGES_SATISFY_BOOST_RANGE(::ranges::group_by_view)
212
213#endif
The forward_range concept.
The indirect_relation concept.
The viewable_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
Tiny meta-programming library.
Definition basic_iterator.hpp:47
Definition default_sentinel.hpp:26
Definition group_by.hpp:54
Definition subrange.hpp:196
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition facade.hpp:66
Definition group_by.hpp:173
Definition group_by.hpp:188