xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/bits/range_access.h (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
1 // <range_access.h> -*- C++ -*-
2 
3 // Copyright (C) 2010-2020 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/range_access.h
26  *  This is an internal header file, included by other library headers.
27  *  Do not attempt to use it directly. @headername{iterator}
28  */
29 
30 #ifndef _GLIBCXX_RANGE_ACCESS_H
31 #define _GLIBCXX_RANGE_ACCESS_H 1
32 
33 #pragma GCC system_header
34 
35 #if __cplusplus >= 201103L
36 #include <initializer_list>
37 #include <bits/iterator_concepts.h>
38 #include <ext/numeric_traits.h>
39 
40 namespace std _GLIBCXX_VISIBILITY(default)
41 {
42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
43 
44   /**
45    *  @brief  Return an iterator pointing to the first element of
46    *          the container.
47    *  @param  __cont  Container.
48    */
49   template<typename _Container>
50     inline _GLIBCXX17_CONSTEXPR auto
51     begin(_Container& __cont) -> decltype(__cont.begin())
52     { return __cont.begin(); }
53 
54   /**
55    *  @brief  Return an iterator pointing to the first element of
56    *          the const container.
57    *  @param  __cont  Container.
58    */
59   template<typename _Container>
60     inline _GLIBCXX17_CONSTEXPR auto
61     begin(const _Container& __cont) -> decltype(__cont.begin())
62     { return __cont.begin(); }
63 
64   /**
65    *  @brief  Return an iterator pointing to one past the last element of
66    *          the container.
67    *  @param  __cont  Container.
68    */
69   template<typename _Container>
70     inline _GLIBCXX17_CONSTEXPR auto
71     end(_Container& __cont) -> decltype(__cont.end())
72     { return __cont.end(); }
73 
74   /**
75    *  @brief  Return an iterator pointing to one past the last element of
76    *          the const container.
77    *  @param  __cont  Container.
78    */
79   template<typename _Container>
80     inline _GLIBCXX17_CONSTEXPR auto
81     end(const _Container& __cont) -> decltype(__cont.end())
82     { return __cont.end(); }
83 
84   /**
85    *  @brief  Return an iterator pointing to the first element of the array.
86    *  @param  __arr  Array.
87    */
88   template<typename _Tp, size_t _Nm>
89     inline _GLIBCXX14_CONSTEXPR _Tp*
90     begin(_Tp (&__arr)[_Nm]) noexcept
91     { return __arr; }
92 
93   /**
94    *  @brief  Return an iterator pointing to one past the last element
95    *          of the array.
96    *  @param  __arr  Array.
97    */
98   template<typename _Tp, size_t _Nm>
99     inline _GLIBCXX14_CONSTEXPR _Tp*
100     end(_Tp (&__arr)[_Nm]) noexcept
101     { return __arr + _Nm; }
102 
103 #if __cplusplus >= 201402L
104 
105   template<typename _Tp> class valarray;
106   // These overloads must be declared for cbegin and cend to use them.
107   template<typename _Tp> _Tp* begin(valarray<_Tp>&) noexcept;
108   template<typename _Tp> const _Tp* begin(const valarray<_Tp>&) noexcept;
109   template<typename _Tp> _Tp* end(valarray<_Tp>&) noexcept;
110   template<typename _Tp> const _Tp* end(const valarray<_Tp>&) noexcept;
111 
112   /**
113    *  @brief  Return an iterator pointing to the first element of
114    *          the const container.
115    *  @param  __cont  Container.
116    */
117   template<typename _Container>
118     inline constexpr auto
119     cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont)))
120       -> decltype(std::begin(__cont))
121     { return std::begin(__cont); }
122 
123   /**
124    *  @brief  Return an iterator pointing to one past the last element of
125    *          the const container.
126    *  @param  __cont  Container.
127    */
128   template<typename _Container>
129     inline constexpr auto
130     cend(const _Container& __cont) noexcept(noexcept(std::end(__cont)))
131       -> decltype(std::end(__cont))
132     { return std::end(__cont); }
133 
134   /**
135    *  @brief  Return a reverse iterator pointing to the last element of
136    *          the container.
137    *  @param  __cont  Container.
138    */
139   template<typename _Container>
140     inline _GLIBCXX17_CONSTEXPR auto
141     rbegin(_Container& __cont) -> decltype(__cont.rbegin())
142     { return __cont.rbegin(); }
143 
144   /**
145    *  @brief  Return a reverse iterator pointing to the last element of
146    *          the const container.
147    *  @param  __cont  Container.
148    */
149   template<typename _Container>
150     inline _GLIBCXX17_CONSTEXPR auto
151     rbegin(const _Container& __cont) -> decltype(__cont.rbegin())
152     { return __cont.rbegin(); }
153 
154   /**
155    *  @brief  Return a reverse iterator pointing one past the first element of
156    *          the container.
157    *  @param  __cont  Container.
158    */
159   template<typename _Container>
160     inline _GLIBCXX17_CONSTEXPR auto
161     rend(_Container& __cont) -> decltype(__cont.rend())
162     { return __cont.rend(); }
163 
164   /**
165    *  @brief  Return a reverse iterator pointing one past the first element of
166    *          the const container.
167    *  @param  __cont  Container.
168    */
169   template<typename _Container>
170     inline _GLIBCXX17_CONSTEXPR auto
171     rend(const _Container& __cont) -> decltype(__cont.rend())
172     { return __cont.rend(); }
173 
174   /**
175    *  @brief  Return a reverse iterator pointing to the last element of
176    *          the array.
177    *  @param  __arr  Array.
178    */
179   template<typename _Tp, size_t _Nm>
180     inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
181     rbegin(_Tp (&__arr)[_Nm]) noexcept
182     { return reverse_iterator<_Tp*>(__arr + _Nm); }
183 
184   /**
185    *  @brief  Return a reverse iterator pointing one past the first element of
186    *          the array.
187    *  @param  __arr  Array.
188    */
189   template<typename _Tp, size_t _Nm>
190     inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
191     rend(_Tp (&__arr)[_Nm]) noexcept
192     { return reverse_iterator<_Tp*>(__arr); }
193 
194   /**
195    *  @brief  Return a reverse iterator pointing to the last element of
196    *          the initializer_list.
197    *  @param  __il  initializer_list.
198    */
199   template<typename _Tp>
200     inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
201     rbegin(initializer_list<_Tp> __il) noexcept
202     { return reverse_iterator<const _Tp*>(__il.end()); }
203 
204   /**
205    *  @brief  Return a reverse iterator pointing one past the first element of
206    *          the initializer_list.
207    *  @param  __il  initializer_list.
208    */
209   template<typename _Tp>
210     inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
211     rend(initializer_list<_Tp> __il) noexcept
212     { return reverse_iterator<const _Tp*>(__il.begin()); }
213 
214   /**
215    *  @brief  Return a reverse iterator pointing to the last element of
216    *          the const container.
217    *  @param  __cont  Container.
218    */
219   template<typename _Container>
220     inline _GLIBCXX17_CONSTEXPR auto
221     crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont))
222     { return std::rbegin(__cont); }
223 
224   /**
225    *  @brief  Return a reverse iterator pointing one past the first element of
226    *          the const container.
227    *  @param  __cont  Container.
228    */
229   template<typename _Container>
230     inline _GLIBCXX17_CONSTEXPR auto
231     crend(const _Container& __cont) -> decltype(std::rend(__cont))
232     { return std::rend(__cont); }
233 
234 #endif // C++14
235 
236 #if __cplusplus >= 201703L
237 #define __cpp_lib_nonmember_container_access 201411
238 
239   /**
240    *  @brief  Return the size of a container.
241    *  @param  __cont  Container.
242    */
243   template <typename _Container>
244     constexpr auto
245     size(const _Container& __cont) noexcept(noexcept(__cont.size()))
246     -> decltype(__cont.size())
247     { return __cont.size(); }
248 
249   /**
250    *  @brief  Return the size of an array.
251    */
252   template <typename _Tp, size_t _Nm>
253     constexpr size_t
254     size(const _Tp (&)[_Nm]) noexcept
255     { return _Nm; }
256 
257   /**
258    *  @brief  Return whether a container is empty.
259    *  @param  __cont  Container.
260    */
261   template <typename _Container>
262     [[nodiscard]] constexpr auto
263     empty(const _Container& __cont) noexcept(noexcept(__cont.empty()))
264     -> decltype(__cont.empty())
265     { return __cont.empty(); }
266 
267   /**
268    *  @brief  Return whether an array is empty (always false).
269    */
270   template <typename _Tp, size_t _Nm>
271     [[nodiscard]] constexpr bool
272     empty(const _Tp (&)[_Nm]) noexcept
273     { return false; }
274 
275   /**
276    *  @brief  Return whether an initializer_list is empty.
277    *  @param  __il  Initializer list.
278    */
279   template <typename _Tp>
280     [[nodiscard]] constexpr bool
281     empty(initializer_list<_Tp> __il) noexcept
282     { return __il.size() == 0;}
283 
284   /**
285    *  @brief  Return the data pointer of a container.
286    *  @param  __cont  Container.
287    */
288   template <typename _Container>
289     constexpr auto
290     data(_Container& __cont) noexcept(noexcept(__cont.data()))
291     -> decltype(__cont.data())
292     { return __cont.data(); }
293 
294   /**
295    *  @brief  Return the data pointer of a const container.
296    *  @param  __cont  Container.
297    */
298   template <typename _Container>
299     constexpr auto
300     data(const _Container& __cont) noexcept(noexcept(__cont.data()))
301     -> decltype(__cont.data())
302     { return __cont.data(); }
303 
304   /**
305    *  @brief  Return the data pointer of an array.
306    *  @param  __array  Array.
307    */
308   template <typename _Tp, size_t _Nm>
309     constexpr _Tp*
310     data(_Tp (&__array)[_Nm]) noexcept
311     { return __array; }
312 
313   /**
314    *  @brief  Return the data pointer of an initializer list.
315    *  @param  __il  Initializer list.
316    */
317   template <typename _Tp>
318     constexpr const _Tp*
319     data(initializer_list<_Tp> __il) noexcept
320     { return __il.begin(); }
321 
322 #endif // C++17
323 
324 #if __cplusplus > 201703L
325 #define __cpp_lib_ssize 201902L
326   template<typename _Container>
327     constexpr auto
328     ssize(const _Container& __cont)
329     noexcept(noexcept(__cont.size()))
330     -> common_type_t<ptrdiff_t, make_signed_t<decltype(__cont.size())>>
331     {
332       using type = make_signed_t<decltype(__cont.size())>;
333       return static_cast<common_type_t<ptrdiff_t, type>>(__cont.size());
334     }
335 
336   template<typename _Tp, ptrdiff_t _Num>
337     constexpr ptrdiff_t
338     ssize(const _Tp (&)[_Num]) noexcept
339     { return _Num; }
340 
341 #ifdef __cpp_lib_concepts
342 namespace ranges
343 {
344   template<typename>
345     inline constexpr bool disable_sized_range = false;
346 
347   template<typename _Tp>
348     inline constexpr bool enable_borrowed_range = false;
349 
350   template<typename _Tp>
351     extern const bool enable_view;
352 
353   namespace __detail
354   {
355     template<integral _Tp>
356       constexpr auto
357       __to_unsigned_like(_Tp __t) noexcept
358       { return static_cast<make_unsigned_t<_Tp>>(__t); }
359 
360 #if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
361     constexpr unsigned __int128
362     __to_unsigned_like(__int128 __t) noexcept
363     { return __t; }
364 
365     constexpr unsigned __int128
366     __to_unsigned_like(unsigned __int128 __t) noexcept
367     { return __t; }
368 #endif
369 
370     template<typename _Tp>
371       using __make_unsigned_like_t
372 	= decltype(__detail::__to_unsigned_like(std::declval<_Tp>()));
373 
374     // Part of the constraints of ranges::borrowed_range
375     template<typename _Tp>
376       concept __maybe_borrowed_range
377 	= is_lvalue_reference_v<_Tp>
378 	  || enable_borrowed_range<remove_cvref_t<_Tp>>;
379 
380   } // namespace __detail
381 
382   namespace __cust_access
383   {
384     using std::ranges::__detail::__maybe_borrowed_range;
385     using std::__detail::__class_or_enum;
386     using std::__detail::__decay_copy;
387     using std::__detail::__member_begin;
388     using std::__detail::__adl_begin;
389 
390     struct _Begin
391     {
392     private:
393       template<typename _Tp>
394 	static constexpr bool
395 	_S_noexcept()
396 	{
397 	  if constexpr (is_array_v<remove_reference_t<_Tp>>)
398 	    return true;
399 	  else if constexpr (__member_begin<_Tp>)
400 	    return noexcept(__decay_copy(std::declval<_Tp&>().begin()));
401 	  else
402 	    return noexcept(__decay_copy(begin(std::declval<_Tp&>())));
403 	}
404 
405     public:
406       template<__maybe_borrowed_range _Tp>
407 	requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
408 	  || __adl_begin<_Tp>
409 	constexpr auto
410 	operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
411 	{
412 	  if constexpr (is_array_v<remove_reference_t<_Tp>>)
413 	    {
414 	      static_assert(is_lvalue_reference_v<_Tp>);
415 	      using _Up = remove_all_extents_t<remove_reference_t<_Tp>>;
416 	      static_assert(sizeof(_Up) != 0, "not array of incomplete type");
417 	      return __t + 0;
418 	    }
419 	  else if constexpr (__member_begin<_Tp>)
420 	    return __t.begin();
421 	  else
422 	    return begin(__t);
423 	}
424     };
425 
426     template<typename _Tp>
427       concept __member_end = requires(_Tp& __t)
428 	{
429 	  { __decay_copy(__t.end()) }
430 	    -> sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
431 	};
432 
433     void end(auto&) = delete;
434     void end(const auto&) = delete;
435 
436     template<typename _Tp>
437       concept __adl_end = __class_or_enum<remove_reference_t<_Tp>>
438 	&& requires(_Tp& __t)
439 	{
440 	  { __decay_copy(end(__t)) }
441 	    -> sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
442 	};
443 
444     struct _End
445     {
446     private:
447       template<typename _Tp>
448 	static constexpr bool
449 	_S_noexcept()
450 	{
451 	  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
452 	    return true;
453 	  else if constexpr (__member_end<_Tp>)
454 	    return noexcept(__decay_copy(std::declval<_Tp&>().end()));
455 	  else
456 	    return noexcept(__decay_copy(end(std::declval<_Tp&>())));
457 	}
458 
459     public:
460       template<__maybe_borrowed_range _Tp>
461 	requires is_bounded_array_v<remove_reference_t<_Tp>> || __member_end<_Tp>
462 	|| __adl_end<_Tp>
463 	constexpr auto
464 	operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
465 	{
466 	  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
467 	    {
468 	      static_assert(is_lvalue_reference_v<_Tp>);
469 	      return __t + extent_v<remove_reference_t<_Tp>>;
470 	    }
471 	  else if constexpr (__member_end<_Tp>)
472 	    return __t.end();
473 	  else
474 	    return end(__t);
475 	}
476     };
477 
478     template<typename _Tp>
479       constexpr decltype(auto)
480       __as_const(_Tp&& __t) noexcept
481       {
482 	if constexpr (is_lvalue_reference_v<_Tp>)
483 	  return static_cast<const remove_reference_t<_Tp>&>(__t);
484 	else
485 	  return static_cast<const _Tp&&>(__t);
486       }
487 
488     struct _CBegin
489     {
490       template<typename _Tp>
491 	constexpr auto
492 	operator()(_Tp&& __e) const
493 	noexcept(noexcept(_Begin{}(__cust_access::__as_const((_Tp&&)__e))))
494 	requires requires { _Begin{}(__cust_access::__as_const((_Tp&&)__e)); }
495 	{
496 	  return _Begin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
497 	}
498     };
499 
500     struct _CEnd
501     {
502       template<typename _Tp>
503 	constexpr auto
504 	operator()(_Tp&& __e) const
505 	noexcept(noexcept(_End{}(__cust_access::__as_const((_Tp&&)__e))))
506 	requires requires { _End{}(__cust_access::__as_const((_Tp&&)__e)); }
507 	{
508 	  return _End{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
509 	}
510     };
511 
512     template<typename _Tp>
513       concept __member_rbegin = requires(_Tp& __t)
514 	{
515 	  { __decay_copy(__t.rbegin()) } -> input_or_output_iterator;
516 	};
517 
518     void rbegin(auto&) = delete;
519     void rbegin(const auto&) = delete;
520 
521     template<typename _Tp>
522       concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>>
523 	&& requires(_Tp& __t)
524 	{
525 	  { __decay_copy(rbegin(__t)) } -> input_or_output_iterator;
526 	};
527 
528     template<typename _Tp>
529       concept __reversable = requires(_Tp& __t)
530 	{
531 	  { _Begin{}(__t) } -> bidirectional_iterator;
532 	  { _End{}(__t) } -> same_as<decltype(_Begin{}(__t))>;
533 	};
534 
535     struct _RBegin
536     {
537     private:
538       template<typename _Tp>
539 	static constexpr bool
540 	_S_noexcept()
541 	{
542 	  if constexpr (__member_rbegin<_Tp>)
543 	    return noexcept(__decay_copy(std::declval<_Tp&>().rbegin()));
544 	  else if constexpr (__adl_rbegin<_Tp>)
545 	    return noexcept(__decay_copy(rbegin(std::declval<_Tp&>())));
546 	  else
547 	    {
548 	      if constexpr (noexcept(_End{}(std::declval<_Tp&>())))
549 		{
550 		  using _It = decltype(_End{}(std::declval<_Tp&>()));
551 		  // std::reverse_iterator copy-initializes its member.
552 		  return is_nothrow_copy_constructible_v<_It>;
553 		}
554 	      else
555 		return false;
556 	    }
557 	}
558 
559     public:
560       template<__maybe_borrowed_range _Tp>
561 	requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
562 	constexpr auto
563 	operator()(_Tp&& __t) const
564 	noexcept(_S_noexcept<_Tp>())
565 	{
566 	  if constexpr (__member_rbegin<_Tp>)
567 	    return __t.rbegin();
568 	  else if constexpr (__adl_rbegin<_Tp>)
569 	    return rbegin(__t);
570 	  else
571 	    return std::make_reverse_iterator(_End{}(__t));
572 	}
573     };
574 
575     template<typename _Tp>
576       concept __member_rend = requires(_Tp& __t)
577 	{
578 	  { __decay_copy(__t.rend()) }
579 	    -> sentinel_for<decltype(_RBegin{}(__t))>;
580 	};
581 
582     void rend(auto&) = delete;
583     void rend(const auto&) = delete;
584 
585     template<typename _Tp>
586       concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>>
587 	&& requires(_Tp& __t)
588 	{
589 	  { __decay_copy(rend(__t)) }
590 	    -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
591 	};
592 
593     struct _REnd
594     {
595     private:
596       template<typename _Tp>
597 	static constexpr bool
598 	_S_noexcept()
599 	{
600 	  if constexpr (__member_rend<_Tp>)
601 	    return noexcept(__decay_copy(std::declval<_Tp&>().rend()));
602 	  else if constexpr (__adl_rend<_Tp>)
603 	    return noexcept(__decay_copy(rend(std::declval<_Tp&>())));
604 	  else
605 	    {
606 	      if constexpr (noexcept(_Begin{}(std::declval<_Tp&>())))
607 		{
608 		  using _It = decltype(_Begin{}(std::declval<_Tp&>()));
609 		  // std::reverse_iterator copy-initializes its member.
610 		  return is_nothrow_copy_constructible_v<_It>;
611 		}
612 	      else
613 		return false;
614 	    }
615 	}
616 
617     public:
618       template<__maybe_borrowed_range _Tp>
619 	requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
620 	constexpr auto
621 	operator()(_Tp&& __t) const
622 	noexcept(_S_noexcept<_Tp>())
623 	{
624 	  if constexpr (__member_rend<_Tp>)
625 	    return __t.rend();
626 	  else if constexpr (__adl_rend<_Tp>)
627 	    return rend(__t);
628 	  else
629 	    return std::make_reverse_iterator(_Begin{}(__t));
630 	}
631     };
632 
633     struct _CRBegin
634     {
635       template<typename _Tp>
636 	constexpr auto
637 	operator()(_Tp&& __e) const
638 	noexcept(noexcept(_RBegin{}(__cust_access::__as_const((_Tp&&)__e))))
639 	requires requires { _RBegin{}(__cust_access::__as_const((_Tp&&)__e)); }
640 	{
641 	  return _RBegin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
642 	}
643     };
644 
645     struct _CREnd
646     {
647       template<typename _Tp>
648 	constexpr auto
649 	operator()(_Tp&& __e) const
650 	noexcept(noexcept(_REnd{}(__cust_access::__as_const((_Tp&&)__e))))
651 	requires requires { _REnd{}(__cust_access::__as_const((_Tp&&)__e)); }
652 	{
653 	  return _REnd{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
654 	}
655     };
656 
657     template<typename _Tp>
658       concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
659 	&& requires(_Tp&& __t)
660 	{
661 	  { __decay_copy(std::forward<_Tp>(__t).size()) }
662 	    -> __detail::__is_integer_like;
663 	};
664 
665     void size(auto&) = delete;
666     void size(const auto&) = delete;
667 
668     template<typename _Tp>
669       concept __adl_size = __class_or_enum<remove_reference_t<_Tp>>
670 	&& !disable_sized_range<remove_cvref_t<_Tp>>
671 	&& requires(_Tp&& __t)
672 	{
673 	  { __decay_copy(size(std::forward<_Tp>(__t))) }
674 	    -> __detail::__is_integer_like;
675 	};
676 
677     template<typename _Tp>
678       concept __sentinel_size = requires(_Tp&& __t)
679 	{
680 	  { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
681 
682 	  { _End{}(std::forward<_Tp>(__t)) }
683 	    -> sized_sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
684 	};
685 
686     struct _Size
687     {
688     private:
689       template<typename _Tp>
690 	static constexpr bool
691 	_S_noexcept()
692 	{
693 	  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
694 	    return true;
695 	  else if constexpr (__member_size<_Tp>)
696 	    return noexcept(__decay_copy(std::declval<_Tp>().size()));
697 	  else if constexpr (__adl_size<_Tp>)
698 	    return noexcept(__decay_copy(size(std::declval<_Tp>())));
699 	  else if constexpr (__sentinel_size<_Tp>)
700 	    return noexcept(_End{}(std::declval<_Tp>())
701 			    - _Begin{}(std::declval<_Tp>()));
702 	}
703 
704     public:
705       template<typename _Tp>
706 	requires is_bounded_array_v<remove_reference_t<_Tp>>
707 	  || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
708 	constexpr auto
709 	operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
710 	{
711 	  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
712 	    {
713 	      return extent_v<remove_reference_t<_Tp>>;
714 	    }
715 	  else if constexpr (__member_size<_Tp>)
716 	    return std::forward<_Tp>(__e).size();
717 	  else if constexpr (__adl_size<_Tp>)
718 	    return size(std::forward<_Tp>(__e));
719 	  else if constexpr (__sentinel_size<_Tp>)
720 	    return __detail::__to_unsigned_like(
721 		_End{}(std::forward<_Tp>(__e))
722 		- _Begin{}(std::forward<_Tp>(__e)));
723 	}
724     };
725 
726     struct _SSize
727     {
728       template<typename _Tp>
729 	requires requires (_Tp&& __e)
730 	  {
731 	    _Begin{}(std::forward<_Tp>(__e));
732 	    _Size{}(std::forward<_Tp>(__e));
733 	  }
734 	constexpr auto
735 	operator()(_Tp&& __e) const
736 	noexcept(noexcept(_Size{}(std::forward<_Tp>(__e))))
737 	{
738 	  using __iter_type = decltype(_Begin{}(std::forward<_Tp>(__e)));
739 	  using __diff_type = iter_difference_t<__iter_type>;
740 	  using __gnu_cxx::__int_traits;
741 	  auto __size = _Size{}(std::forward<_Tp>(__e));
742 	  if constexpr (integral<__diff_type>)
743 	    {
744 	      if constexpr (__int_traits<__diff_type>::__digits
745 			    < __int_traits<ptrdiff_t>::__digits)
746 		return static_cast<ptrdiff_t>(__size);
747 	    }
748 	  return static_cast<__diff_type>(__size);
749 	}
750     };
751 
752     template<typename _Tp>
753       concept __member_empty = requires(_Tp&& __t)
754 	{ bool(std::forward<_Tp>(__t).empty()); };
755 
756     template<typename _Tp>
757       concept __size0_empty = requires(_Tp&& __t)
758 	{ _Size{}(std::forward<_Tp>(__t)) == 0; };
759 
760     template<typename _Tp>
761       concept __eq_iter_empty = requires(_Tp&& __t)
762 	{
763 	  { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
764 	  bool(_Begin{}(std::forward<_Tp>(__t))
765 	      == _End{}(std::forward<_Tp>(__t)));
766 	};
767 
768     struct _Empty
769     {
770     private:
771       template<typename _Tp>
772 	static constexpr bool
773 	_S_noexcept()
774 	{
775 	  if constexpr (__member_empty<_Tp>)
776 	    return noexcept(bool(std::declval<_Tp>().empty()));
777 	  else if constexpr (__size0_empty<_Tp>)
778 	    return noexcept(_Size{}(std::declval<_Tp>()) == 0);
779 	  else
780 	    return noexcept(bool(_Begin{}(std::declval<_Tp>())
781 		== _End{}(std::declval<_Tp>())));
782 	}
783 
784     public:
785       template<typename _Tp>
786 	requires __member_empty<_Tp> || __size0_empty<_Tp>
787 	|| __eq_iter_empty<_Tp>
788 	constexpr bool
789 	operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
790 	{
791 	  if constexpr (__member_empty<_Tp>)
792 	    return bool(std::forward<_Tp>(__e).empty());
793 	  else if constexpr (__size0_empty<_Tp>)
794 	    return _Size{}(std::forward<_Tp>(__e)) == 0;
795 	  else
796 	    return bool(_Begin{}(std::forward<_Tp>(__e))
797 		== _End{}(std::forward<_Tp>(__e)));
798 	}
799     };
800 
801     template<typename _Tp>
802       concept __pointer_to_object = is_pointer_v<_Tp>
803 				    && is_object_v<remove_pointer_t<_Tp>>;
804 
805     template<typename _Tp>
806       concept __member_data = is_lvalue_reference_v<_Tp>
807 	&& requires(_Tp __t) { { __t.data() } -> __pointer_to_object; };
808 
809     template<typename _Tp>
810       concept __begin_data = requires(_Tp&& __t)
811 	{ { _Begin{}(std::forward<_Tp>(__t)) } -> contiguous_iterator; };
812 
813     struct _Data
814     {
815     private:
816       template<typename _Tp>
817 	static constexpr bool
818 	_S_noexcept()
819 	{
820 	  if constexpr (__member_data<_Tp>)
821 	    return noexcept(__decay_copy(std::declval<_Tp>().data()));
822 	  else
823 	    return noexcept(_Begin{}(std::declval<_Tp>()));
824 	}
825 
826     public:
827       template<__maybe_borrowed_range _Tp>
828 	requires __member_data<_Tp> || __begin_data<_Tp>
829 	constexpr auto
830 	operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
831 	{
832 	  if constexpr (__member_data<_Tp>)
833 	    return __e.data();
834 	  else
835 	    return std::to_address(_Begin{}(std::forward<_Tp>(__e)));
836 	}
837     };
838 
839     struct _CData
840     {
841       template<typename _Tp>
842 	constexpr auto
843 	operator()(_Tp&& __e) const
844 	noexcept(noexcept(_Data{}(__cust_access::__as_const((_Tp&&)__e))))
845 	requires requires { _Data{}(__cust_access::__as_const((_Tp&&)__e)); }
846 	{
847 	  return _Data{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
848 	}
849     };
850 
851   } // namespace __cust_access
852 
853   inline namespace __cust
854   {
855     inline constexpr __cust_access::_Begin begin{};
856     inline constexpr __cust_access::_End end{};
857     inline constexpr __cust_access::_CBegin cbegin{};
858     inline constexpr __cust_access::_CEnd cend{};
859     inline constexpr __cust_access::_RBegin rbegin{};
860     inline constexpr __cust_access::_REnd rend{};
861     inline constexpr __cust_access::_CRBegin crbegin{};
862     inline constexpr __cust_access::_CREnd crend{};
863     inline constexpr __cust_access::_Size size{};
864     inline constexpr __cust_access::_SSize ssize{};
865     inline constexpr __cust_access::_Empty empty{};
866     inline constexpr __cust_access::_Data data{};
867     inline constexpr __cust_access::_CData cdata{};
868   }
869 
870   /// [range.range] The range concept.
871   template<typename _Tp>
872     concept range = requires(_Tp& __t)
873       {
874 	ranges::begin(__t);
875 	ranges::end(__t);
876       };
877 
878   /// [range.range] The borrowed_range concept.
879   template<typename _Tp>
880     concept borrowed_range
881       = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>;
882 
883   template<typename _Tp>
884     using iterator_t = std::__detail::__range_iter_t<_Tp>;
885 
886   template<range _Range>
887     using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
888 
889   template<range _Range>
890     using range_difference_t = iter_difference_t<iterator_t<_Range>>;
891 
892   template<range _Range>
893     using range_value_t = iter_value_t<iterator_t<_Range>>;
894 
895   template<range _Range>
896     using range_reference_t = iter_reference_t<iterator_t<_Range>>;
897 
898   template<range _Range>
899     using range_rvalue_reference_t
900       = iter_rvalue_reference_t<iterator_t<_Range>>;
901 
902   /// [range.sized] The sized_range concept.
903   template<typename _Tp>
904     concept sized_range = range<_Tp>
905       && requires(_Tp& __t) { ranges::size(__t); };
906 
907   template<sized_range _Range>
908     using range_size_t = decltype(ranges::size(std::declval<_Range&>()));
909 
910   // [range.refinements]
911 
912   /// A range for which ranges::begin returns an output iterator.
913   template<typename _Range, typename _Tp>
914     concept output_range
915       = range<_Range> && output_iterator<iterator_t<_Range>, _Tp>;
916 
917   /// A range for which ranges::begin returns an input iterator.
918   template<typename _Tp>
919     concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
920 
921   /// A range for which ranges::begin returns a forward iterator.
922   template<typename _Tp>
923     concept forward_range
924       = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
925 
926   /// A range for which ranges::begin returns a bidirectional iterator.
927   template<typename _Tp>
928     concept bidirectional_range
929       = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
930 
931   /// A range for which ranges::begin returns a random access iterator.
932   template<typename _Tp>
933     concept random_access_range
934       = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
935 
936   /// A range for which ranges::begin returns a contiguous iterator.
937   template<typename _Tp>
938     concept contiguous_range
939       = random_access_range<_Tp> && contiguous_iterator<iterator_t<_Tp>>
940       && requires(_Tp& __t)
941       {
942 	{ ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
943       };
944 
945   /// A range for which ranges::begin and ranges::end return the same type.
946   template<typename _Tp>
947     concept common_range
948       = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
949 
950   // [range.iter.ops] range iterator operations
951 
952   struct __advance_fn
953   {
954     template<input_or_output_iterator _It>
955       constexpr void
956       operator()(_It& __it, iter_difference_t<_It> __n) const
957       {
958 	if constexpr (random_access_iterator<_It>)
959 	  __it += __n;
960 	else if constexpr (bidirectional_iterator<_It>)
961 	  {
962 	    if (__n > 0)
963 	      {
964 		do
965 		  {
966 		    ++__it;
967 		  }
968 		while (--__n);
969 	      }
970 	    else if (__n < 0)
971 	      {
972 		do
973 		  {
974 		    --__it;
975 		  }
976 		while (++__n);
977 	      }
978 	  }
979 	else
980 	  {
981 #ifdef __cpp_lib_is_constant_evaluated
982 	    if (std::is_constant_evaluated() && __n < 0)
983 	      throw "attempt to decrement a non-bidirectional iterator";
984 #endif
985 	    __glibcxx_assert(__n >= 0);
986 	    while (__n-- > 0)
987 	      ++__it;
988 	  }
989       }
990 
991     template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
992       constexpr void
993       operator()(_It& __it, _Sent __bound) const
994       {
995 	if constexpr (assignable_from<_It&, _Sent>)
996 	  __it = std::move(__bound);
997 	else if constexpr (sized_sentinel_for<_Sent, _It>)
998 	  (*this)(__it, __bound - __it);
999 	else
1000 	  {
1001 	    while (__it != __bound)
1002 	      ++__it;
1003 	  }
1004       }
1005 
1006     template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
1007       constexpr iter_difference_t<_It>
1008       operator()(_It& __it, iter_difference_t<_It> __n, _Sent __bound) const
1009       {
1010 	if constexpr (sized_sentinel_for<_Sent, _It>)
1011 	  {
1012 	    const auto __diff = __bound - __it;
1013 
1014 	    if (__diff == 0)
1015 	      return __n;
1016 	    else if (__diff > 0 ? __n >= __diff : __n <= __diff)
1017 	      {
1018 		(*this)(__it, __bound);
1019 		return __n - __diff;
1020 	      }
1021 	    else if (__n != 0) [[likely]]
1022 	      {
1023 #ifdef __cpp_lib_is_constant_evaluated
1024 		if (std::is_constant_evaluated() && !(__n < 0 == __diff < 0))
1025 		  throw "inconsistent directions for distance and bound";
1026 #endif
1027 		// n and bound must not lead in opposite directions:
1028 		__glibcxx_assert(__n < 0 == __diff < 0);
1029 
1030 		(*this)(__it, __n);
1031 		return 0;
1032 	      }
1033 	    else
1034 	      return 0;
1035 	  }
1036 	else if (__it == __bound || __n == 0)
1037 	  return __n;
1038 	else if (__n > 0)
1039 	  {
1040 	    iter_difference_t<_It> __m = 0;
1041 	    do
1042 	      {
1043 		++__it;
1044 		++__m;
1045 	      }
1046 	    while (__m != __n && __it != __bound);
1047 	    return __n - __m;
1048 	  }
1049 	else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
1050 	  {
1051 	    iter_difference_t<_It> __m = 0;
1052 	    do
1053 	      {
1054 		--__it;
1055 		--__m;
1056 	      }
1057 	    while (__m != __n && __it != __bound);
1058 	    return __n - __m;
1059 	  }
1060 	else
1061 	  {
1062 #ifdef __cpp_lib_is_constant_evaluated
1063 	    if (std::is_constant_evaluated() && __n < 0)
1064 	      throw "attempt to decrement a non-bidirectional iterator";
1065 #endif
1066 	    __glibcxx_assert(__n >= 0);
1067 	    return __n;
1068 	  }
1069       }
1070   };
1071 
1072   inline constexpr __advance_fn advance{};
1073 
1074   struct __distance_fn
1075   {
1076     template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
1077       constexpr iter_difference_t<_It>
1078       operator()(_It __first, _Sent __last) const
1079       {
1080 	if constexpr (sized_sentinel_for<_Sent, _It>)
1081 	  return __last - __first;
1082 	else
1083 	  {
1084 	    iter_difference_t<_It> __n = 0;
1085 	    while (__first != __last)
1086 	      {
1087 		++__first;
1088 		++__n;
1089 	      }
1090 	    return __n;
1091 	  }
1092       }
1093 
1094     template<range _Range>
1095       constexpr range_difference_t<_Range>
1096       operator()(_Range&& __r) const
1097       {
1098 	if constexpr (sized_range<_Range>)
1099 	  return static_cast<range_difference_t<_Range>>(ranges::size(__r));
1100 	else
1101 	  return (*this)(ranges::begin(__r), ranges::end(__r));
1102       }
1103   };
1104 
1105   inline constexpr __distance_fn distance{};
1106 
1107   struct __next_fn
1108   {
1109     template<input_or_output_iterator _It>
1110       constexpr _It
1111       operator()(_It __x) const
1112       {
1113 	++__x;
1114 	return __x;
1115       }
1116 
1117     template<input_or_output_iterator _It>
1118       constexpr _It
1119       operator()(_It __x, iter_difference_t<_It> __n) const
1120       {
1121 	ranges::advance(__x, __n);
1122 	return __x;
1123       }
1124 
1125     template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
1126       constexpr _It
1127       operator()(_It __x, _Sent __bound) const
1128       {
1129 	ranges::advance(__x, __bound);
1130 	return __x;
1131       }
1132 
1133     template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
1134       constexpr _It
1135       operator()(_It __x, iter_difference_t<_It> __n, _Sent __bound) const
1136       {
1137 	ranges::advance(__x, __n, __bound);
1138 	return __x;
1139       }
1140   };
1141 
1142   inline constexpr __next_fn next{};
1143 
1144   struct __prev_fn
1145   {
1146     template<bidirectional_iterator _It>
1147       constexpr _It
1148       operator()(_It __x) const
1149       {
1150 	--__x;
1151 	return __x;
1152       }
1153 
1154     template<bidirectional_iterator _It>
1155       constexpr _It
1156       operator()(_It __x, iter_difference_t<_It> __n) const
1157       {
1158 	ranges::advance(__x, -__n);
1159 	return __x;
1160       }
1161 
1162     template<bidirectional_iterator _It>
1163       constexpr _It
1164       operator()(_It __x, iter_difference_t<_It> __n, _It __bound) const
1165       {
1166 	ranges::advance(__x, -__n, __bound);
1167 	return __x;
1168       }
1169   };
1170 
1171   inline constexpr __prev_fn prev{};
1172 
1173 } // namespace ranges
1174 #endif // library concepts
1175 #endif // C++20
1176 _GLIBCXX_END_NAMESPACE_VERSION
1177 } // namespace
1178 
1179 #endif // C++11
1180 
1181 #endif // _GLIBCXX_RANGE_ACCESS_H
1182