libstdc++
ranges_base.h
Go to the documentation of this file.
1 // Core concepts and definitions for <ranges> -*- C++ -*-
2 
3 // Copyright (C) 2019-2023 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file bits/ranges_base.h
26  * This is an internal header file, included by other library headers.
27  * Do not attempt to use it directly. @headername{ranges}
28  */
29 
30 #ifndef _GLIBCXX_RANGES_BASE_H
31 #define _GLIBCXX_RANGES_BASE_H 1
32 
33 #pragma GCC system_header
34 
35 #if __cplusplus > 201703L
36 #include <initializer_list>
37 #include <bits/stl_iterator.h>
38 #include <ext/numeric_traits.h>
39 #include <bits/max_size_type.h>
40 
41 #ifdef __cpp_lib_concepts
42 namespace std _GLIBCXX_VISIBILITY(default)
43 {
44 _GLIBCXX_BEGIN_NAMESPACE_VERSION
45 namespace ranges
46 {
47  template<typename>
48  inline constexpr bool disable_sized_range = false;
49 
50  template<typename _Tp>
51  inline constexpr bool enable_borrowed_range = false;
52 
53  namespace __detail
54  {
55  constexpr __max_size_type
56  __to_unsigned_like(__max_size_type __t) noexcept
57  { return __t; }
58 
59  constexpr __max_size_type
60  __to_unsigned_like(__max_diff_type __t) noexcept
61  { return __max_size_type(__t); }
62 
63  template<integral _Tp>
64  constexpr auto
65  __to_unsigned_like(_Tp __t) noexcept
66  { return static_cast<make_unsigned_t<_Tp>>(__t); }
67 
68 #if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
69  constexpr unsigned __int128
70  __to_unsigned_like(__int128 __t) noexcept
71  { return __t; }
72 
73  constexpr unsigned __int128
74  __to_unsigned_like(unsigned __int128 __t) noexcept
75  { return __t; }
76 #endif
77 
78  template<typename _Tp>
79  using __make_unsigned_like_t
80  = decltype(__detail::__to_unsigned_like(std::declval<_Tp>()));
81 
82  // Part of the constraints of ranges::borrowed_range
83  template<typename _Tp>
84  concept __maybe_borrowed_range
85  = is_lvalue_reference_v<_Tp>
86  || enable_borrowed_range<remove_cvref_t<_Tp>>;
87 
88  } // namespace __detail
89 
90  namespace __cust_access
91  {
92  using std::ranges::__detail::__maybe_borrowed_range;
93  using std::__detail::__range_iter_t;
94 
95  struct _Begin
96  {
97  private:
98  template<typename _Tp>
99  static constexpr bool
100  _S_noexcept()
101  {
102  if constexpr (is_array_v<remove_reference_t<_Tp>>)
103  return true;
104  else if constexpr (__member_begin<_Tp>)
105  return noexcept(__decay_copy(std::declval<_Tp&>().begin()));
106  else
107  return noexcept(__decay_copy(begin(std::declval<_Tp&>())));
108  }
109 
110  public:
111  template<__maybe_borrowed_range _Tp>
112  requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
113  || __adl_begin<_Tp>
114  constexpr auto
115  operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
116  {
117  if constexpr (is_array_v<remove_reference_t<_Tp>>)
118  {
119  static_assert(is_lvalue_reference_v<_Tp>);
120  return __t + 0;
121  }
122  else if constexpr (__member_begin<_Tp>)
123  return __t.begin();
124  else
125  return begin(__t);
126  }
127  };
128 
129  template<typename _Tp>
130  concept __member_end = requires(_Tp& __t)
131  {
132  { __decay_copy(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>;
133  };
134 
135  // Poison pills so that unqualified lookup doesn't find std::end.
136  void end(auto&) = delete;
137  void end(const auto&) = delete;
138 
139  template<typename _Tp>
140  concept __adl_end = __class_or_enum<remove_reference_t<_Tp>>
141  && requires(_Tp& __t)
142  {
143  { __decay_copy(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>;
144  };
145 
146  struct _End
147  {
148  private:
149  template<typename _Tp>
150  static constexpr bool
151  _S_noexcept()
152  {
153  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
154  return true;
155  else if constexpr (__member_end<_Tp>)
156  return noexcept(__decay_copy(std::declval<_Tp&>().end()));
157  else
158  return noexcept(__decay_copy(end(std::declval<_Tp&>())));
159  }
160 
161  public:
162  template<__maybe_borrowed_range _Tp>
164  || __member_end<_Tp> || __adl_end<_Tp>
165  constexpr auto
166  operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
167  {
168  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
169  {
170  static_assert(is_lvalue_reference_v<_Tp>);
171  return __t + extent_v<remove_reference_t<_Tp>>;
172  }
173  else if constexpr (__member_end<_Tp>)
174  return __t.end();
175  else
176  return end(__t);
177  }
178  };
179 
180  template<typename _Tp>
181  concept __member_rbegin = requires(_Tp& __t)
182  {
183  { __decay_copy(__t.rbegin()) } -> input_or_output_iterator;
184  };
185 
186  void rbegin(auto&) = delete;
187  void rbegin(const auto&) = delete;
188 
189  template<typename _Tp>
190  concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>>
191  && requires(_Tp& __t)
192  {
193  { __decay_copy(rbegin(__t)) } -> input_or_output_iterator;
194  };
195 
196  template<typename _Tp>
197  concept __reversable = requires(_Tp& __t)
198  {
199  { _Begin{}(__t) } -> bidirectional_iterator;
200  { _End{}(__t) } -> same_as<decltype(_Begin{}(__t))>;
201  };
202 
203  struct _RBegin
204  {
205  private:
206  template<typename _Tp>
207  static constexpr bool
208  _S_noexcept()
209  {
210  if constexpr (__member_rbegin<_Tp>)
211  return noexcept(__decay_copy(std::declval<_Tp&>().rbegin()));
212  else if constexpr (__adl_rbegin<_Tp>)
213  return noexcept(__decay_copy(rbegin(std::declval<_Tp&>())));
214  else
215  {
216  if constexpr (noexcept(_End{}(std::declval<_Tp&>())))
217  {
218  using _It = decltype(_End{}(std::declval<_Tp&>()));
219  // std::reverse_iterator copy-initializes its member.
220  return is_nothrow_copy_constructible_v<_It>;
221  }
222  else
223  return false;
224  }
225  }
226 
227  public:
228  template<__maybe_borrowed_range _Tp>
229  requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
230  constexpr auto
231  operator()[[nodiscard]](_Tp&& __t) const
232  noexcept(_S_noexcept<_Tp&>())
233  {
234  if constexpr (__member_rbegin<_Tp>)
235  return __t.rbegin();
236  else if constexpr (__adl_rbegin<_Tp>)
237  return rbegin(__t);
238  else
239  return std::make_reverse_iterator(_End{}(__t));
240  }
241  };
242 
243  template<typename _Tp>
244  concept __member_rend = requires(_Tp& __t)
245  {
246  { __decay_copy(__t.rend()) }
247  -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
248  };
249 
250  void rend(auto&) = delete;
251  void rend(const auto&) = delete;
252 
253  template<typename _Tp>
254  concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>>
255  && requires(_Tp& __t)
256  {
257  { __decay_copy(rend(__t)) }
258  -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
259  };
260 
261  struct _REnd
262  {
263  private:
264  template<typename _Tp>
265  static constexpr bool
266  _S_noexcept()
267  {
268  if constexpr (__member_rend<_Tp>)
269  return noexcept(__decay_copy(std::declval<_Tp&>().rend()));
270  else if constexpr (__adl_rend<_Tp>)
271  return noexcept(__decay_copy(rend(std::declval<_Tp&>())));
272  else
273  {
274  if constexpr (noexcept(_Begin{}(std::declval<_Tp&>())))
275  {
276  using _It = decltype(_Begin{}(std::declval<_Tp&>()));
277  // std::reverse_iterator copy-initializes its member.
278  return is_nothrow_copy_constructible_v<_It>;
279  }
280  else
281  return false;
282  }
283  }
284 
285  public:
286  template<__maybe_borrowed_range _Tp>
287  requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
288  constexpr auto
289  operator()[[nodiscard]](_Tp&& __t) const
290  noexcept(_S_noexcept<_Tp&>())
291  {
292  if constexpr (__member_rend<_Tp>)
293  return __t.rend();
294  else if constexpr (__adl_rend<_Tp>)
295  return rend(__t);
296  else
297  return std::make_reverse_iterator(_Begin{}(__t));
298  }
299  };
300 
301  template<typename _Tp>
302  concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
303  && requires(_Tp& __t)
304  {
305  { __decay_copy(__t.size()) } -> __detail::__is_integer_like;
306  };
307 
308  void size(auto&) = delete;
309  void size(const auto&) = delete;
310 
311  template<typename _Tp>
312  concept __adl_size = __class_or_enum<remove_reference_t<_Tp>>
313  && !disable_sized_range<remove_cvref_t<_Tp>>
314  && requires(_Tp& __t)
315  {
316  { __decay_copy(size(__t)) } -> __detail::__is_integer_like;
317  };
318 
319  template<typename _Tp>
320  concept __sentinel_size = requires(_Tp& __t)
321  {
322  requires (!is_unbounded_array_v<remove_reference_t<_Tp>>);
323 
324  { _Begin{}(__t) } -> forward_iterator;
325 
326  { _End{}(__t) } -> sized_sentinel_for<decltype(_Begin{}(__t))>;
327 
328  __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t));
329  };
330 
331  struct _Size
332  {
333  private:
334  template<typename _Tp>
335  static constexpr bool
336  _S_noexcept()
337  {
338  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
339  return true;
340  else if constexpr (__member_size<_Tp>)
341  return noexcept(__decay_copy(std::declval<_Tp&>().size()));
342  else if constexpr (__adl_size<_Tp>)
343  return noexcept(__decay_copy(size(std::declval<_Tp&>())));
344  else if constexpr (__sentinel_size<_Tp>)
345  return noexcept(_End{}(std::declval<_Tp&>())
346  - _Begin{}(std::declval<_Tp&>()));
347  }
348 
349  public:
350  template<typename _Tp>
351  requires is_bounded_array_v<remove_reference_t<_Tp>>
352  || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
353  constexpr auto
354  operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
355  {
356  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
357  return extent_v<remove_reference_t<_Tp>>;
358  else if constexpr (__member_size<_Tp>)
359  return __t.size();
360  else if constexpr (__adl_size<_Tp>)
361  return size(__t);
362  else if constexpr (__sentinel_size<_Tp>)
363  return __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t));
364  }
365  };
366 
367  struct _SSize
368  {
369  // _GLIBCXX_RESOLVE_LIB_DEFECTS
370  // 3403. Domain of ranges::ssize(E) doesn't match ranges::size(E)
371  template<typename _Tp>
372  requires requires (_Tp& __t) { _Size{}(__t); }
373  constexpr auto
374  operator()[[nodiscard]](_Tp&& __t) const noexcept(noexcept(_Size{}(__t)))
375  {
376  auto __size = _Size{}(__t);
377  using __size_type = decltype(__size);
378  // Return the wider of ptrdiff_t and make-signed-like-t<__size_type>.
379  if constexpr (integral<__size_type>)
380  {
382  if constexpr (__int_traits<__size_type>::__digits
383  < __int_traits<ptrdiff_t>::__digits)
384  return static_cast<ptrdiff_t>(__size);
385  else
386  return static_cast<make_signed_t<__size_type>>(__size);
387  }
388 #if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
389  // For strict-ansi modes integral<__int128> is false
390  else if constexpr (__detail::__is_int128<__size_type>)
391  return static_cast<__int128>(__size);
392 #endif
393  else // Must be one of __max_diff_type or __max_size_type.
394  return __detail::__max_diff_type(__size);
395  }
396  };
397 
398  template<typename _Tp>
399  concept __member_empty = requires(_Tp& __t) { bool(__t.empty()); };
400 
401  template<typename _Tp>
402  concept __size0_empty = requires(_Tp& __t) { _Size{}(__t) == 0; };
403 
404  template<typename _Tp>
405  concept __eq_iter_empty = requires(_Tp& __t)
406  {
407  requires (!is_unbounded_array_v<remove_reference_t<_Tp>>);
408 
409  { _Begin{}(__t) } -> forward_iterator;
410 
411  bool(_Begin{}(__t) == _End{}(__t));
412  };
413 
414  struct _Empty
415  {
416  private:
417  template<typename _Tp>
418  static constexpr bool
419  _S_noexcept()
420  {
421  if constexpr (__member_empty<_Tp>)
422  return noexcept(bool(std::declval<_Tp&>().empty()));
423  else if constexpr (__size0_empty<_Tp>)
424  return noexcept(_Size{}(std::declval<_Tp&>()) == 0);
425  else
426  return noexcept(bool(_Begin{}(std::declval<_Tp&>())
427  == _End{}(std::declval<_Tp&>())));
428  }
429 
430  public:
431  template<typename _Tp>
432  requires __member_empty<_Tp> || __size0_empty<_Tp>
433  || __eq_iter_empty<_Tp>
434  constexpr bool
435  operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
436  {
437  if constexpr (__member_empty<_Tp>)
438  return bool(__t.empty());
439  else if constexpr (__size0_empty<_Tp>)
440  return _Size{}(__t) == 0;
441  else
442  return bool(_Begin{}(__t) == _End{}(__t));
443  }
444  };
445 
446  template<typename _Tp>
447  concept __pointer_to_object = is_pointer_v<_Tp>
448  && is_object_v<remove_pointer_t<_Tp>>;
449 
450  template<typename _Tp>
451  concept __member_data = requires(_Tp& __t)
452  {
453  { __decay_copy(__t.data()) } -> __pointer_to_object;
454  };
455 
456  template<typename _Tp>
457  concept __begin_data = contiguous_iterator<__range_iter_t<_Tp>>;
458 
459  struct _Data
460  {
461  private:
462  template<typename _Tp>
463  static constexpr bool
464  _S_noexcept()
465  {
466  if constexpr (__member_data<_Tp>)
467  return noexcept(__decay_copy(std::declval<_Tp&>().data()));
468  else
469  return noexcept(_Begin{}(std::declval<_Tp&>()));
470  }
471 
472  public:
473  template<__maybe_borrowed_range _Tp>
474  requires __member_data<_Tp> || __begin_data<_Tp>
475  constexpr auto
476  operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
477  {
478  if constexpr (__member_data<_Tp>)
479  return __t.data();
480  else
481  return std::to_address(_Begin{}(__t));
482  }
483  };
484 
485  } // namespace __cust_access
486 
487  inline namespace __cust
488  {
489  inline constexpr __cust_access::_Begin begin{};
490  inline constexpr __cust_access::_End end{};
491  inline constexpr __cust_access::_RBegin rbegin{};
492  inline constexpr __cust_access::_REnd rend{};
493  inline constexpr __cust_access::_Size size{};
494  inline constexpr __cust_access::_SSize ssize{};
495  inline constexpr __cust_access::_Empty empty{};
496  inline constexpr __cust_access::_Data data{};
497  }
498 
499  /// [range.range] The range concept.
500  template<typename _Tp>
501  concept range = requires(_Tp& __t)
502  {
503  ranges::begin(__t);
504  ranges::end(__t);
505  };
506 
507  /// [range.range] The borrowed_range concept.
508  template<typename _Tp>
510  = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>;
511 
512  template<typename _Tp>
513  using iterator_t = std::__detail::__range_iter_t<_Tp>;
514 
515  template<range _Range>
516  using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
517 
518 #if __cplusplus > 202002L
519  template<range _Range>
520  using const_iterator_t = const_iterator<iterator_t<_Range>>;
521 
522  template<range _Range>
523  using const_sentinel_t = const_sentinel<sentinel_t<_Range>>;
524 
525  template<range _Range>
526  using range_const_reference_t = iter_const_reference_t<iterator_t<_Range>>;
527 #endif
528 
529  template<range _Range>
530  using range_difference_t = iter_difference_t<iterator_t<_Range>>;
531 
532  template<range _Range>
533  using range_value_t = iter_value_t<iterator_t<_Range>>;
534 
535  template<range _Range>
536  using range_reference_t = iter_reference_t<iterator_t<_Range>>;
537 
538  template<range _Range>
539  using range_rvalue_reference_t
541 
542  // _GLIBCXX_RESOLVE_LIB_DEFECTS
543  // 3860. range_common_reference_t is missing
544  template<range _Range>
545  using range_common_reference_t
546  = iter_common_reference_t<iterator_t<_Range>>;
547 
548  /// [range.sized] The sized_range concept.
549  template<typename _Tp>
550  concept sized_range = range<_Tp>
551  && requires(_Tp& __t) { ranges::size(__t); };
552 
553  template<sized_range _Range>
554  using range_size_t = decltype(ranges::size(std::declval<_Range&>()));
555 
556  template<typename _Derived>
557  requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
558  class view_interface; // defined in <bits/ranges_util.h>
559 
560  namespace __detail
561  {
562  template<typename _Tp, typename _Up>
563  requires (!same_as<_Tp, view_interface<_Up>>)
564  void __is_derived_from_view_interface_fn(const _Tp&,
565  const view_interface<_Up>&); // not defined
566 
567  // Returns true iff _Tp has exactly one public base class that's a
568  // specialization of view_interface.
569  template<typename _Tp>
570  concept __is_derived_from_view_interface
571  = requires (_Tp __t) { __is_derived_from_view_interface_fn(__t, __t); };
572  } // namespace __detail
573 
574  /// [range.view] The ranges::view_base type.
575  struct view_base { };
576 
577  /// [range.view] The ranges::enable_view boolean.
578  template<typename _Tp>
579  inline constexpr bool enable_view = derived_from<_Tp, view_base>
580  || __detail::__is_derived_from_view_interface<_Tp>;
581 
582  /// [range.view] The ranges::view concept.
583  template<typename _Tp>
584  concept view
585  = range<_Tp> && movable<_Tp> && enable_view<_Tp>;
586 
587  // [range.refinements]
588 
589  /// A range for which ranges::begin returns an output iterator.
590  template<typename _Range, typename _Tp>
591  concept output_range
592  = range<_Range> && output_iterator<iterator_t<_Range>, _Tp>;
593 
594  /// A range for which ranges::begin returns an input iterator.
595  template<typename _Tp>
596  concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
597 
598  /// A range for which ranges::begin returns a forward iterator.
599  template<typename _Tp>
601  = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
602 
603  /// A range for which ranges::begin returns a bidirectional iterator.
604  template<typename _Tp>
606  = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
607 
608  /// A range for which ranges::begin returns a random access iterator.
609  template<typename _Tp>
611  = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
612 
613  /// A range for which ranges::begin returns a contiguous iterator.
614  template<typename _Tp>
616  = random_access_range<_Tp> && contiguous_iterator<iterator_t<_Tp>>
617  && requires(_Tp& __t)
618  {
619  { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
620  };
621 
622  /// A range for which ranges::begin and ranges::end return the same type.
623  template<typename _Tp>
624  concept common_range
625  = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
626 
627 #if __cplusplus > 202002L
628  template<typename _Tp>
629  concept constant_range
630  = input_range<_Tp> && std::__detail::__constant_iterator<iterator_t<_Tp>>;
631 #endif
632 
633  namespace __cust_access
634  {
635 #if __cplusplus > 202020L
636  template<typename _Range>
637  constexpr auto&
638  __possibly_const_range(_Range& __r) noexcept
639  {
640  if constexpr (constant_range<const _Range> && !constant_range<_Range>)
641  return const_cast<const _Range&>(__r);
642  else
643  return __r;
644  }
645 #else
646  // If _To is an lvalue-reference, return const _Tp&, otherwise const _Tp&&.
647  template<typename _To, typename _Tp>
648  constexpr decltype(auto)
649  __as_const(_Tp& __t) noexcept
650  {
651  static_assert(std::is_same_v<_To&, _Tp&>);
652 
653  if constexpr (is_lvalue_reference_v<_To>)
654  return const_cast<const _Tp&>(__t);
655  else
656  return static_cast<const _Tp&&>(__t);
657  }
658 #endif
659 
660  struct _CBegin
661  {
662 #if __cplusplus > 202002L
663  template<__maybe_borrowed_range _Tp>
664  [[nodiscard]]
665  constexpr auto
666  operator()(_Tp&& __t) const
667  noexcept(noexcept(std::make_const_iterator
668  (ranges::begin(__cust_access::__possibly_const_range(__t)))))
669  requires requires { std::make_const_iterator
670  (ranges::begin(__cust_access::__possibly_const_range(__t))); }
671  {
672  auto& __r = __cust_access::__possibly_const_range(__t);
673  return const_iterator_t<decltype(__r)>(ranges::begin(__r));
674  }
675 #else
676  template<typename _Tp>
677  [[nodiscard]]
678  constexpr auto
679  operator()(_Tp&& __e) const
680  noexcept(noexcept(_Begin{}(__cust_access::__as_const<_Tp>(__e))))
681  requires requires { _Begin{}(__cust_access::__as_const<_Tp>(__e)); }
682  {
683  return _Begin{}(__cust_access::__as_const<_Tp>(__e));
684  }
685 #endif
686  };
687 
688  struct _CEnd final
689  {
690 #if __cplusplus > 202002L
691  template<__maybe_borrowed_range _Tp>
692  [[nodiscard]]
693  constexpr auto
694  operator()(_Tp&& __t) const
695  noexcept(noexcept(std::make_const_sentinel
696  (ranges::end(__cust_access::__possibly_const_range(__t)))))
697  requires requires { std::make_const_sentinel
698  (ranges::end(__cust_access::__possibly_const_range(__t))); }
699  {
700  auto& __r = __cust_access::__possibly_const_range(__t);
701  return const_sentinel_t<decltype(__r)>(ranges::end(__r));
702  }
703 #else
704  template<typename _Tp>
705  [[nodiscard]]
706  constexpr auto
707  operator()(_Tp&& __e) const
708  noexcept(noexcept(_End{}(__cust_access::__as_const<_Tp>(__e))))
709  requires requires { _End{}(__cust_access::__as_const<_Tp>(__e)); }
710  {
711  return _End{}(__cust_access::__as_const<_Tp>(__e));
712  }
713 #endif
714  };
715 
716  struct _CRBegin
717  {
718 #if __cplusplus > 202002L
719  template<__maybe_borrowed_range _Tp>
720  [[nodiscard]]
721  constexpr auto
722  operator()(_Tp&& __t) const
723  noexcept(noexcept(std::make_const_iterator
724  (ranges::rbegin(__cust_access::__possibly_const_range(__t)))))
725  requires requires { std::make_const_iterator
726  (ranges::rbegin(__cust_access::__possibly_const_range(__t))); }
727  {
728  auto& __r = __cust_access::__possibly_const_range(__t);
729  return const_iterator<decltype(ranges::rbegin(__r))>(ranges::rbegin(__r));
730  }
731 #else
732  template<typename _Tp>
733  [[nodiscard]]
734  constexpr auto
735  operator()(_Tp&& __e) const
736  noexcept(noexcept(_RBegin{}(__cust_access::__as_const<_Tp>(__e))))
737  requires requires { _RBegin{}(__cust_access::__as_const<_Tp>(__e)); }
738  {
739  return _RBegin{}(__cust_access::__as_const<_Tp>(__e));
740  }
741 #endif
742  };
743 
744  struct _CREnd
745  {
746 #if __cplusplus > 202002L
747  template<__maybe_borrowed_range _Tp>
748  [[nodiscard]]
749  constexpr auto
750  operator()(_Tp&& __t) const
751  noexcept(noexcept(std::make_const_sentinel
752  (ranges::rend(__cust_access::__possibly_const_range(__t)))))
753  requires requires { std::make_const_sentinel
754  (ranges::rend(__cust_access::__possibly_const_range(__t))); }
755  {
756  auto& __r = __cust_access::__possibly_const_range(__t);
757  return const_sentinel<decltype(ranges::rend(__r))>(ranges::rend(__r));
758  }
759 #else
760  template<typename _Tp>
761  [[nodiscard]]
762  constexpr auto
763  operator()(_Tp&& __e) const
764  noexcept(noexcept(_REnd{}(__cust_access::__as_const<_Tp>(__e))))
765  requires requires { _REnd{}(__cust_access::__as_const<_Tp>(__e)); }
766  {
767  return _REnd{}(__cust_access::__as_const<_Tp>(__e));
768  }
769 #endif
770  };
771 
772  struct _CData
773  {
774 #if __cplusplus > 202002L
775  template<__maybe_borrowed_range _Tp>
776  [[nodiscard]]
777  constexpr const auto*
778  operator()(_Tp&& __t) const
779  noexcept(noexcept(ranges::data(__cust_access::__possibly_const_range(__t))))
780  requires requires { ranges::data(__cust_access::__possibly_const_range(__t)); }
781  { return ranges::data(__cust_access::__possibly_const_range(__t)); }
782 #else
783  template<typename _Tp>
784  [[nodiscard]]
785  constexpr auto
786  operator()(_Tp&& __e) const
787  noexcept(noexcept(_Data{}(__cust_access::__as_const<_Tp>(__e))))
788  requires requires { _Data{}(__cust_access::__as_const<_Tp>(__e)); }
789  {
790  return _Data{}(__cust_access::__as_const<_Tp>(__e));
791  }
792 #endif
793  };
794 
795  } // namespace __cust_access
796 
797  inline namespace __cust
798  {
799  inline constexpr __cust_access::_CBegin cbegin{};
800  inline constexpr __cust_access::_CEnd cend{};
801  inline constexpr __cust_access::_CRBegin crbegin{};
802  inline constexpr __cust_access::_CREnd crend{};
803  inline constexpr __cust_access::_CData cdata{};
804  }
805 
806  namespace __detail
807  {
808  template<typename _Tp>
809  inline constexpr bool __is_initializer_list = false;
810 
811  template<typename _Tp>
812  inline constexpr bool __is_initializer_list<initializer_list<_Tp>> = true;
813  } // namespace __detail
814 
815  /// A range which can be safely converted to a view.
816  template<typename _Tp>
817  concept viewable_range = range<_Tp>
818  && ((view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>)
819  || (!view<remove_cvref_t<_Tp>>
820  && (is_lvalue_reference_v<_Tp>
821  || (movable<remove_reference_t<_Tp>>
822  && !__detail::__is_initializer_list<remove_cvref_t<_Tp>>))));
823 
824  // [range.iter.ops] range iterator operations
825 
826  struct __advance_fn final
827  {
828  template<input_or_output_iterator _It>
829  constexpr void
830  operator()(_It& __it, iter_difference_t<_It> __n) const
831  {
832  if constexpr (random_access_iterator<_It>)
833  __it += __n;
834  else if constexpr (bidirectional_iterator<_It>)
835  {
836  if (__n > 0)
837  {
838  do
839  {
840  ++__it;
841  }
842  while (--__n);
843  }
844  else if (__n < 0)
845  {
846  do
847  {
848  --__it;
849  }
850  while (++__n);
851  }
852  }
853  else
854  {
855  // cannot decrement a non-bidirectional iterator
856  __glibcxx_assert(__n >= 0);
857  while (__n-- > 0)
858  ++__it;
859  }
860  }
861 
862  template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
863  constexpr void
864  operator()(_It& __it, _Sent __bound) const
865  {
866  if constexpr (assignable_from<_It&, _Sent>)
867  __it = std::move(__bound);
868  else if constexpr (sized_sentinel_for<_Sent, _It>)
869  (*this)(__it, __bound - __it);
870  else
871  {
872  while (__it != __bound)
873  ++__it;
874  }
875  }
876 
877  template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
878  constexpr iter_difference_t<_It>
879  operator()(_It& __it, iter_difference_t<_It> __n, _Sent __bound) const
880  {
881  if constexpr (sized_sentinel_for<_Sent, _It>)
882  {
883  const auto __diff = __bound - __it;
884 
885  if (__diff == 0)
886  return __n;
887  else if (__diff > 0 ? __n >= __diff : __n <= __diff)
888  {
889  (*this)(__it, __bound);
890  return __n - __diff;
891  }
892  else if (__n != 0) [[likely]]
893  {
894  // n and bound must not lead in opposite directions:
895  __glibcxx_assert((__n < 0) == (__diff < 0));
896 
897  (*this)(__it, __n);
898  return 0;
899  }
900  else
901  return 0;
902  }
903  else if (__it == __bound || __n == 0)
904  return __n;
905  else if (__n > 0)
906  {
907  iter_difference_t<_It> __m = 0;
908  do
909  {
910  ++__it;
911  ++__m;
912  }
913  while (__m != __n && __it != __bound);
914  return __n - __m;
915  }
916  else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
917  {
918  iter_difference_t<_It> __m = 0;
919  do
920  {
921  --__it;
922  --__m;
923  }
924  while (__m != __n && __it != __bound);
925  return __n - __m;
926  }
927  else
928  {
929  // cannot decrement a non-bidirectional iterator
930  __glibcxx_assert(__n >= 0);
931  return __n;
932  }
933  }
934 
935  void operator&() const = delete;
936  };
937 
938  inline constexpr __advance_fn advance{};
939 
940  struct __distance_fn final
941  {
942  // _GLIBCXX_RESOLVE_LIB_DEFECTS
943  // 3664. LWG 3392 broke std::ranges::distance(a, a+3)
944  template<typename _It, sentinel_for<_It> _Sent>
945  requires (!sized_sentinel_for<_Sent, _It>)
946  constexpr iter_difference_t<_It>
947  operator()[[nodiscard]](_It __first, _Sent __last) const
948  {
949  iter_difference_t<_It> __n = 0;
950  while (__first != __last)
951  {
952  ++__first;
953  ++__n;
954  }
955  return __n;
956  }
957 
958  template<typename _It, sized_sentinel_for<decay_t<_It>> _Sent>
959  [[nodiscard]]
960  constexpr iter_difference_t<decay_t<_It>>
961  operator()(_It&& __first, _Sent __last) const
962  { return __last - static_cast<const decay_t<_It>&>(__first); }
963 
964  template<range _Range>
965  [[nodiscard]]
966  constexpr range_difference_t<_Range>
967  operator()(_Range&& __r) const
968  {
969  if constexpr (sized_range<_Range>)
970  return static_cast<range_difference_t<_Range>>(ranges::size(__r));
971  else
972  return (*this)(ranges::begin(__r), ranges::end(__r));
973  }
974 
975  void operator&() const = delete;
976  };
977 
978  inline constexpr __distance_fn distance{};
979 
980  struct __next_fn final
981  {
982  template<input_or_output_iterator _It>
983  [[nodiscard]]
984  constexpr _It
985  operator()(_It __x) const
986  {
987  ++__x;
988  return __x;
989  }
990 
991  template<input_or_output_iterator _It>
992  [[nodiscard]]
993  constexpr _It
994  operator()(_It __x, iter_difference_t<_It> __n) const
995  {
996  ranges::advance(__x, __n);
997  return __x;
998  }
999 
1000  template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
1001  [[nodiscard]]
1002  constexpr _It
1003  operator()(_It __x, _Sent __bound) const
1004  {
1005  ranges::advance(__x, __bound);
1006  return __x;
1007  }
1008 
1009  template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
1010  [[nodiscard]]
1011  constexpr _It
1012  operator()(_It __x, iter_difference_t<_It> __n, _Sent __bound) const
1013  {
1014  ranges::advance(__x, __n, __bound);
1015  return __x;
1016  }
1017 
1018  void operator&() const = delete;
1019  };
1020 
1021  inline constexpr __next_fn next{};
1022 
1023  struct __prev_fn final
1024  {
1025  template<bidirectional_iterator _It>
1026  [[nodiscard]]
1027  constexpr _It
1028  operator()(_It __x) const
1029  {
1030  --__x;
1031  return __x;
1032  }
1033 
1034  template<bidirectional_iterator _It>
1035  [[nodiscard]]
1036  constexpr _It
1037  operator()(_It __x, iter_difference_t<_It> __n) const
1038  {
1039  ranges::advance(__x, -__n);
1040  return __x;
1041  }
1042 
1043  template<bidirectional_iterator _It>
1044  [[nodiscard]]
1045  constexpr _It
1046  operator()(_It __x, iter_difference_t<_It> __n, _It __bound) const
1047  {
1048  ranges::advance(__x, -__n, __bound);
1049  return __x;
1050  }
1051 
1052  void operator&() const = delete;
1053  };
1054 
1055  inline constexpr __prev_fn prev{};
1056 
1057  /// Type returned by algorithms instead of a dangling iterator or subrange.
1058  struct dangling
1059  {
1060  constexpr dangling() noexcept = default;
1061  template<typename... _Args>
1062  constexpr dangling(_Args&&...) noexcept { }
1063  };
1064 
1065  template<range _Range>
1066  using borrowed_iterator_t = __conditional_t<borrowed_range<_Range>,
1067  iterator_t<_Range>,
1068  dangling>;
1069 
1070 } // namespace ranges
1071 _GLIBCXX_END_NAMESPACE_VERSION
1072 } // namespace std
1073 #endif // library concepts
1074 #endif // C++20
1075 #endif // _GLIBCXX_RANGES_BASE_H
concept bidirectional_range
A range for which ranges::begin returns a bidirectional iterator.
Definition: ranges_base.h:606
concept forward_range
A range for which ranges::begin returns a forward iterator.
Definition: ranges_base.h:601
constexpr bool enable_view
[range.view] The ranges::enable_view boolean.
Definition: ranges_base.h:579
concept viewable_range
A range which can be safely converted to a view.
Definition: ranges_base.h:817
concept contiguous_range
A range for which ranges::begin returns a contiguous iterator.
Definition: ranges_base.h:616
concept view
[range.view] The ranges::view concept.
Definition: ranges_base.h:585
concept input_range
A range for which ranges::begin returns an input iterator.
Definition: ranges_base.h:596
concept output_range
A range for which ranges::begin returns an output iterator.
Definition: ranges_base.h:592
concept range
[range.range] The range concept.
Definition: ranges_base.h:501
concept random_access_range
A range for which ranges::begin returns a random access iterator.
Definition: ranges_base.h:611
concept sized_range
[range.sized] The sized_range concept.
Definition: ranges_base.h:550
concept common_range
A range for which ranges::begin and ranges::end return the same type.
Definition: ranges_base.h:625
concept borrowed_range
[range.range] The borrowed_range concept.
Definition: ranges_base.h:510
constexpr _Tp * to_address(_Tp *__ptr) noexcept
Obtain address referenced by a pointer to an object.
Definition: ptr_traits.h:250
typename remove_reference< _Tp >::type remove_reference_t
Alias template for remove_reference.
Definition: type_traits:1640
typename remove_cvref< _Tp >::type remove_cvref_t
Definition: type_traits:3451
constexpr bool is_bounded_array_v
True for a type that is an array of known bound.
Definition: type_traits:3499
constexpr bool is_unbounded_array_v
True for a type that is an array of unknown bound.
Definition: type_traits:3508
auto declval() noexcept -> decltype(__declval< _Tp >(0))
Definition: type_traits:2386
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:97
_Tp * end(valarray< _Tp > &__va) noexcept
Return an iterator pointing to one past the last element of the valarray.
Definition: valarray:1249
_Tp * begin(valarray< _Tp > &__va) noexcept
Return an iterator pointing to the first element of the valarray.
Definition: valarray:1227
constexpr reverse_iterator< _Iterator > make_reverse_iterator(_Iterator __i)
Generator function for reverse_iterator.
ISO C++ entities toplevel namespace is std.
ranges::__cust_imove::_IMove::__type< _Tp & > iter_rvalue_reference_t
The result type of ranges::iter_move(std::declval<_Tp&>())
constexpr bitset< _Nb > operator&(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Definition: bitset:1553
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
concept same_as
[concept.same], concept same_as
Definition: concepts:63
constexpr auto crend(const _Container &__cont) -> decltype(std::rend(__cont))
Return a reverse iterator pointing one past the first element of the const container.
Definition: range_access.h:249
constexpr auto rend(_Container &__cont) -> decltype(__cont.rend())
Return a reverse iterator pointing one past the first element of the container.
Definition: range_access.h:172
constexpr auto cend(const _Container &__cont) noexcept(noexcept(std::end(__cont))) -> decltype(std::end(__cont))
Return an iterator pointing to one past the last element of the const container.
Definition: range_access.h:138
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
Return whether a container is empty.
Definition: range_access.h:284
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Definition: range_access.h:264
constexpr void advance(_InputIterator &__i, _Distance __n)
A generalization of pointer arithmetic.
constexpr auto rbegin(_Container &__cont) -> decltype(__cont.rbegin())
Return a reverse iterator pointing to the last element of the container.
Definition: range_access.h:150
constexpr auto crbegin(const _Container &__cont) -> decltype(std::rbegin(__cont))
Return a reverse iterator pointing to the last element of the const container.
Definition: range_access.h:238
constexpr auto data(_Container &__cont) noexcept(noexcept(__cont.data())) -> decltype(__cont.data())
Return the data pointer of a container.
Definition: range_access.h:314
constexpr auto cbegin(const _Container &__cont) noexcept(noexcept(std::begin(__cont))) -> decltype(std::begin(__cont))
Return an iterator pointing to the first element of the const container.
Definition: range_access.h:126
__numeric_traits_integer< _Tp > __int_traits
Convenience alias for __numeric_traits<integer-type>.
[range.view] The ranges::view_base type.
Definition: ranges_base.h:575
Type returned by algorithms instead of a dangling iterator or subrange.
Definition: ranges_base.h:1059