Horizon
range_access.hpp
Go to the documentation of this file.
1 // 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 
25 #include <range/v3/range_fwd.hpp>
26 
28 
29 #include <range/v3/detail/prologue.hpp>
30 
31 namespace 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
CPP_concept type
\concept type
Definition: concepts.hpp:838
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