Horizon
Loading...
Searching...
No Matches
range_access.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2014-present
5// Copyright Casey Carter 2016
6//
7// Use, modification and distribution is subject to the
8// Boost Software License, Version 1.0. (See accompanying
9// file LICENSE_1_0.txt or copy at
10// http://www.boost.org/LICENSE_1_0.txt)
11//
12// Project home: https://github.com/ericniebler/range-v3
13//
14
15#ifndef RANGES_V3_DETAIL_RANGE_ACCESS_HPP
16#define RANGES_V3_DETAIL_RANGE_ACCESS_HPP
17
18#include <cstddef>
19#include <utility>
20
21#include <meta/meta.hpp>
22
23#include <concepts/concepts.hpp>
24
26
28
29#include <range/v3/detail/prologue.hpp>
30
31namespace ranges
32{
35 struct range_access
36 {
38 private:
39 template<typename T>
40 static std::false_type single_pass_2_(long);
41 template<typename T>
42 static typename T::single_pass single_pass_2_(int);
43
44 template<typename T>
45 struct single_pass_
46 {
47 using type = decltype(range_access::single_pass_2_<T>(42));
48 };
49
50 template<typename T>
51 static std::false_type contiguous_2_(long);
52 template<typename T>
53 static typename T::contiguous contiguous_2_(int);
54
55 template<typename T>
56 struct contiguous_
57 {
58 using type = decltype(range_access::contiguous_2_<T>(42));
59 };
60
61 template<typename T>
62 static basic_mixin<T> mixin_base_2_(long);
63 template<typename T>
64 static typename T::mixin mixin_base_2_(int);
65
66 template<typename Cur>
67 struct mixin_base_
68 {
69 using type = decltype(range_access::mixin_base_2_<Cur>(42));
70 };
71
72
73 public:
74 template<typename Cur>
75 using single_pass_t = meta::_t<single_pass_<Cur>>;
76
77 template<typename Cur>
78 using contiguous_t = meta::_t<contiguous_<Cur>>;
79
80 template<typename Cur>
81 using mixin_base_t = meta::_t<mixin_base_<Cur>>;
82
83 // clang-format off
84 template<typename Rng>
85 static constexpr auto CPP_auto_fun(begin_cursor)(Rng &rng)
86 (
87 return rng.begin_cursor()
88 )
89 template<typename Rng>
90 static constexpr auto CPP_auto_fun(end_cursor)(Rng &rng)
91 (
92 return rng.end_cursor()
93 )
94
95 template<typename Rng>
96 static constexpr auto CPP_auto_fun(begin_adaptor)(Rng &rng)
97 (
98 return rng.begin_adaptor()
99 )
100 template<typename Rng>
101 static constexpr auto CPP_auto_fun(end_adaptor)(Rng &rng)
102 (
103 return rng.end_adaptor()
104 )
105
106 template<typename Cur>
107 static constexpr auto CPP_auto_fun(read)(Cur const &pos)
108 (
109 return pos.read()
110 )
111 template<typename Cur>
112 static constexpr auto CPP_auto_fun(arrow)(Cur const &pos)
113 (
114 return pos.arrow()
115 )
116 template<typename Cur>
117 static constexpr auto CPP_auto_fun(move)(Cur const &pos)
118 (
119 return pos.move()
120 )
121 template<typename Cur, typename T>
122 static constexpr auto CPP_auto_fun(write)(Cur &pos, T &&t)
123 (
124 return pos.write((T &&) t)
125 )
126 template<typename Cur>
127 static constexpr auto CPP_auto_fun(next)(Cur & pos)
128 (
129 return pos.next()
130 )
131 template<typename Cur, typename O>
132 static constexpr auto CPP_auto_fun(equal)(Cur const &pos, O const &other)
133 (
134 return pos.equal(other)
135 )
136 template<typename Cur>
137 static constexpr auto CPP_auto_fun(prev)(Cur & pos)
138 (
139 return pos.prev()
140 )
141 template<typename Cur, typename D>
142 static constexpr auto CPP_auto_fun(advance)(Cur & pos, D n)
143 (
144 return pos.advance(n)
145 )
146 template<typename Cur, typename O>
147 static constexpr auto CPP_auto_fun(distance_to)(Cur const &pos, O const &other)
148 (
149 return pos.distance_to(other)
150 )
151
152 private:
153 template<typename Cur>
154 using sized_cursor_difference_t = decltype(
155 range_access::distance_to(std::declval<Cur>(), std::declval<Cur>()));
156 // clang-format on
157
158 template<typename T>
159 static std::ptrdiff_t cursor_difference_2_(detail::ignore_t);
160 template<typename T>
161 static sized_cursor_difference_t<T> cursor_difference_2_(long);
162 template<typename T>
163 static typename T::difference_type cursor_difference_2_(int);
164
165 template<typename T>
166 using cursor_reference_t = decltype(std::declval<T const &>().read());
167
168 template<typename T>
169 static meta::id<uncvref_t<cursor_reference_t<T>>> cursor_value_2_(long);
170 template<typename T>
171 static meta::id<typename T::value_type> cursor_value_2_(int);
172
173#ifdef RANGES_WORKAROUND_CWG_1554
174 template<typename Cur>
175 struct cursor_difference
176 {
177 using type = decltype(range_access::cursor_difference_2_<Cur>(42));
178 };
179
180 template<typename Cur>
181 struct cursor_value : decltype(range_access::cursor_value_2_<Cur>(42))
182 {};
183#endif // RANGES_WORKAROUND_CWG_1554
184 public:
185#ifdef RANGES_WORKAROUND_CWG_1554
186 template<typename Cur>
187 using cursor_difference_t = meta::_t<cursor_difference<Cur>>;
188
189 template<typename Cur>
190 using cursor_value_t = meta::_t<cursor_value<Cur>>;
191#else // ^^^ workaround ^^^ / vvv no workaround vvv
192 template<typename Cur>
193 using cursor_difference_t = decltype(range_access::cursor_difference_2_<Cur>(42));
194
195 template<typename Cur>
196 using cursor_value_t = meta::_t<decltype(range_access::cursor_value_2_<Cur>(42))>;
197#endif // RANGES_WORKAROUND_CWG_1554
198
199 template<typename Cur>
200 static constexpr Cur & pos(basic_iterator<Cur> & it) noexcept
201 {
202 return it.pos();
203 }
204 template<typename Cur>
205 static constexpr Cur const & pos(basic_iterator<Cur> const & it) noexcept
206 {
207 return it.pos();
208 }
209 template<typename Cur>
210 static constexpr Cur && pos(basic_iterator<Cur> && it) noexcept
211 {
212 return detail::move(it.pos());
213 }
214
215 template<typename Cur>
216 static constexpr Cur cursor(basic_iterator<Cur> it)
217 {
218 return std::move(it.pos());
219 }
221 };
223
225 namespace detail
226 {
227 //
228 // Concepts that the range cursor must model
229 // clang-format off
230 //
233 template<typename T>
234 CPP_concept cursor =
235 semiregular<T> && semiregular<range_access::mixin_base_t<T>> &&
236 constructible_from<range_access::mixin_base_t<T>, T> &&
237 constructible_from<range_access::mixin_base_t<T>, T const &>;
238 // Axiom: mixin_base_t<T> has a member get(), accessible to derived classes,
239 // which perfectly-returns the contained cursor object and does not throw
240 // exceptions.
241
244 template<typename T>
245 CPP_requires(has_cursor_next_,
246 requires(T & t)
247 (
248 range_access::next(t)
249 ));
252 template<typename T>
253 CPP_concept has_cursor_next = CPP_requires_ref(detail::has_cursor_next_, T);
254
257 template<typename S, typename C>
258 CPP_requires(sentinel_for_cursor_,
259 requires(S & s, C & c) //
260 (
261 range_access::equal(c, s),
262 concepts::requires_<convertible_to<decltype(
263 range_access::equal(c, s)), bool>>
264 ));
267 template<typename S, typename C>
268 CPP_concept sentinel_for_cursor =
269 semiregular<S> &&
270 cursor<C> &&
271 CPP_requires_ref(detail::sentinel_for_cursor_, S, C);
272
275 template<typename T>
276 CPP_requires(readable_cursor_,
277 requires(T & t) //
278 (
279 range_access::read(t)
280 ));
283 template<typename T>
284 CPP_concept readable_cursor = CPP_requires_ref(detail::readable_cursor_, T);
285
288 template<typename T>
289 CPP_requires(has_cursor_arrow_,
290 requires(T const & t) //
291 (
292 range_access::arrow(t)
293 ));
296 template<typename T>
297 CPP_concept has_cursor_arrow = CPP_requires_ref(detail::has_cursor_arrow_, T);
298
301 template<typename T, typename U>
302 CPP_requires(writable_cursor_,
303 requires(T & t, U && u) //
304 (
305 range_access::write(t, (U &&) u)
306 ));
309 template<typename T, typename U>
310 CPP_concept writable_cursor =
311 CPP_requires_ref(detail::writable_cursor_, T, U);
312
315 template<typename S, typename C>
316 CPP_requires(sized_sentinel_for_cursor_,
317 requires(S & s, C & c) //
318 (
319 range_access::distance_to(c, s),
320 concepts::requires_<signed_integer_like_<decltype(
321 range_access::distance_to(c, s))>>
322 )
323 );
326 template<typename S, typename C>
327 CPP_concept sized_sentinel_for_cursor =
328 sentinel_for_cursor<S, C> &&
329 CPP_requires_ref(detail::sized_sentinel_for_cursor_, S, C);
330
333 template<typename T, typename U>
334 CPP_concept output_cursor =
335 writable_cursor<T, U> && cursor<T>;
336
339 template<typename T>
340 CPP_concept input_cursor =
341 readable_cursor<T> && cursor<T> && has_cursor_next<T>;
342
345 template<typename T>
346 CPP_concept forward_cursor =
347 input_cursor<T> && sentinel_for_cursor<T, T> &&
348 !range_access::single_pass_t<uncvref_t<T>>::value;
349
352 template<typename T>
353 CPP_requires(bidirectional_cursor_,
354 requires(T & t) //
355 (
356 range_access::prev(t)
357 ));
360 template<typename T>
361 CPP_concept bidirectional_cursor =
362 forward_cursor<T> &&
363 CPP_requires_ref(detail::bidirectional_cursor_, T);
364
367 template<typename T>
368 CPP_requires(random_access_cursor_,
369 requires(T & t) //
370 (
371 range_access::advance(t, range_access::distance_to(t, t))
372 ));
375 template<typename T>
376 CPP_concept random_access_cursor =
377 bidirectional_cursor<T> && //
378 sized_sentinel_for_cursor<T, T> && //
379 CPP_requires_ref(detail::random_access_cursor_, T);
380
381 template(class T)(
382 requires std::is_lvalue_reference<T>::value)
383 void is_lvalue_reference(T&&);
384
387 template<typename T>
388 CPP_requires(contiguous_cursor_,
389 requires(T & t) //
390 (
391 detail::is_lvalue_reference(range_access::read(t))
392 ));
395 template<typename T>
396 CPP_concept contiguous_cursor =
397 random_access_cursor<T> && //
398 range_access::contiguous_t<uncvref_t<T>>::value && //
399 CPP_requires_ref(detail::contiguous_cursor_, T);
400 // clang-format on
401
402 template<typename Cur, bool IsReadable>
403 RANGES_INLINE_VAR constexpr bool is_writable_cursor_ = true;
404
405 template<typename Cur>
406 RANGES_INLINE_VAR constexpr bool is_writable_cursor_<Cur, true> =
407 (bool) writable_cursor<Cur, range_access::cursor_value_t<Cur>>;
408
409 template<typename Cur>
410 RANGES_INLINE_VAR constexpr bool is_writable_cursor_v =
411 is_writable_cursor_<Cur, (bool)readable_cursor<Cur>>;
412 } // namespace detail
414} // namespace ranges
415
416#include <range/v3/detail/epilogue.hpp>
417
418#endif
typename T::type _t
Type alias for T::type.
Definition meta.hpp:141
Tiny meta-programming library.
A trait that always returns its argument T.
Definition meta.hpp:558