30#ifndef _GLIBCXX_RANGES_BASE_H
31#define _GLIBCXX_RANGES_BASE_H 1
33#pragma GCC system_header
35#if __cplusplus > 201703L
41#ifdef __cpp_lib_concepts
42namespace std _GLIBCXX_VISIBILITY(default)
44_GLIBCXX_BEGIN_NAMESPACE_VERSION
48 inline constexpr bool disable_sized_range =
false;
50 template<
typename _Tp>
51 inline constexpr bool enable_borrowed_range =
false;
55 constexpr __max_size_type
56 __to_unsigned_like(__max_size_type __t)
noexcept
59 constexpr __max_size_type
60 __to_unsigned_like(__max_diff_type __t)
noexcept
61 {
return __max_size_type(__t); }
63 template<
integral _Tp>
65 __to_unsigned_like(_Tp __t)
noexcept
66 {
return static_cast<make_unsigned_t<_Tp>
>(__t); }
68#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
69 constexpr unsigned __int128
70 __to_unsigned_like(__int128 __t)
noexcept
73 constexpr unsigned __int128
74 __to_unsigned_like(
unsigned __int128 __t)
noexcept
78 template<
typename _Tp>
79 using __make_unsigned_like_t
80 =
decltype(__detail::__to_unsigned_like(std::declval<_Tp>()));
83 template<
typename _Tp>
84 concept __maybe_borrowed_range
85 = is_lvalue_reference_v<_Tp>
86 || enable_borrowed_range<remove_cvref_t<_Tp>>;
90 namespace __cust_access
92 using std::ranges::__detail::__maybe_borrowed_range;
93 using std::__detail::__range_iter_t;
98 template<
typename _Tp>
102 if constexpr (is_array_v<remove_reference_t<_Tp>>)
104 else if constexpr (__member_begin<_Tp>)
105 return noexcept(__decay_copy(std::declval<_Tp&>().begin()));
107 return noexcept(__decay_copy(
begin(std::declval<_Tp&>())));
111 template<__maybe_borrowed_range _Tp>
112 requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
115 operator()[[nodiscard]](_Tp&& __t)
const noexcept(_S_noexcept<_Tp&>())
117 if constexpr (is_array_v<remove_reference_t<_Tp>>)
119 static_assert(is_lvalue_reference_v<_Tp>);
122 else if constexpr (__member_begin<_Tp>)
129 template<
typename _Tp>
130 concept __member_end =
requires(_Tp& __t)
132 { __decay_copy(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>;
136 void end(
auto&) =
delete;
137 void end(
const auto&) =
delete;
139 template<
typename _Tp>
140 concept __adl_end = __class_or_enum<remove_reference_t<_Tp>>
141 &&
requires(_Tp& __t)
143 { __decay_copy(
end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>;
149 template<
typename _Tp>
150 static constexpr bool
153 if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
155 else if constexpr (__member_end<_Tp>)
156 return noexcept(__decay_copy(std::declval<_Tp&>().end()));
158 return noexcept(__decay_copy(
end(std::declval<_Tp&>())));
162 template<__maybe_borrowed_range _Tp>
163 requires is_bounded_array_v<remove_reference_t<_Tp>>
164 || __member_end<_Tp> || __adl_end<_Tp>
166 operator()[[nodiscard]](_Tp&& __t)
const noexcept(_S_noexcept<_Tp&>())
168 if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
170 static_assert(is_lvalue_reference_v<_Tp>);
171 return __t + extent_v<remove_reference_t<_Tp>>;
173 else if constexpr (__member_end<_Tp>)
181 template<
typename _To,
typename _Tp>
182 constexpr decltype(
auto)
183 __as_const(_Tp& __t)
noexcept
185 static_assert(std::is_same_v<_To&, _Tp&>);
187 if constexpr (is_lvalue_reference_v<_To>)
188 return const_cast<const _Tp&
>(__t);
190 return static_cast<const _Tp&&
>(__t);
195 template<
typename _Tp>
198 operator()(_Tp&& __e)
const
199 noexcept(
noexcept(_Begin{}(__cust_access::__as_const<_Tp>(__e))))
200 requires requires { _Begin{}(__cust_access::__as_const<_Tp>(__e)); }
202 return _Begin{}(__cust_access::__as_const<_Tp>(__e));
208 template<
typename _Tp>
211 operator()(_Tp&& __e)
const
212 noexcept(
noexcept(_End{}(__cust_access::__as_const<_Tp>(__e))))
213 requires requires { _End{}(__cust_access::__as_const<_Tp>(__e)); }
215 return _End{}(__cust_access::__as_const<_Tp>(__e));
219 template<
typename _Tp>
220 concept __member_rbegin =
requires(_Tp& __t)
222 { __decay_copy(__t.rbegin()) } -> input_or_output_iterator;
225 void rbegin(
auto&) =
delete;
226 void rbegin(
const auto&) =
delete;
228 template<
typename _Tp>
229 concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>>
230 &&
requires(_Tp& __t)
232 { __decay_copy(
rbegin(__t)) } -> input_or_output_iterator;
235 template<
typename _Tp>
236 concept __reversable =
requires(_Tp& __t)
238 { _Begin{}(__t) } -> bidirectional_iterator;
239 { _End{}(__t) } -> same_as<
decltype(_Begin{}(__t))>;
245 template<
typename _Tp>
246 static constexpr bool
249 if constexpr (__member_rbegin<_Tp>)
250 return noexcept(__decay_copy(std::declval<_Tp&>().
rbegin()));
251 else if constexpr (__adl_rbegin<_Tp>)
252 return noexcept(__decay_copy(
rbegin(std::declval<_Tp&>())));
255 if constexpr (
noexcept(_End{}(std::declval<_Tp&>())))
257 using _It =
decltype(_End{}(std::declval<_Tp&>()));
259 return is_nothrow_copy_constructible_v<_It>;
267 template<__maybe_borrowed_range _Tp>
268 requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
270 operator()[[nodiscard]](_Tp&& __t)
const
271 noexcept(_S_noexcept<_Tp&>())
273 if constexpr (__member_rbegin<_Tp>)
275 else if constexpr (__adl_rbegin<_Tp>)
282 template<
typename _Tp>
283 concept __member_rend =
requires(_Tp& __t)
285 { __decay_copy(__t.rend()) }
286 -> sentinel_for<
decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
289 void rend(
auto&) =
delete;
290 void rend(
const auto&) =
delete;
292 template<
typename _Tp>
293 concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>>
294 &&
requires(_Tp& __t)
296 { __decay_copy(
rend(__t)) }
297 -> sentinel_for<
decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
303 template<
typename _Tp>
304 static constexpr bool
307 if constexpr (__member_rend<_Tp>)
308 return noexcept(__decay_copy(std::declval<_Tp&>().
rend()));
309 else if constexpr (__adl_rend<_Tp>)
310 return noexcept(__decay_copy(
rend(std::declval<_Tp&>())));
313 if constexpr (
noexcept(_Begin{}(std::declval<_Tp&>())))
315 using _It =
decltype(_Begin{}(std::declval<_Tp&>()));
317 return is_nothrow_copy_constructible_v<_It>;
325 template<__maybe_borrowed_range _Tp>
326 requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
328 operator()[[nodiscard]](_Tp&& __t)
const
329 noexcept(_S_noexcept<_Tp&>())
331 if constexpr (__member_rend<_Tp>)
333 else if constexpr (__adl_rend<_Tp>)
342 template<
typename _Tp>
345 operator()(_Tp&& __e)
const
346 noexcept(
noexcept(_RBegin{}(__cust_access::__as_const<_Tp>(__e))))
347 requires requires { _RBegin{}(__cust_access::__as_const<_Tp>(__e)); }
349 return _RBegin{}(__cust_access::__as_const<_Tp>(__e));
355 template<
typename _Tp>
358 operator()(_Tp&& __e)
const
359 noexcept(
noexcept(_REnd{}(__cust_access::__as_const<_Tp>(__e))))
360 requires requires { _REnd{}(__cust_access::__as_const<_Tp>(__e)); }
362 return _REnd{}(__cust_access::__as_const<_Tp>(__e));
366 template<
typename _Tp>
367 concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
368 &&
requires(_Tp& __t)
370 { __decay_copy(__t.size()) } -> __detail::__is_integer_like;
373 void size(
auto&) =
delete;
374 void size(
const auto&) =
delete;
376 template<
typename _Tp>
377 concept __adl_size = __class_or_enum<remove_reference_t<_Tp>>
378 && !disable_sized_range<remove_cvref_t<_Tp>>
379 &&
requires(_Tp& __t)
381 { __decay_copy(
size(__t)) } -> __detail::__is_integer_like;
384 template<
typename _Tp>
385 concept __sentinel_size =
requires(_Tp& __t)
387 requires (!is_unbounded_array_v<remove_reference_t<_Tp>>);
389 { _Begin{}(__t) } -> forward_iterator;
391 { _End{}(__t) } -> sized_sentinel_for<
decltype(_Begin{}(__t))>;
393 __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t));
399 template<
typename _Tp>
400 static constexpr bool
403 if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
405 else if constexpr (__member_size<_Tp>)
406 return noexcept(__decay_copy(std::declval<_Tp&>().size()));
407 else if constexpr (__adl_size<_Tp>)
408 return noexcept(__decay_copy(
size(std::declval<_Tp&>())));
409 else if constexpr (__sentinel_size<_Tp>)
410 return noexcept(_End{}(std::declval<_Tp&>())
411 - _Begin{}(std::declval<_Tp&>()));
415 template<
typename _Tp>
416 requires is_bounded_array_v<remove_reference_t<_Tp>>
417 || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
419 operator()[[nodiscard]](_Tp&& __t)
const noexcept(_S_noexcept<_Tp&>())
421 if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
422 return extent_v<remove_reference_t<_Tp>>;
423 else if constexpr (__member_size<_Tp>)
425 else if constexpr (__adl_size<_Tp>)
427 else if constexpr (__sentinel_size<_Tp>)
428 return __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t));
436 template<
typename _Tp>
437 requires requires (_Tp& __t) { _Size{}(__t); }
439 operator()[[nodiscard]](_Tp&& __t)
const noexcept(
noexcept(_Size{}(__t)))
441 auto __size = _Size{}(__t);
442 using __size_type =
decltype(__size);
444 if constexpr (integral<__size_type>)
447 if constexpr (__int_traits<__size_type>::__digits
448 < __int_traits<ptrdiff_t>::__digits)
449 return static_cast<ptrdiff_t
>(__size);
451 return static_cast<make_signed_t<__size_type>
>(__size);
453#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
455 else if constexpr (__detail::__is_int128<__size_type>)
456 return static_cast<__int128
>(__size);
459 return __detail::__max_diff_type(__size);
463 template<
typename _Tp>
464 concept __member_empty =
requires(_Tp& __t) { bool(__t.empty()); };
466 template<
typename _Tp>
467 concept __size0_empty =
requires(_Tp& __t) { _Size{}(__t) == 0; };
469 template<
typename _Tp>
470 concept __eq_iter_empty =
requires(_Tp& __t)
472 requires (!is_unbounded_array_v<remove_reference_t<_Tp>>);
474 { _Begin{}(__t) } -> forward_iterator;
476 bool(_Begin{}(__t) == _End{}(__t));
482 template<
typename _Tp>
483 static constexpr bool
486 if constexpr (__member_empty<_Tp>)
487 return noexcept(
bool(std::declval<_Tp&>().
empty()));
488 else if constexpr (__size0_empty<_Tp>)
489 return noexcept(_Size{}(std::declval<_Tp&>()) == 0);
491 return noexcept(bool(_Begin{}(std::declval<_Tp&>())
492 == _End{}(std::declval<_Tp&>())));
496 template<
typename _Tp>
497 requires __member_empty<_Tp> || __size0_empty<_Tp>
498 || __eq_iter_empty<_Tp>
500 operator()[[nodiscard]](_Tp&& __t)
const noexcept(_S_noexcept<_Tp&>())
502 if constexpr (__member_empty<_Tp>)
503 return bool(__t.empty());
504 else if constexpr (__size0_empty<_Tp>)
505 return _Size{}(__t) == 0;
507 return bool(_Begin{}(__t) == _End{}(__t));
511 template<
typename _Tp>
512 concept __pointer_to_object = is_pointer_v<_Tp>
513 && is_object_v<remove_pointer_t<_Tp>>;
515 template<
typename _Tp>
516 concept __member_data =
requires(_Tp& __t)
518 { __decay_copy(__t.data()) } -> __pointer_to_object;
521 template<
typename _Tp>
522 concept __begin_data = contiguous_iterator<__range_iter_t<_Tp>>;
527 template<
typename _Tp>
528 static constexpr bool
531 if constexpr (__member_data<_Tp>)
532 return noexcept(__decay_copy(std::declval<_Tp&>().
data()));
534 return noexcept(_Begin{}(std::declval<_Tp&>()));
538 template<__maybe_borrowed_range _Tp>
539 requires __member_data<_Tp> || __begin_data<_Tp>
541 operator()[[nodiscard]](_Tp&& __t)
const noexcept(_S_noexcept<_Tp>())
543 if constexpr (__member_data<_Tp>)
552 template<
typename _Tp>
555 operator()(_Tp&& __e)
const
556 noexcept(
noexcept(_Data{}(__cust_access::__as_const<_Tp>(__e))))
557 requires requires { _Data{}(__cust_access::__as_const<_Tp>(__e)); }
559 return _Data{}(__cust_access::__as_const<_Tp>(__e));
565 inline namespace __cust
567 inline constexpr __cust_access::_Begin
begin{};
568 inline constexpr __cust_access::_End
end{};
569 inline constexpr __cust_access::_CBegin
cbegin{};
570 inline constexpr __cust_access::_CEnd
cend{};
571 inline constexpr __cust_access::_RBegin
rbegin{};
572 inline constexpr __cust_access::_REnd
rend{};
573 inline constexpr __cust_access::_CRBegin
crbegin{};
574 inline constexpr __cust_access::_CREnd
crend{};
575 inline constexpr __cust_access::_Size
size{};
576 inline constexpr __cust_access::_SSize ssize{};
577 inline constexpr __cust_access::_Empty
empty{};
578 inline constexpr __cust_access::_Data
data{};
579 inline constexpr __cust_access::_CData cdata{};
583 template<
typename _Tp>
591 template<
typename _Tp>
593 =
range<_Tp> && __detail::__maybe_borrowed_range<_Tp>;
595 template<
typename _Tp>
596 using iterator_t = std::__detail::__range_iter_t<_Tp>;
598 template<range _Range>
599 using sentinel_t =
decltype(ranges::end(std::declval<_Range&>()));
601 template<range _Range>
602 using range_difference_t = iter_difference_t<iterator_t<_Range>>;
604 template<range _Range>
605 using range_value_t = iter_value_t<iterator_t<_Range>>;
607 template<range _Range>
608 using range_reference_t = iter_reference_t<iterator_t<_Range>>;
610 template<range _Range>
611 using range_rvalue_reference_t
612 = iter_rvalue_reference_t<iterator_t<_Range>>;
615 template<
typename _Tp>
617 &&
requires(_Tp& __t) { ranges::size(__t); };
619 template<sized_range _Range>
620 using range_size_t =
decltype(ranges::size(std::declval<_Range&>()));
622 template<
typename _Derived>
628 template<
typename _Tp,
typename _Up>
630 void __is_derived_from_view_interface_fn(
const _Tp&,
635 template<
typename _Tp>
636 concept __is_derived_from_view_interface
637 =
requires (_Tp __t) { __is_derived_from_view_interface_fn(__t, __t); };
644 template<
typename _Tp>
646 || __detail::__is_derived_from_view_interface<_Tp>;
649 template<
typename _Tp>
651 =
range<_Tp> && movable<_Tp> && enable_view<_Tp>;
656 template<
typename _Range,
typename _Tp>
661 template<
typename _Tp>
665 template<
typename _Tp>
670 template<
typename _Tp>
675 template<
typename _Tp>
680 template<
typename _Tp>
683 &&
requires(_Tp& __t)
689 template<
typename _Tp>
695 template<
typename _Tp>
696 inline constexpr bool __is_initializer_list =
false;
698 template<
typename _Tp>
699 inline constexpr bool __is_initializer_list<initializer_list<_Tp>> =
true;
703 template<
typename _Tp>
706 || (!
view<remove_cvref_t<_Tp>>
707 && (is_lvalue_reference_v<_Tp>
708 || (movable<remove_reference_t<_Tp>>
709 && !__detail::__is_initializer_list<remove_cvref_t<_Tp>>))));
713 struct __advance_fn final
715 template<input_or_output_iterator _It>
717 operator()(_It& __it, iter_difference_t<_It> __n)
const
719 if constexpr (random_access_iterator<_It>)
721 else if constexpr (bidirectional_iterator<_It>)
743 __glibcxx_assert(__n >= 0);
749 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
751 operator()(_It& __it, _Sent __bound)
const
753 if constexpr (assignable_from<_It&, _Sent>)
755 else if constexpr (sized_sentinel_for<_Sent, _It>)
756 (*
this)(__it, __bound - __it);
759 while (__it != __bound)
764 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
765 constexpr iter_difference_t<_It>
766 operator()(_It& __it, iter_difference_t<_It> __n, _Sent __bound)
const
768 if constexpr (sized_sentinel_for<_Sent, _It>)
770 const auto __diff = __bound - __it;
774 else if (__diff > 0 ? __n >= __diff : __n <= __diff)
776 (*this)(__it, __bound);
779 else if (__n != 0) [[likely]]
782 __glibcxx_assert((__n < 0) == (__diff < 0));
790 else if (__it == __bound || __n == 0)
794 iter_difference_t<_It> __m = 0;
800 while (__m != __n && __it != __bound);
803 else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
805 iter_difference_t<_It> __m = 0;
811 while (__m != __n && __it != __bound);
817 __glibcxx_assert(__n >= 0);
825 inline constexpr __advance_fn
advance{};
827 struct __distance_fn final
829 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
830 requires (!sized_sentinel_for<_Sent, _It>)
831 constexpr iter_difference_t<_It>
832 operator()[[nodiscard]](_It __first, _Sent __last)
const
834 iter_difference_t<_It> __n = 0;
835 while (__first != __last)
843 template<input_or_output_iterator _It, sized_sentinel_for<_It> _Sent>
845 constexpr iter_difference_t<_It>
846 operator()(
const _It& __first,
const _Sent& __last)
const
848 return __last - __first;
851 template<range _Range>
853 constexpr range_difference_t<_Range>
854 operator()(_Range&& __r)
const
856 if constexpr (sized_range<_Range>)
857 return static_cast<range_difference_t<_Range>
>(ranges::size(__r));
859 return (*
this)(ranges::begin(__r), ranges::end(__r));
865 inline constexpr __distance_fn
distance{};
867 struct __next_fn final
869 template<input_or_output_iterator _It>
872 operator()(_It __x)
const
878 template<input_or_output_iterator _It>
881 operator()(_It __x, iter_difference_t<_It> __n)
const
883 ranges::advance(__x, __n);
887 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
890 operator()(_It __x, _Sent __bound)
const
892 ranges::advance(__x, __bound);
896 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
899 operator()(_It __x, iter_difference_t<_It> __n, _Sent __bound)
const
901 ranges::advance(__x, __n, __bound);
908 inline constexpr __next_fn next{};
910 struct __prev_fn final
912 template<b
idirectional_iterator _It>
915 operator()(_It __x)
const
921 template<b
idirectional_iterator _It>
924 operator()(_It __x, iter_difference_t<_It> __n)
const
926 ranges::advance(__x, -__n);
930 template<b
idirectional_iterator _It>
933 operator()(_It __x, iter_difference_t<_It> __n, _It __bound)
const
935 ranges::advance(__x, -__n, __bound);
942 inline constexpr __prev_fn prev{};
947 constexpr dangling()
noexcept =
default;
948 template<
typename... _Args>
949 constexpr dangling(_Args&&...)
noexcept { }
952 template<range _Range>
953 using borrowed_iterator_t = __conditional_t<borrowed_range<_Range>,
958_GLIBCXX_END_NAMESPACE_VERSION
constexpr bool enable_view
[range.view] The ranges::enable_view boolean.
constexpr _Tp * to_address(_Tp *__ptr) noexcept
Obtain address referenced by a pointer to an object.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
_Tp * end(valarray< _Tp > &__va) noexcept
Return an iterator pointing to one past the last element of the valarray.
_Tp * begin(valarray< _Tp > &__va) noexcept
Return an iterator pointing to the first element of the valarray.
constexpr reverse_iterator< _Iterator > make_reverse_iterator(_Iterator __i)
Generator function for reverse_iterator.
ISO C++ entities toplevel namespace is std.
constexpr auto crend(const _Container &__cont) -> decltype(std::rend(__cont))
Return a reverse iterator pointing one past the first element of the const container.
constexpr auto rend(_Container &__cont) -> decltype(__cont.rend())
Return a reverse iterator pointing one past the first element of the container.
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
constexpr auto cend(const _Container &__cont) noexcept(noexcept(std::end(__cont))) -> decltype(std::end(__cont))
Return an iterator pointing to one past the last element of the const container.
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
Return whether a container is empty.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
constexpr void advance(_InputIterator &__i, _Distance __n)
A generalization of pointer arithmetic.
constexpr auto rbegin(_Container &__cont) -> decltype(__cont.rbegin())
Return a reverse iterator pointing to the last element of the container.
constexpr auto crbegin(const _Container &__cont) -> decltype(std::rbegin(__cont))
Return a reverse iterator pointing to the last element of the const container.
constexpr auto data(_Container &__cont) noexcept(noexcept(__cont.data())) -> decltype(__cont.data())
Return the data pointer of a container.
constexpr auto cbegin(const _Container &__cont) noexcept(noexcept(std::begin(__cont))) -> decltype(std::begin(__cont))
Return an iterator pointing to the first element of the const container.
constexpr bitset< _Nb > operator&(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
__numeric_traits_integer< _Tp > __int_traits
Convenience alias for __numeric_traits<integer-type>.
The ranges::view_interface class template.
[range.view] The ranges::view_base type.
Type returned by algorithms instead of a dangling iterator or subrange.
[concept.same], concept same_as
[concept.derived], concept derived_from
[concept.constructible], concept constructible_from
[range.range] The range concept.
[range.range] The borrowed_range concept.
[range.sized] The sized_range concept.
[range.view] The ranges::view concept.
A range for which ranges::begin returns an output iterator.
A range for which ranges::begin returns an input iterator.
A range for which ranges::begin returns a forward iterator.
A range for which ranges::begin returns a bidirectional iterator.
A range for which ranges::begin returns a random access iterator.
A range for which ranges::begin returns a contiguous iterator.
A range for which ranges::begin and ranges::end return the same type.
A range which can be safely converted to a view.