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
40namespace 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
342namespace 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