Horizon
Loading...
Searching...
No Matches
iterator_range.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_ITERATOR_RANGE_HPP
15#define RANGES_V3_ITERATOR_RANGE_HPP
16
17#include <type_traits>
18#include <utility>
19
20#include <meta/meta.hpp>
21
22#include <concepts/concepts.hpp>
23
25
29#include <range/v3/utility/static_const.hpp>
31
32RANGES_DEPRECATED_HEADER(
33 "This header is deprecated. Please switch to subrange in "
34 "<range/v3/view/subrange.hpp>.")
35
36#include <range/v3/detail/prologue.hpp>
37
38namespace ranges
39{
42
43 template<typename I, typename S>
44 RANGES_INLINE_VAR constexpr bool enable_borrowed_range<iterator_range<I, S>> = true;
45
46 template<typename I, typename S>
47 RANGES_INLINE_VAR constexpr bool enable_borrowed_range<sized_iterator_range<I, S>> =
48 true;
49
50 template<typename I, typename S /*= I*/>
51 struct RANGES_EMPTY_BASES iterator_range
52 : view_interface<iterator_range<I, S>,
53 same_as<S, unreachable_sentinel_t> ? infinite : unknown>
54 , compressed_pair<I, S>
55 {
56 private:
57 template<typename, typename>
58 friend struct iterator_range;
59 template<typename, typename>
60 friend struct sized_iterator_range;
61 compressed_pair<I, S> & base() noexcept
62 {
63 return *this;
64 }
65 compressed_pair<I, S> const & base() const noexcept
66 {
67 return *this;
68 }
69 using compressed_pair<I, S>::first;
70 using compressed_pair<I, S>::second;
71
72 public:
73 using iterator = I;
74 using sentinel = S;
76 using const_iterator = I; // Mostly to avoid spurious errors in Boost.Range
78
79 constexpr I & begin() &
80 {
81 return this->first();
82 }
83 constexpr I const & begin() const &
84 {
85 return this->first();
86 }
87
88 constexpr S & end() &
89 {
90 return this->second();
91 }
92 constexpr S const & end() const &
93 {
94 return this->second();
95 }
96
97 iterator_range() = default;
98 constexpr iterator_range(I first, S last)
99 : compressed_pair<I, S>{detail::move(first), detail::move(last)}
100 {}
101 template(typename X, typename Y)(
102 requires constructible_from<I, X> AND constructible_from<S, Y>)
103 constexpr iterator_range(iterator_range<X, Y> rng)
104 : compressed_pair<I, S>{detail::move(rng.begin()), detail::move(rng.end())}
105 {}
106 template(typename X, typename Y)(
107 requires constructible_from<I, X> AND constructible_from<S, Y>)
108 constexpr explicit iterator_range(std::pair<X, Y> rng)
109 : compressed_pair<I, S>{detail::move(rng.first), detail::move(rng.second)}
110 {}
111 template(typename X, typename Y)(
112 requires assignable_from<I &, X> AND assignable_from<S &, Y>)
113 iterator_range & operator=(iterator_range<X, Y> rng)
114 {
115 base().first() = std::move(rng.base()).first();
116 base().second() = std::move(rng.base()).second();
117 return *this;
118 }
119 template(typename X, typename Y)(
120 requires convertible_to<I, X> AND convertible_to<S, Y>)
121 constexpr operator std::pair<X, Y>() const
122 {
123 return {base().first(), base().second()};
124 }
125 constexpr bool empty() const
126 {
127 return base().first() == base().second();
128 }
129 };
130
131 // Like iterator_range, but with a known size. The first and second members
132 // are private to prevent inadvertent violations of the class invariant.
133 //
134 // Class invariant:
135 // distance(begin(), end()) == size()
136 //
137 template<typename I, typename S /* = I */>
138 struct sized_iterator_range
139 : view_interface<sized_iterator_range<I, S>, finite>
140 {
141 using size_type = detail::iter_size_t<I>;
142 using iterator = I;
143 using sentinel = S;
144#ifndef RANGES_DOXYGEN_INVOKED
145 using const_iterator = I; // Mostly to avoid spurious errors in Boost.Range
146#endif
147
148 private:
149 template<typename X, typename Y>
150 friend struct sized_iterator_range;
151 iterator_range<I, S> rng_;
152 size_type size_;
153
154 public:
155 sized_iterator_range() = default;
156 RANGES_NDEBUG_CONSTEXPR sized_iterator_range(I first, S last, size_type size)
157 : rng_{detail::move(first), detail::move(last)}
158 , size_(size)
159 {
160#ifndef NDEBUG
161 RANGES_ASSERT(!(bool)forward_iterator<I> ||
162 static_cast<size_type>(ranges::distance(rng_)) == size_);
163#endif
164 }
165 template(typename X, typename Y)(
166 requires constructible_from<I, X> AND constructible_from<S, Y>)
167 RANGES_NDEBUG_CONSTEXPR sized_iterator_range(std::pair<X, Y> rng, size_type size)
168 : sized_iterator_range{detail::move(rng).first, detail::move(rng).second, size}
169 {}
170 template(typename X, typename Y)(
171 requires constructible_from<I, X> AND constructible_from<S, Y>)
172 RANGES_NDEBUG_CONSTEXPR sized_iterator_range(iterator_range<X, Y> rng,
173 size_type size)
174 : sized_iterator_range{detail::move(rng).first(),
175 detail::move(rng).second,
176 size}
177 {}
178 template(typename X, typename Y)(
179 requires constructible_from<I, X> AND constructible_from<S, Y>)
180 RANGES_NDEBUG_CONSTEXPR sized_iterator_range(sized_iterator_range<X, Y> rng)
181 : sized_iterator_range{detail::move(rng).rng_.first(),
182 detail::move(rng).rng_.second,
183 rng.size_}
184 {}
185 template(typename X, typename Y)(
186 requires assignable_from<I &, X> AND assignable_from<S &, Y>)
187 sized_iterator_range & operator=(sized_iterator_range<X, Y> rng)
188 {
189 rng_ = detail::move(rng).rng_;
190 size_ = rng.size_;
191 return *this;
192 }
193 I begin() const
194 {
195 return rng_.begin();
196 }
197 S end() const
198 {
199 return rng_.end();
200 }
201 size_type size() const noexcept
202 {
203 return size_;
204 }
205 template(typename X, typename Y)(
206 requires convertible_to<I, X> AND convertible_to<S, Y>)
207 constexpr operator std::pair<X, Y>() const
208 {
209 return rng_;
210 }
211 template(typename X, typename Y)(
212 requires convertible_to<I, X> AND convertible_to<S, Y>)
213 constexpr operator iterator_range<X, Y>() const
214 {
215 return rng_;
216 }
217 constexpr operator iterator_range<I, S> const &() const & noexcept
218 {
219 return rng_;
220 }
221 // clang-format off
223 template(std::size_t N)(
224 requires (N < 2)) //
225 friend constexpr auto CPP_auto_fun(get)(sized_iterator_range const &p)
226 (
227 // return ranges::get<N>(p.rng_)
228 return ranges::get<N>(p.*&sized_iterator_range::rng_) // makes clang happy
229 )
230 // clang-format on
232 template(std::size_t N)(
233 requires (N == 2)) //
234 friend constexpr size_type get(sized_iterator_range const & p) noexcept
235 {
236 return p.size();
237 }
238 };
239
240 struct make_iterator_range_fn
241 {
243 template(typename I, typename S)(
244 requires sentinel_for<S, I>)
245 constexpr iterator_range<I, S> operator()(I first, S last) const
246 {
247 return {detail::move(first), detail::move(last)};
248 }
249
251 template(typename I, typename S)(
252 requires sentinel_for<S, I>)
253 constexpr sized_iterator_range<I, S> //
254 operator()(I first, S last, detail::iter_size_t<I> sz) const
255 {
256 return {detail::move(first), detail::move(last), sz};
257 }
258 };
259
261 RANGES_INLINE_VARIABLE(make_iterator_range_fn, make_iterator_range)
262
263 // TODO add specialization of range_cardinality for when we can determine the range is
264 // infinite
265
266
267} // namespace ranges
268
269// The standard is inconsistent about whether these are classes or structs
270RANGES_DIAGNOSTIC_PUSH
271RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
272
274namespace std
275{
276 template<typename I, typename S>
277 struct tuple_size<::ranges::iterator_range<I, S>> : std::integral_constant<size_t, 2>
278 {};
279
280 template<typename I, typename S>
281 struct tuple_element<0, ::ranges::iterator_range<I, S>>
282 {
283 using type = I;
284 };
285
286 template<typename I, typename S>
287 struct tuple_element<1, ::ranges::iterator_range<I, S>>
288 {
289 using type = S;
290 };
291
292 template<typename I, typename S>
293 struct tuple_size<::ranges::sized_iterator_range<I, S>>
294 : std::integral_constant<size_t, 3>
295 {};
296
297 template<typename I, typename S>
298 struct tuple_element<0, ::ranges::sized_iterator_range<I, S>>
299 {
300 using type = I;
301 };
302
303 template<typename I, typename S>
304 struct tuple_element<1, ::ranges::sized_iterator_range<I, S>>
305 {
306 using type = S;
307 };
308
309 template<typename I, typename S>
310 struct tuple_element<2, ::ranges::sized_iterator_range<I, S>>
311 {
312 using type = typename ::ranges::sized_iterator_range<I, S>::size_type;
313 };
314} // namespace std
316
317RANGES_DIAGNOSTIC_POP
318
319#include <range/v3/detail/epilogue.hpp>
320
321#endif
front< Pair > first
Retrieve the first element of the pair Pair.
Definition meta.hpp:2251
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition meta.hpp:1696
front< pop_front< Pair > > second
Retrieve the first element of the pair Pair.
Definition meta.hpp:2256
bool_< 0==size< L >::type::value > empty
An Boolean integral constant wrapper around true if L is an empty type list; false,...
Definition meta.hpp:2231
Tiny meta-programming library.
Definition range_fwd.hpp:591