Horizon
access.hpp
Go to the documentation of this file.
1 // 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_RANGE_ACCESS_HPP
15 #define RANGES_V3_RANGE_ACCESS_HPP
16 
17 #include <range/v3/detail/config.hpp>
18 
19 #include <functional> // for reference_wrapper (whose use with begin/end is deprecated)
20 #include <initializer_list>
21 #include <iterator>
22 #include <limits>
23 #include <utility>
24 
25 #ifdef __has_include
26 #if __has_include(<span>) && !defined(RANGES_WORKAROUND_MSVC_UNUSABLE_SPAN)
27 #include <span>
28 #endif
29 #if __has_include(<string_view>)
30 #include <string_view>
31 #endif
32 #endif
33 
34 #include <range/v3/range_fwd.hpp>
35 
39 #include <range/v3/utility/static_const.hpp>
40 
41 #include <range/v3/detail/prologue.hpp>
42 
43 namespace ranges
44 {
45 #if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201603L
46  template<class CharT, class Traits>
47  RANGES_INLINE_VAR constexpr bool
48  enable_borrowed_range<std::basic_string_view<CharT, Traits>> = true;
49 #endif
50 
51 // libstdc++'s <span> header only defines std::span when concepts
52 // are also enabled. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97869
53 #if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L && \
54  (!defined(__GLIBCXX__) || defined(__cpp_lib_concepts))
55  template<class T, std::size_t N>
56  RANGES_INLINE_VAR constexpr bool enable_borrowed_range<std::span<T, N>> = true;
57 #endif
58 
59  namespace detail
60  {
61  template<typename T>
62  RANGES_INLINE_VAR constexpr bool _borrowed_range =
63  enable_borrowed_range<uncvref_t<T>>;
64 
65  template<typename T>
66  RANGES_INLINE_VAR constexpr bool _borrowed_range<T &> = true;
67 
68  template<typename T>
69  T _decay_copy(T) noexcept;
70  } // namespace detail
71 
73  namespace _begin_
74  {
75  // Poison pill for std::begin. (See the detailed discussion at
76  // https://github.com/ericniebler/stl2/issues/139)
77  template<typename T>
78  void begin(T &&) = delete;
79 
80 #ifdef RANGES_WORKAROUND_MSVC_895622
81  void begin();
82 #endif
83 
84  template<typename T>
85  void begin(std::initializer_list<T>) = delete;
86 
87  template(typename I)(
88  requires input_or_output_iterator<I>)
89  void is_iterator(I);
90 
91  // clang-format off
94  template<typename T>
95  CPP_requires(has_member_begin_,
96  requires(T & t) //
97  (
98  _begin_::is_iterator(t.begin())
99  ));
102  template<typename T>
103  CPP_concept has_member_begin =
104  CPP_requires_ref(_begin_::has_member_begin_, T);
105 
108  template<typename T>
109  CPP_requires(has_non_member_begin_,
110  requires(T & t) //
111  (
112  _begin_::is_iterator(begin(t))
113  ));
116  template<typename T>
117  CPP_concept has_non_member_begin =
118  CPP_requires_ref(_begin_::has_non_member_begin_, T);
119  // clang-format on
120 
121  struct fn
122  {
123  private:
124  struct _member_result_
125  {
126  template<typename R>
127  using invoke = decltype(detail::_decay_copy(declval(R &).begin()));
128  };
129  struct _non_member_result_
130  {
131  template<typename R>
132  using invoke = decltype(detail::_decay_copy(begin(declval(R &))));
133  };
134 
135  template<typename R>
136  using _result_t =
137  meta::invoke<
139  has_member_begin<R>,
140  _member_result_,
141  _non_member_result_>,
142  R>;
143 
144  public:
145  template<typename R, std::size_t N>
146  void operator()(R(&&)[N]) const = delete;
147 
148  template<typename R, std::size_t N>
149  constexpr R * operator()(R (&array)[N]) const noexcept
150  {
151  return array;
152  }
153 
154  template(typename R)(
155  requires detail::_borrowed_range<R> AND has_member_begin<R>)
156  constexpr _result_t<R> operator()(R && r) const //
157  noexcept(noexcept(r.begin()))
158  {
159  return r.begin();
160  }
161 
162  template(typename R)(
163  requires detail::_borrowed_range<R> AND (!has_member_begin<R>) AND
164  has_non_member_begin<R>)
165  constexpr _result_t<R> operator()(R && r) const //
166  noexcept(noexcept(begin(r)))
167  {
168  return begin(r);
169  }
170  };
171 
172  template<typename R>
173  using _t = decltype(fn{}(declval(R &&)));
174  } // namespace _begin_
176 
182  RANGES_DEFINE_CPO(_begin_::fn, begin)
183 
184 
185  namespace _end_
186  {
187  // Poison pill for std::end. (See the detailed discussion at
188  // https://github.com/ericniebler/stl2/issues/139)
189  template<typename T>
190  void end(T &&) = delete;
191 
192 #ifdef RANGES_WORKAROUND_MSVC_895622
193  void end();
194 #endif
195 
196  template<typename T>
197  void end(std::initializer_list<T>) = delete;
198 
199  template(typename I, typename S)(
200  requires sentinel_for<S, I>)
201  void _is_sentinel(S, I);
202 
203  // clang-format off
206  template<typename T>
207  CPP_requires(has_member_end_,
208  requires(T & t) //
209  (
210  _end_::_is_sentinel(t.end(), ranges::begin(t))
211  ));
214  template<typename T>
215  CPP_concept has_member_end =
216  CPP_requires_ref(_end_::has_member_end_, T);
217 
220  template<typename T>
221  CPP_requires(has_non_member_end_,
222  requires(T & t) //
223  (
224  _end_::_is_sentinel(end(t), ranges::begin(t))
225  ));
228  template<typename T>
229  CPP_concept has_non_member_end =
230  CPP_requires_ref(_end_::has_non_member_end_, T);
231  // clang-format on
232 
233  struct fn
234  {
235  private:
236  struct _member_result_
237  {
238  template<typename R>
239  using invoke = decltype(detail::_decay_copy(declval(R &).end()));
240  };
241  struct _non_member_result_
242  {
243  template<typename R>
244  using invoke = decltype(detail::_decay_copy(end(declval(R &))));
245  };
246 
247  template<typename R>
248  using _result_t =
249  meta::invoke<
251  has_member_end<R>,
252  _member_result_,
253  _non_member_result_>,
254  R>;
255 
256  template<typename Int>
257  using iter_diff_t =
259  std::make_signed<Int>, //
260  meta::id<Int>>>;
261 
262  public:
263  template<typename R, std::size_t N>
264  void operator()(R(&&)[N]) const = delete;
265 
266  template<typename R, std::size_t N>
267  constexpr R * operator()(R (&array)[N]) const noexcept
268  {
269  return array + N;
270  }
271 
272  template(typename R)(
273  requires detail::_borrowed_range<R> AND has_member_end<R>)
274  constexpr _result_t<R> operator()(R && r) const //
275  noexcept(noexcept(r.end()))
276  {
277  return r.end();
278  }
279 
280  template(typename R)(
281  requires detail::_borrowed_range<R> AND (!has_member_end<R>) AND
282  has_non_member_end<R>)
283  constexpr _result_t<R> operator()(R && r) const //
284  noexcept(noexcept(end(r)))
285  {
286  return end(r);
287  }
288 
289  template(typename Int)(
290  requires detail::integer_like_<Int>)
291  auto operator-(Int dist) const
292  -> detail::from_end_<iter_diff_t<Int>>
293  {
294  using SInt = iter_diff_t<Int>;
295  RANGES_EXPECT(0 <= dist);
296  RANGES_EXPECT(dist <=
297  static_cast<Int>((std::numeric_limits<SInt>::max)()));
298  return detail::from_end_<SInt>{-static_cast<SInt>(dist)};
299  }
300  };
301 
302  template<typename R>
303  using _t = decltype(fn{}(declval(R &&)));
304  } // namespace _end_
306 
313  RANGES_DEFINE_CPO(_end_::fn, end)
314 
315 
316  namespace _cbegin_
317  {
318  struct fn
319  {
320  template<typename T, std::size_t N>
321  void operator()(T(&&)[N]) const = delete;
322 
323  template<typename R>
324  constexpr _begin_::_t<detail::as_const_t<R>> operator()(R && r) const
325  noexcept(noexcept(ranges::begin(detail::as_const(r))))
326  {
327  return ranges::begin(detail::as_const(r));
328  }
329  };
330  } // namespace _cbegin_
332 
337  RANGES_INLINE_VARIABLE(_cbegin_::fn, cbegin)
338 
339 
340  namespace _cend_
341  {
342  struct fn
343  {
344  template<typename T, std::size_t N>
345  void operator()(T(&&)[N]) const = delete;
346 
347  template<typename R>
348  constexpr _end_::_t<detail::as_const_t<R>> operator()(R && r) const
349  noexcept(noexcept(ranges::end(detail::as_const(r))))
350  {
351  return ranges::end(detail::as_const(r));
352  }
353  };
354  } // namespace _cend_
356 
361  RANGES_INLINE_VARIABLE(_cend_::fn, cend)
362 
363 
364  namespace _rbegin_
365  {
366  template<typename R>
367  void rbegin(R &&) = delete;
368  // Non-standard, to keep unqualified rbegin(r) from finding std::rbegin
369  // and returning a std::reverse_iterator.
370  template<typename T>
371  void rbegin(std::initializer_list<T>) = delete;
372  template<typename T, std::size_t N>
373  void rbegin(T (&)[N]) = delete;
374 
375  // clang-format off
378  template<typename T>
379  CPP_requires(has_member_rbegin_,
380  requires(T & t) //
381  (
382  _begin_::is_iterator(t.rbegin())
383  ));
386  template<typename T>
387  CPP_concept has_member_rbegin =
388  CPP_requires_ref(_rbegin_::has_member_rbegin_, T);
389 
392  template<typename T>
393  CPP_requires(has_non_member_rbegin_,
394  requires(T & t) //
395  (
396  _begin_::is_iterator(rbegin(t))
397  ));
400  template<typename T>
401  CPP_concept has_non_member_rbegin =
402  CPP_requires_ref(_rbegin_::has_non_member_rbegin_, T);
403 
404  template<typename I>
405  void _same_type(I, I);
406 
409  template<typename T>
410  CPP_requires(can_reverse_end_,
411  requires(T & t) //
412  (
413  // make_reverse_iterator is constrained with
414  // bidirectional_iterator.
415  ranges::make_reverse_iterator(ranges::end(t)),
416  _rbegin_::_same_type(ranges::begin(t), ranges::end(t))
417  ));
420  template<typename T>
421  CPP_concept can_reverse_end =
422  CPP_requires_ref(_rbegin_::can_reverse_end_, T);
423  // clang-format on
424 
425  struct fn
426  {
427  private:
428  struct _member_result_
429  {
430  template<typename R>
431  using invoke = decltype(detail::_decay_copy(declval(R &).rbegin()));
432  };
433  struct _non_member_result_
434  {
435  template<typename R>
436  using invoke = decltype(detail::_decay_copy(rbegin(declval(R &))));
437  };
438  struct _reverse_result_
439  {
440  template<typename R>
441  using invoke =
442  decltype(ranges::make_reverse_iterator(ranges::end(declval(R &))));
443  };
444  struct _other_result_
445  {
446  template<typename R>
447  using invoke =
448  meta::invoke<
450  has_non_member_rbegin<R>,
451  _non_member_result_,
452  _reverse_result_>,
453  R>;
454  };
455 
456  template<typename R>
457  using _result_t =
458  meta::invoke<
460  has_member_rbegin<R>,
461  _member_result_,
462  _other_result_>,
463  R>;
464 
465  public:
466  template(typename R)(
467  requires detail::_borrowed_range<R> AND has_member_rbegin<R>)
468  constexpr auto operator()(R && r) const //
469  noexcept(noexcept(r.rbegin())) //
470  {
471  return r.rbegin();
472  }
473 
474  template(typename R)(
475  requires detail::_borrowed_range<R> AND (!has_member_rbegin<R>) AND
476  has_non_member_rbegin<R>)
477  constexpr auto operator()(R && r) const //
478  noexcept(noexcept(rbegin(r))) //
479  {
480  return rbegin(r);
481  }
482 
483  template(typename R)(
484  requires detail::_borrowed_range<R> AND (!has_member_rbegin<R>) AND
485  (!has_non_member_rbegin<R>) AND can_reverse_end<R>)
486  constexpr auto operator()(R && r) const //
487  noexcept(noexcept(ranges::make_reverse_iterator(ranges::end(r))))
488  {
489  return ranges::make_reverse_iterator(ranges::end(r));
490  }
491  };
492 
493  template<typename R>
494  using _t = decltype(fn{}(declval(R &&)));
495  } // namespace _rbegin_
497 
505  RANGES_DEFINE_CPO(_rbegin_::fn, rbegin)
506 
507 
508  namespace _rend_
509  {
510  template<typename R>
511  void rend(R &&) = delete;
512  // Non-standard, to keep unqualified rend(r) from finding std::rend
513  // and returning a std::reverse_iterator.
514  template<typename T>
515  void rend(std::initializer_list<T>) = delete;
516  template<typename T, std::size_t N>
517  void rend(T (&)[N]) = delete;
518 
519  // clang-format off
522  template<typename T>
523  CPP_requires(has_member_rend_,
524  requires(T & t) //
525  (
526  _end_::_is_sentinel(t.rend(), ranges::rbegin(t))
527  ));
530  template<typename T>
531  CPP_concept has_member_rend =
532  CPP_requires_ref(_rend_::has_member_rend_, T);
533 
536  template<typename T>
537  CPP_requires(has_non_member_rend_,
538  requires(T & t) //
539  (
540  _end_::_is_sentinel(rend(t), ranges::rbegin(t))
541  ));
544  template<typename T>
545  CPP_concept has_non_member_rend =
546  CPP_requires_ref(_rend_::has_non_member_rend_, T);
547 
550  template<typename T>
551  CPP_requires(can_reverse_begin_,
552  requires(T & t) //
553  (
554  // make_reverse_iterator is constrained with
555  // bidirectional_iterator.
556  ranges::make_reverse_iterator(ranges::begin(t)),
557  _rbegin_::_same_type(ranges::begin(t), ranges::end(t))
558  ));
561  template<typename T>
562  CPP_concept can_reverse_begin =
563  CPP_requires_ref(_rend_::can_reverse_begin_, T);
564  // clang-format on
565 
566  struct fn
567  {
568  private:
569  struct _member_result_
570  {
571  template<typename R>
572  using invoke = decltype(detail::_decay_copy(declval(R &).rend()));
573  };
574  struct _non_member_result_
575  {
576  template<typename R>
577  using invoke = decltype(detail::_decay_copy(rend(declval(R &))));
578  };
579  struct _reverse_result_
580  {
581  template<typename R>
582  using invoke =
583  decltype(ranges::make_reverse_iterator(ranges::begin(declval(R &))));
584  };
585  struct _other_result_
586  {
587  template<typename R>
588  using invoke =
589  meta::invoke<
591  has_non_member_rend<R>,
592  _non_member_result_,
593  _reverse_result_>,
594  R>;
595  };
596 
597  template<typename R>
598  using _result_t =
599  meta::invoke<
601  has_member_rend<R>,
602  _member_result_,
603  _other_result_>,
604  R>;
605 
606  public:
607  template(typename R)(
608  requires detail::_borrowed_range<R> AND has_member_rend<R>)
609  constexpr auto operator()(R && r) const //
610  noexcept(noexcept(r.rend())) //
611  {
612  return r.rend();
613  }
614 
615  template(typename R)(
616  requires detail::_borrowed_range<R> AND (!has_member_rend<R>) AND
617  has_non_member_rend<R>)
618  constexpr auto operator()(R && r) const //
619  noexcept(noexcept(rend(r))) //
620  {
621  return rend(r);
622  }
623 
624  template(typename R)(
625  requires detail::_borrowed_range<R> AND (!has_member_rend<R>) AND
626  (!has_non_member_rend<R>) AND can_reverse_begin<R>)
627  constexpr auto operator()(R && r) const //
628  noexcept(noexcept(ranges::make_reverse_iterator(ranges::begin(r))))
629  {
630  return ranges::make_reverse_iterator(ranges::begin(r));
631  }
632  };
633 
634  template<typename R>
635  using _t = decltype(fn{}(declval(R &&)));
636  } // namespace _rend_
638 
647  RANGES_DEFINE_CPO(_rend_::fn, rend)
648 
649 
650  namespace _crbegin_
651  {
652  struct fn
653  {
654  template<typename T, std::size_t N>
655  void operator()(T(&&)[N]) const = delete;
656 
657  template<typename R>
658  constexpr _rbegin_::_t<detail::as_const_t<R>> operator()(R && r) const
659  noexcept(noexcept(ranges::rbegin(detail::as_const(r))))
660  {
661  return ranges::rbegin(detail::as_const(r));
662  }
663  };
664  } // namespace _crbegin_
666 
671  RANGES_INLINE_VARIABLE(_crbegin_::fn, crbegin)
672 
673 
674  namespace _crend_
675  {
676  struct fn
677  {
678  template<typename T, std::size_t N>
679  void operator()(T(&&)[N]) const = delete;
680 
681  template<typename R>
682  constexpr _rend_::_t<detail::as_const_t<R>> operator()(R && r) const
683  noexcept(noexcept(ranges::rend(detail::as_const(r))))
684  {
685  return ranges::rend(detail::as_const(r));
686  }
687  };
688  } // namespace _crend_
690 
695  RANGES_INLINE_VARIABLE(_crend_::fn, crend)
696 
697  template<typename Rng>
698  using iterator_t = decltype(begin(declval(Rng &)));
699 
700  template<typename Rng>
701  using sentinel_t = decltype(end(declval(Rng &)));
702 
703  namespace cpp20
704  {
705  using ranges::begin;
706  using ranges::cbegin;
707  using ranges::cend;
708  using ranges::crbegin;
709  using ranges::crend;
710  using ranges::end;
711  using ranges::rbegin;
712  using ranges::rend;
713 
714  using ranges::iterator_t;
715  using ranges::sentinel_t;
716 
717  using ranges::enable_borrowed_range;
718  } // namespace cpp20
719 } // namespace ranges
720 
721 #include <range/v3/detail/epilogue.hpp>
722 
723 #endif
decltype(begin(declval(Rng &))) iterator_t
Definition: access.hpp:698
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
typename T::type _t
Type alias for T::type.
Definition: meta.hpp:141
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition: meta.hpp:1148
@ array
array (ordered collection of values)
Point operator-(const Point &a, const Point &b)
Subtract two points_ component-wise.
Definition: shapes.h:244
A trait that always returns its argument T.
Definition: meta.hpp:558