30 #ifndef _GLIBCXX_RANGES_BASE_H
31 #define _GLIBCXX_RANGES_BASE_H 1
33 #ifdef _GLIBCXX_SYSHDR
34 #pragma GCC system_header
37 #if __cplusplus > 201703L
44 #if __glibcxx_containers_ranges // C++ >= 23
48 #pragma GCC diagnostic push
49 #pragma GCC diagnostic ignored "-Wpedantic" // __int128
51 #if __glibcxx_algorithm_default_value_type // C++ >= 26
52 # define _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_I, _P) = projected_value_t<_I, _P>
54 # define _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_I, _P)
57 #ifdef __cpp_lib_concepts
58 namespace std _GLIBCXX_VISIBILITY(default)
60 _GLIBCXX_BEGIN_NAMESPACE_VERSION
64 inline constexpr
bool disable_sized_range =
false;
66 template<
typename _Tp>
67 inline constexpr
bool enable_borrowed_range =
false;
71 [[__gnu__::__always_inline__]]
72 constexpr __max_size_type
73 __to_unsigned_like(__max_size_type __t) noexcept
76 [[__gnu__::__always_inline__]]
77 constexpr __max_size_type
78 __to_unsigned_like(__max_diff_type __t) noexcept
79 {
return __max_size_type(__t); }
81 template<
integral _Tp>
82 [[__gnu__::__always_inline__]]
84 __to_unsigned_like(_Tp __t) noexcept
85 {
return static_cast<make_unsigned_t<_Tp>
>(__t); }
87 template<
typename _Tp>
88 using __make_unsigned_like_t
89 = decltype(__detail::__to_unsigned_like(std::declval<_Tp>()));
92 template<
typename _Tp>
93 concept __maybe_borrowed_range
94 = is_lvalue_reference_v<_Tp>
95 || enable_borrowed_range<remove_cvref_t<_Tp>>;
102 using std::ranges::__detail::__maybe_borrowed_range;
103 using std::__detail::__range_iter_t;
108 template<
typename _Tp>
109 static consteval
bool
112 if constexpr (is_array_v<remove_reference_t<_Tp>>)
114 else if constexpr (__member_begin<_Tp>)
121 template<__maybe_borrowed_range _Tp>
124 [[nodiscard, __gnu__::__always_inline__]]
126 operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
128 if constexpr (is_array_v<remove_reference_t<_Tp>>)
130 static_assert(is_lvalue_reference_v<_Tp>);
133 else if constexpr (__member_begin<_Tp>)
140 template<
typename _Tp>
141 concept __member_end = requires(_Tp& __t)
143 { _GLIBCXX_AUTO_CAST(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>;
149 template<
typename _Tp>
150 concept __adl_end = __class_or_enum<remove_reference_t<_Tp>>
151 && requires(_Tp& __t)
153 { _GLIBCXX_AUTO_CAST(
end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>;
159 template<
typename _Tp>
160 static consteval
bool
163 if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
165 else if constexpr (__member_end<_Tp>)
166 return noexcept(_GLIBCXX_AUTO_CAST(
std::
declval<_Tp&>().
end()));
168 return noexcept(_GLIBCXX_AUTO_CAST(
end(
std::
declval<_Tp&>())));
172 template<__maybe_borrowed_range _Tp>
174 || __member_end<_Tp> || __adl_end<_Tp>
175 [[nodiscard, __gnu__::__always_inline__]]
177 operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
179 if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
181 static_assert(is_lvalue_reference_v<_Tp>);
182 return __t + extent_v<remove_reference_t<_Tp>>;
184 else if constexpr (__member_end<_Tp>)
191 template<
typename _Tp>
192 concept __member_rbegin = requires(_Tp& __t)
194 { _GLIBCXX_AUTO_CAST(__t.rbegin()) } -> input_or_output_iterator;
199 template<
typename _Tp>
200 concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>>
201 && requires(_Tp& __t)
203 { _GLIBCXX_AUTO_CAST(
rbegin(__t)) } -> input_or_output_iterator;
206 template<
typename _Tp>
207 concept __reversable = requires(_Tp& __t)
209 { _Begin{}(__t) } -> bidirectional_iterator;
210 { _End{}(__t) } ->
same_as<decltype(_Begin{}(__t))>;
216 template<
typename _Tp>
217 static consteval
bool
220 if constexpr (__member_rbegin<_Tp>)
221 return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().
rbegin()));
222 else if constexpr (__adl_rbegin<_Tp>)
223 return noexcept(_GLIBCXX_AUTO_CAST(
rbegin(std::declval<_Tp&>())));
226 if constexpr (noexcept(_End{}(std::declval<_Tp&>())))
228 using _It = decltype(_End{}(std::declval<_Tp&>()));
230 return is_nothrow_copy_constructible_v<_It>;
238 template<__maybe_borrowed_range _Tp>
239 requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
240 [[nodiscard, __gnu__::__always_inline__]]
242 operator()(_Tp&& __t)
const
243 noexcept(_S_noexcept<_Tp&>())
245 if constexpr (__member_rbegin<_Tp>)
247 else if constexpr (__adl_rbegin<_Tp>)
254 template<
typename _Tp>
255 concept __member_rend = requires(_Tp& __t)
257 { _GLIBCXX_AUTO_CAST(__t.rend()) }
258 -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
261 void rend() =
delete;
263 template<
typename _Tp>
264 concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>>
265 && requires(_Tp& __t)
267 { _GLIBCXX_AUTO_CAST(
rend(__t)) }
268 -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
274 template<
typename _Tp>
275 static consteval
bool
278 if constexpr (__member_rend<_Tp>)
279 return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().
rend()));
280 else if constexpr (__adl_rend<_Tp>)
281 return noexcept(_GLIBCXX_AUTO_CAST(
rend(std::declval<_Tp&>())));
284 if constexpr (noexcept(_Begin{}(std::declval<_Tp&>())))
286 using _It = decltype(_Begin{}(std::declval<_Tp&>()));
288 return is_nothrow_copy_constructible_v<_It>;
296 template<__maybe_borrowed_range _Tp>
297 requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
298 [[nodiscard, __gnu__::__always_inline__]]
300 operator()(_Tp&& __t)
const
301 noexcept(_S_noexcept<_Tp&>())
303 if constexpr (__member_rend<_Tp>)
305 else if constexpr (__adl_rend<_Tp>)
312 template<
typename _Tp>
313 concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
314 && requires(_Tp& __t)
316 { _GLIBCXX_AUTO_CAST(__t.size()) } -> __detail::__is_integer_like;
319 void size() =
delete;
321 template<
typename _Tp>
322 concept __adl_size = __class_or_enum<remove_reference_t<_Tp>>
323 && !disable_sized_range<remove_cvref_t<_Tp>>
324 && requires(_Tp& __t)
326 { _GLIBCXX_AUTO_CAST(
size(__t)) } -> __detail::__is_integer_like;
329 template<
typename _Tp>
330 concept __sentinel_size = requires(_Tp& __t)
332 requires (!is_unbounded_array_v<remove_reference_t<_Tp>>);
334 { _Begin{}(__t) } -> forward_iterator;
336 { _End{}(__t) } -> sized_sentinel_for<decltype(_Begin{}(__t))>;
338 __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t));
344 template<
typename _Tp>
345 static consteval
bool
348 if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
350 else if constexpr (__member_size<_Tp>)
352 else if constexpr (__adl_size<_Tp>)
354 else if constexpr (__sentinel_size<_Tp>)
355 return noexcept(_End{}(std::declval<_Tp&>())
356 - _Begin{}(std::declval<_Tp&>()));
360 template<
typename _Tp>
361 requires is_bounded_array_v<remove_reference_t<_Tp>>
362 || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
363 [[nodiscard, __gnu__::__always_inline__]]
365 operator()(_Tp&& __t)
const noexcept(_S_noexcept<_Tp&>())
367 if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
369 else if constexpr (__member_size<_Tp>)
371 else if constexpr (__adl_size<_Tp>)
373 else if constexpr (__sentinel_size<_Tp>)
374 return __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t));
382 template<
typename _Tp>
383 requires requires (_Tp& __t) { _Size{}(__t); }
384 [[nodiscard, __gnu__::__always_inline__]]
386 operator()(_Tp&& __t)
const noexcept(noexcept(_Size{}(__t)))
388 auto __size = _Size{}(__t);
389 using __size_type = decltype(__size);
391 if constexpr (integral<__size_type>)
394 if constexpr (__int_traits<__size_type>::__digits
395 < __int_traits<ptrdiff_t>::__digits)
396 return static_cast<ptrdiff_t
>(__size);
398 return static_cast<make_signed_t<__size_type>
>(__size);
401 return __detail::__max_diff_type(__size);
405 template<
typename _Tp>
406 concept __member_empty = requires(_Tp& __t) { bool(__t.empty()); };
408 template<
typename _Tp>
409 concept __size0_empty = requires(_Tp& __t) { _Size{}(__t) == 0; };
411 template<
typename _Tp>
412 concept __eq_iter_empty = requires(_Tp& __t)
414 requires (!is_unbounded_array_v<remove_reference_t<_Tp>>);
416 { _Begin{}(__t) } -> forward_iterator;
418 bool(_Begin{}(__t) == _End{}(__t));
424 template<
typename _Tp>
425 static consteval
bool
428 if constexpr (__member_empty<_Tp>)
429 return noexcept(
bool(std::declval<_Tp&>().
empty()));
430 else if constexpr (__size0_empty<_Tp>)
431 return noexcept(_Size{}(std::declval<_Tp&>()) == 0);
433 return noexcept(
bool(_Begin{}(std::declval<_Tp&>())
434 == _End{}(std::declval<_Tp&>())));
438 template<
typename _Tp>
439 requires __member_empty<_Tp> || __size0_empty<_Tp>
440 || __eq_iter_empty<_Tp>
441 [[nodiscard, __gnu__::__always_inline__]]
443 operator()(_Tp&& __t)
const noexcept(_S_noexcept<_Tp&>())
445 if constexpr (__member_empty<_Tp>)
446 return bool(__t.empty());
447 else if constexpr (__size0_empty<_Tp>)
448 return _Size{}(__t) == 0;
450 return bool(_Begin{}(__t) == _End{}(__t));
454 template<
typename _Tp>
455 concept __pointer_to_object = is_pointer_v<_Tp>
456 && is_object_v<remove_pointer_t<_Tp>>;
458 template<
typename _Tp>
459 concept __member_data = requires(_Tp& __t)
461 { _GLIBCXX_AUTO_CAST(__t.data()) } -> __pointer_to_object;
464 template<
typename _Tp>
465 concept __begin_data = contiguous_iterator<__range_iter_t<_Tp>>;
470 template<
typename _Tp>
471 static consteval
bool
474 if constexpr (__member_data<_Tp>)
475 return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().
data()));
477 return noexcept(_Begin{}(std::declval<_Tp&>()));
481 template<__maybe_borrowed_range _Tp>
482 requires __member_data<_Tp> || __begin_data<_Tp>
483 [[nodiscard, __gnu__::__always_inline__]]
485 operator()(_Tp&& __t)
const noexcept(_S_noexcept<_Tp>())
487 if constexpr (__member_data<_Tp>)
496 inline namespace _Cpo
498 inline constexpr ranges::__access::_Begin
begin{};
499 inline constexpr ranges::__access::_End
end{};
500 inline constexpr ranges::__access::_RBegin
rbegin{};
501 inline constexpr ranges::__access::_REnd
rend{};
502 inline constexpr ranges::__access::_Size
size{};
503 inline constexpr ranges::__access::_SSize ssize{};
504 inline constexpr ranges::__access::_Empty
empty{};
505 inline constexpr ranges::__access::_Data
data{};
509 template<
typename _Tp>
517 template<
typename _Tp>
518 concept borrowed_range
519 = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>;
521 template<
typename _Tp>
522 using iterator_t = std::__detail::__range_iter_t<_Tp>;
524 template<range _Range>
525 using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
527 #if __glibcxx_ranges_as_const // >= C++23
530 template<range _Range>
531 using range_const_reference_t = iter_const_reference_t<iterator_t<_Range>>;
534 template<range _Range>
535 using range_difference_t = iter_difference_t<iterator_t<_Range>>;
537 template<range _Range>
538 using range_value_t = iter_value_t<iterator_t<_Range>>;
540 template<range _Range>
541 using range_reference_t = iter_reference_t<iterator_t<_Range>>;
543 template<range _Range>
544 using range_rvalue_reference_t
549 template<range _Range>
550 using range_common_reference_t
551 = iter_common_reference_t<iterator_t<_Range>>;
554 template<
typename _Tp>
556 && requires(_Tp& __t) { ranges::size(__t); };
558 template<sized_range _Range>
559 using range_size_t = decltype(ranges::size(std::declval<_Range&>()));
561 template<
typename _Derived>
562 requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
567 template<
typename _Tp,
typename _Up>
569 void __is_derived_from_view_interface_fn(const _Tp&,
574 template<typename _Tp>
575 concept __is_derived_from_view_interface
576 = requires (_Tp __t) { __is_derived_from_view_interface_fn(__t, __t); };
583 template<
typename _Tp>
585 || __detail::__is_derived_from_view_interface<_Tp>;
588 template<
typename _Tp>
590 = range<_Tp> && movable<_Tp> && enable_view<_Tp>;
595 template<
typename _Range,
typename _Tp>
597 = range<_Range> && output_iterator<iterator_t<_Range>, _Tp>;
600 template<
typename _Tp>
601 concept
input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
604 template<
typename _Tp>
606 = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
609 template<
typename _Tp>
611 = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
614 template<
typename _Tp>
616 = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
619 template<
typename _Tp>
621 = random_access_range<_Tp> && contiguous_iterator<iterator_t<_Tp>>
622 && requires(_Tp& __t)
624 { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
628 template<
typename _Tp>
630 = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
632 #if __glibcxx_ranges_as_const // >= C++23
633 template<
typename _Tp>
634 concept constant_range
635 = input_range<_Tp> && std::__detail::__constant_iterator<iterator_t<_Tp>>;
640 #if __glibcxx_ranges_as_const // >= C++23
641 template<input_range _Range>
642 [[__gnu__::__always_inline__]]
644 __possibly_const_range(_Range& __r) noexcept
648 if constexpr (input_range<const _Range>)
649 return const_cast<const _Range&
>(__r);
655 template<
typename _To,
typename _Tp>
656 [[__gnu__::__always_inline__]]
657 constexpr decltype(
auto)
658 __as_const(_Tp& __t) noexcept
660 static_assert(std::is_same_v<_To&, _Tp&>);
662 if constexpr (is_lvalue_reference_v<_To>)
663 return const_cast<const _Tp&
>(__t);
665 return static_cast<const _Tp&&
>(__t);
671 #if __glibcxx_ranges_as_const // >= C++23
672 template<__maybe_borrowed_range _Tp>
675 operator()(_Tp&& __t)
const
676 noexcept(noexcept(std::make_const_iterator
677 (ranges::begin(__access::__possibly_const_range(__t)))))
678 requires requires { std::make_const_iterator
679 (ranges::begin(__access::__possibly_const_range(__t))); }
681 auto& __r = __access::__possibly_const_range(__t);
682 return const_iterator<decltype(ranges::begin(__r))>(ranges::begin(__r));
685 template<
typename _Tp>
688 operator()(_Tp&& __e)
const
689 noexcept(noexcept(_Begin{}(__access::__as_const<_Tp>(__e))))
690 requires requires { _Begin{}(__access::__as_const<_Tp>(__e)); }
692 return _Begin{}(__access::__as_const<_Tp>(__e));
699 #if __glibcxx_ranges_as_const // >= C++23
700 template<__maybe_borrowed_range _Tp>
703 operator()(_Tp&& __t)
const
704 noexcept(noexcept(std::make_const_sentinel
705 (ranges::end(__access::__possibly_const_range(__t)))))
706 requires requires { std::make_const_sentinel
707 (ranges::end(__access::__possibly_const_range(__t))); }
709 auto& __r = __access::__possibly_const_range(__t);
710 return const_sentinel<decltype(ranges::end(__r))>(ranges::end(__r));
713 template<
typename _Tp>
716 operator()(_Tp&& __e)
const
717 noexcept(noexcept(_End{}(__access::__as_const<_Tp>(__e))))
718 requires requires { _End{}(__access::__as_const<_Tp>(__e)); }
720 return _End{}(__access::__as_const<_Tp>(__e));
727 #if __glibcxx_ranges_as_const // >= C++23
728 template<__maybe_borrowed_range _Tp>
731 operator()(_Tp&& __t)
const
732 noexcept(noexcept(std::make_const_iterator
733 (ranges::rbegin(__access::__possibly_const_range(__t)))))
734 requires requires { std::make_const_iterator
735 (ranges::rbegin(__access::__possibly_const_range(__t))); }
737 auto& __r = __access::__possibly_const_range(__t);
738 return const_iterator<decltype(ranges::rbegin(__r))>(ranges::rbegin(__r));
741 template<
typename _Tp>
744 operator()(_Tp&& __e)
const
745 noexcept(noexcept(_RBegin{}(__access::__as_const<_Tp>(__e))))
746 requires requires { _RBegin{}(__access::__as_const<_Tp>(__e)); }
748 return _RBegin{}(__access::__as_const<_Tp>(__e));
755 #if __glibcxx_ranges_as_const // >= C++23
756 template<__maybe_borrowed_range _Tp>
759 operator()(_Tp&& __t)
const
760 noexcept(noexcept(std::make_const_sentinel
761 (ranges::rend(__access::__possibly_const_range(__t)))))
762 requires requires { std::make_const_sentinel
763 (ranges::rend(__access::__possibly_const_range(__t))); }
765 auto& __r = __access::__possibly_const_range(__t);
766 return const_sentinel<decltype(ranges::rend(__r))>(ranges::rend(__r));
769 template<
typename _Tp>
772 operator()(_Tp&& __e)
const
773 noexcept(noexcept(_REnd{}(__access::__as_const<_Tp>(__e))))
774 requires requires { _REnd{}(__access::__as_const<_Tp>(__e)); }
776 return _REnd{}(__access::__as_const<_Tp>(__e));
783 #if __glibcxx_ranges_as_const // >= C++23
784 template<__maybe_borrowed_range _Tp>
786 constexpr
const auto*
787 operator()(_Tp&& __t)
const
788 noexcept(noexcept(ranges::data(__access::__possibly_const_range(__t))))
789 requires requires { ranges::data(__access::__possibly_const_range(__t)); }
790 {
return ranges::data(__access::__possibly_const_range(__t)); }
792 template<
typename _Tp>
795 operator()(_Tp&& __e)
const
796 noexcept(noexcept(_Data{}(__access::__as_const<_Tp>(__e))))
797 requires requires { _Data{}(__access::__as_const<_Tp>(__e)); }
799 return _Data{}(__access::__as_const<_Tp>(__e));
805 inline namespace _Cpo
807 inline constexpr ranges::__access::_CBegin
cbegin{};
808 inline constexpr ranges::__access::_CEnd
cend{};
809 inline constexpr ranges::__access::_CRBegin
crbegin{};
810 inline constexpr ranges::__access::_CREnd
crend{};
811 inline constexpr ranges::__access::_CData cdata{};
814 #if __glibcxx_ranges_as_const // >= C++23
817 template<range _Range>
818 using const_iterator_t = decltype(ranges::cbegin(std::declval<_Range&>()));
820 template<range _Range>
821 using const_sentinel_t = decltype(ranges::cend(std::declval<_Range&>()));
826 template<
typename _Tp>
827 inline constexpr
bool __is_initializer_list =
false;
829 template<
typename _Tp>
830 inline constexpr
bool __is_initializer_list<initializer_list<_Tp>> =
true;
834 template<
typename _Tp>
836 && ((view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>)
837 || (!view<remove_cvref_t<_Tp>>
838 && (is_lvalue_reference_v<_Tp>
840 && !__detail::__is_initializer_list<remove_cvref_t<_Tp>>))));
844 struct __advance_fn final
846 template<input_or_output_iterator _It>
848 operator()(_It& __it, iter_difference_t<_It> __n)
const
850 if constexpr (random_access_iterator<_It>)
852 else if constexpr (bidirectional_iterator<_It>)
874 __glibcxx_assert(__n >= 0);
880 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
882 operator()(_It& __it, _Sent __bound)
const
884 if constexpr (assignable_from<_It&, _Sent>)
886 else if constexpr (sized_sentinel_for<_Sent, _It>)
887 (*this)(__it, __bound - __it);
890 while (__it != __bound)
895 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
896 constexpr iter_difference_t<_It>
897 operator()(_It& __it, iter_difference_t<_It> __n, _Sent __bound)
const
899 if constexpr (sized_sentinel_for<_Sent, _It>)
901 const iter_difference_t<_It> __diff = __bound - __it;
906 if constexpr (assignable_from<_It&, _Sent>)
908 else if constexpr (random_access_iterator<_It>)
909 __it += iter_difference_t<_It>(0);
912 else if (__diff > 0 ? __n >= __diff : __n <= __diff)
914 (*this)(__it, __bound);
917 else if (__n != 0) [[likely]]
920 __glibcxx_assert((__n < 0) == (__diff < 0));
928 if constexpr (random_access_iterator<_It>)
929 __it += iter_difference_t<_It>(0);
933 else if (__n == 0 || __it == __bound)
937 iter_difference_t<_It> __m = 0;
943 while (__m != __n && __it != __bound);
946 else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
948 iter_difference_t<_It> __m = 0;
954 while (__m != __n && __it != __bound);
960 __glibcxx_assert(__n >= 0);
968 inline constexpr __advance_fn
advance{};
970 struct __distance_fn final
974 template<
typename _It, sentinel_for<_It> _Sent>
975 requires (!sized_sentinel_for<_Sent, _It>)
976 constexpr iter_difference_t<_It>
977 operator()[[nodiscard]](_It __first, _Sent __last)
const
979 iter_difference_t<_It> __n = 0;
980 while (__first != __last)
988 template<
typename _It, sized_sentinel_for<decay_t<_It>> _Sent>
989 [[nodiscard, __gnu__::__always_inline__]]
990 constexpr iter_difference_t<decay_t<_It>>
991 operator()(_It&& __first, _Sent __last)
const
992 {
return __last -
static_cast<const decay_t<_It>&
>(__first); }
994 template<range _Range>
995 [[nodiscard, __gnu__::__always_inline__]]
996 constexpr range_difference_t<_Range>
997 operator()(_Range&& __r)
const
999 if constexpr (sized_range<_Range>)
1000 return static_cast<range_difference_t<_Range>
>(ranges::size(__r));
1002 return (*
this)(ranges::begin(__r), ranges::end(__r));
1008 inline constexpr __distance_fn
distance{};
1010 struct __next_fn final
1012 template<input_or_output_iterator _It>
1013 [[nodiscard, __gnu__::__always_inline__]]
1015 operator()(_It __x)
const
1021 template<input_or_output_iterator _It>
1022 [[nodiscard, __gnu__::__always_inline__]]
1024 operator()(_It __x, iter_difference_t<_It> __n)
const
1026 ranges::advance(__x, __n);
1030 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
1031 [[nodiscard, __gnu__::__always_inline__]]
1033 operator()(_It __x, _Sent __bound)
const
1035 ranges::advance(__x, __bound);
1039 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
1040 [[nodiscard, __gnu__::__always_inline__]]
1042 operator()(_It __x, iter_difference_t<_It> __n, _Sent __bound)
const
1044 ranges::advance(__x, __n, __bound);
1051 inline constexpr __next_fn next{};
1053 struct __prev_fn final
1055 template<b
idirectional_iterator _It>
1056 [[nodiscard, __gnu__::__always_inline__]]
1058 operator()(_It __x)
const
1064 template<b
idirectional_iterator _It>
1065 [[nodiscard, __gnu__::__always_inline__]]
1067 operator()(_It __x, iter_difference_t<_It> __n)
const
1069 ranges::advance(__x, -__n);
1073 template<b
idirectional_iterator _It>
1074 [[nodiscard, __gnu__::__always_inline__]]
1076 operator()(_It __x, iter_difference_t<_It> __n, _It __bound)
const
1078 ranges::advance(__x, -__n, __bound);
1085 inline constexpr __prev_fn prev{};
1090 constexpr
dangling() noexcept =
default;
1091 template<
typename... _Args>
1092 constexpr
dangling(_Args&&...) noexcept { }
1095 template<range _Range>
1096 using borrowed_iterator_t = __conditional_t<borrowed_range<_Range>,
1101 #if __glibcxx_ranges_to_container // C++ >= 23
1102 struct from_range_t {
explicit from_range_t() =
default; };
1103 inline constexpr from_range_t from_range{};
1106 #if __glibcxx_containers_ranges // C++ >= 23
1108 template<
typename _T1,
typename _T2>
1113 template<
typename _Rg,
typename _Tp>
1114 concept __container_compatible_range
1115 = ranges::input_range<_Rg>
1116 && convertible_to<ranges::range_reference_t<_Rg>, _Tp>;
1120 template<ranges::input_range _Range>
1121 using __range_key_type
1122 = remove_cvref_t<tuple_element_t<0, ranges::range_value_t<_Range>>>;
1124 template<ranges::input_range _Range>
1125 using __range_mapped_type
1126 = remove_cvref_t<tuple_element_t<1, ranges::range_value_t<_Range>>>;
1129 template<ranges::input_range _Range>
1130 using __range_to_alloc_type
1131 = pair<const __range_key_type<_Range>, __range_mapped_type<_Range>>;
1136 _GLIBCXX_END_NAMESPACE_VERSION
1138 #endif // library concepts
1139 #pragma GCC diagnostic pop
1141 #endif // _GLIBCXX_RANGES_BASE_H