${bits_srcdir}/random.h \
${bits_srcdir}/random.tcc \
${bits_srcdir}/range_access.h \
- ${bits_srcdir}/range_cmp.h \
${bits_srcdir}/ranges_algobase.h \
${bits_srcdir}/ranges_algo.h \
+ ${bits_srcdir}/ranges_base.h \
+ ${bits_srcdir}/ranges_cmp.h \
${bits_srcdir}/ranges_uninitialized.h \
+ ${bits_srcdir}/ranges_util.h \
${bits_srcdir}/refwrap.h \
${bits_srcdir}/regex.h \
${bits_srcdir}/regex.tcc \
${bits_srcdir}/random.h \
${bits_srcdir}/random.tcc \
${bits_srcdir}/range_access.h \
- ${bits_srcdir}/range_cmp.h \
${bits_srcdir}/ranges_algobase.h \
${bits_srcdir}/ranges_algo.h \
+ ${bits_srcdir}/ranges_base.h \
+ ${bits_srcdir}/ranges_cmp.h \
${bits_srcdir}/ranges_uninitialized.h \
+ ${bits_srcdir}/ranges_util.h \
${bits_srcdir}/refwrap.h \
${bits_srcdir}/regex.h \
${bits_srcdir}/regex.tcc \
#include <concepts>
#include <bits/ptr_traits.h> // to_address
-#include <bits/range_cmp.h> // identity, ranges::less
+#include <bits/ranges_cmp.h> // identity, ranges::less
#if __cpp_lib_concepts
namespace std _GLIBCXX_VISIBILITY(default)
-// <range_access.h> -*- C++ -*-
+// Range access functions for containers -*- C++ -*-
// Copyright (C) 2010-2020 Free Software Foundation, Inc.
//
#if __cplusplus >= 201103L
#include <initializer_list>
-#include <bits/iterator_concepts.h>
-#include <ext/numeric_traits.h>
-#if __cplusplus > 201703L
-#include <bits/max_size_type.h>
-#endif
+#include <type_traits> // common_type_t, make_signed_t
namespace std _GLIBCXX_VISIBILITY(default)
{
data(initializer_list<_Tp> __il) noexcept
{ return __il.begin(); }
-#endif // C++17
-
#if __cplusplus > 201703L
#define __cpp_lib_ssize 201902L
template<typename _Container>
constexpr ptrdiff_t
ssize(const _Tp (&)[_Num]) noexcept
{ return _Num; }
-
-#ifdef __cpp_lib_concepts
-namespace ranges
-{
- template<typename>
- inline constexpr bool disable_sized_range = false;
-
- template<typename _Tp>
- inline constexpr bool enable_borrowed_range = false;
-
- template<typename _Tp>
- extern const bool enable_view;
-
- namespace __detail
- {
- constexpr __max_size_type
- __to_unsigned_like(__max_size_type __t) noexcept
- { return __t; }
-
- constexpr __max_size_type
- __to_unsigned_like(__max_diff_type __t) noexcept
- { return __max_size_type(__t); }
-
- template<integral _Tp>
- constexpr auto
- __to_unsigned_like(_Tp __t) noexcept
- { return static_cast<make_unsigned_t<_Tp>>(__t); }
-
-#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
- constexpr unsigned __int128
- __to_unsigned_like(__int128 __t) noexcept
- { return __t; }
-
- constexpr unsigned __int128
- __to_unsigned_like(unsigned __int128 __t) noexcept
- { return __t; }
-#endif
-
- template<typename _Tp>
- using __make_unsigned_like_t
- = decltype(__detail::__to_unsigned_like(std::declval<_Tp>()));
-
- // Part of the constraints of ranges::borrowed_range
- template<typename _Tp>
- concept __maybe_borrowed_range
- = is_lvalue_reference_v<_Tp>
- || enable_borrowed_range<remove_cvref_t<_Tp>>;
-
- } // namespace __detail
-
- namespace __cust_access
- {
- using std::ranges::__detail::__maybe_borrowed_range;
- using std::__detail::__class_or_enum;
- using std::__detail::__decay_copy;
- using std::__detail::__member_begin;
- using std::__detail::__adl_begin;
-
- struct _Begin
- {
- private:
- template<typename _Tp>
- static constexpr bool
- _S_noexcept()
- {
- if constexpr (is_array_v<remove_reference_t<_Tp>>)
- return true;
- else if constexpr (__member_begin<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().begin()));
- else
- return noexcept(__decay_copy(begin(std::declval<_Tp&>())));
- }
-
- public:
- template<__maybe_borrowed_range _Tp>
- requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
- || __adl_begin<_Tp>
- constexpr auto
- operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
- {
- if constexpr (is_array_v<remove_reference_t<_Tp>>)
- {
- static_assert(is_lvalue_reference_v<_Tp>);
- using _Up = remove_all_extents_t<remove_reference_t<_Tp>>;
- static_assert(sizeof(_Up) != 0, "not array of incomplete type");
- return __t + 0;
- }
- else if constexpr (__member_begin<_Tp>)
- return __t.begin();
- else
- return begin(__t);
- }
- };
-
- template<typename _Tp>
- concept __member_end = requires(_Tp& __t)
- {
- { __decay_copy(__t.end()) }
- -> sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
- };
-
- void end(auto&) = delete;
- void end(const auto&) = delete;
-
- template<typename _Tp>
- concept __adl_end = __class_or_enum<remove_reference_t<_Tp>>
- && requires(_Tp& __t)
- {
- { __decay_copy(end(__t)) }
- -> sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
- };
-
- struct _End
- {
- private:
- template<typename _Tp>
- static constexpr bool
- _S_noexcept()
- {
- if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
- return true;
- else if constexpr (__member_end<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().end()));
- else
- return noexcept(__decay_copy(end(std::declval<_Tp&>())));
- }
-
- public:
- template<__maybe_borrowed_range _Tp>
- requires is_bounded_array_v<remove_reference_t<_Tp>> || __member_end<_Tp>
- || __adl_end<_Tp>
- constexpr auto
- operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
- {
- if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
- {
- static_assert(is_lvalue_reference_v<_Tp>);
- return __t + extent_v<remove_reference_t<_Tp>>;
- }
- else if constexpr (__member_end<_Tp>)
- return __t.end();
- else
- return end(__t);
- }
- };
-
- template<typename _Tp>
- constexpr decltype(auto)
- __as_const(_Tp&& __t) noexcept
- {
- if constexpr (is_lvalue_reference_v<_Tp>)
- return static_cast<const remove_reference_t<_Tp>&>(__t);
- else
- return static_cast<const _Tp&&>(__t);
- }
-
- struct _CBegin
- {
- template<typename _Tp>
- constexpr auto
- operator()(_Tp&& __e) const
- noexcept(noexcept(_Begin{}(__cust_access::__as_const((_Tp&&)__e))))
- requires requires { _Begin{}(__cust_access::__as_const((_Tp&&)__e)); }
- {
- return _Begin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
- }
- };
-
- struct _CEnd
- {
- template<typename _Tp>
- constexpr auto
- operator()(_Tp&& __e) const
- noexcept(noexcept(_End{}(__cust_access::__as_const((_Tp&&)__e))))
- requires requires { _End{}(__cust_access::__as_const((_Tp&&)__e)); }
- {
- return _End{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
- }
- };
-
- template<typename _Tp>
- concept __member_rbegin = requires(_Tp& __t)
- {
- { __decay_copy(__t.rbegin()) } -> input_or_output_iterator;
- };
-
- void rbegin(auto&) = delete;
- void rbegin(const auto&) = delete;
-
- template<typename _Tp>
- concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>>
- && requires(_Tp& __t)
- {
- { __decay_copy(rbegin(__t)) } -> input_or_output_iterator;
- };
-
- template<typename _Tp>
- concept __reversable = requires(_Tp& __t)
- {
- { _Begin{}(__t) } -> bidirectional_iterator;
- { _End{}(__t) } -> same_as<decltype(_Begin{}(__t))>;
- };
-
- struct _RBegin
- {
- private:
- template<typename _Tp>
- static constexpr bool
- _S_noexcept()
- {
- if constexpr (__member_rbegin<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().rbegin()));
- else if constexpr (__adl_rbegin<_Tp>)
- return noexcept(__decay_copy(rbegin(std::declval<_Tp&>())));
- else
- {
- if constexpr (noexcept(_End{}(std::declval<_Tp&>())))
- {
- using _It = decltype(_End{}(std::declval<_Tp&>()));
- // std::reverse_iterator copy-initializes its member.
- return is_nothrow_copy_constructible_v<_It>;
- }
- else
- return false;
- }
- }
-
- public:
- template<__maybe_borrowed_range _Tp>
- requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
- constexpr auto
- operator()(_Tp&& __t) const
- noexcept(_S_noexcept<_Tp>())
- {
- if constexpr (__member_rbegin<_Tp>)
- return __t.rbegin();
- else if constexpr (__adl_rbegin<_Tp>)
- return rbegin(__t);
- else
- return std::make_reverse_iterator(_End{}(__t));
- }
- };
-
- template<typename _Tp>
- concept __member_rend = requires(_Tp& __t)
- {
- { __decay_copy(__t.rend()) }
- -> sentinel_for<decltype(_RBegin{}(__t))>;
- };
-
- void rend(auto&) = delete;
- void rend(const auto&) = delete;
-
- template<typename _Tp>
- concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>>
- && requires(_Tp& __t)
- {
- { __decay_copy(rend(__t)) }
- -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
- };
-
- struct _REnd
- {
- private:
- template<typename _Tp>
- static constexpr bool
- _S_noexcept()
- {
- if constexpr (__member_rend<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().rend()));
- else if constexpr (__adl_rend<_Tp>)
- return noexcept(__decay_copy(rend(std::declval<_Tp&>())));
- else
- {
- if constexpr (noexcept(_Begin{}(std::declval<_Tp&>())))
- {
- using _It = decltype(_Begin{}(std::declval<_Tp&>()));
- // std::reverse_iterator copy-initializes its member.
- return is_nothrow_copy_constructible_v<_It>;
- }
- else
- return false;
- }
- }
-
- public:
- template<__maybe_borrowed_range _Tp>
- requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
- constexpr auto
- operator()(_Tp&& __t) const
- noexcept(_S_noexcept<_Tp>())
- {
- if constexpr (__member_rend<_Tp>)
- return __t.rend();
- else if constexpr (__adl_rend<_Tp>)
- return rend(__t);
- else
- return std::make_reverse_iterator(_Begin{}(__t));
- }
- };
-
- struct _CRBegin
- {
- template<typename _Tp>
- constexpr auto
- operator()(_Tp&& __e) const
- noexcept(noexcept(_RBegin{}(__cust_access::__as_const((_Tp&&)__e))))
- requires requires { _RBegin{}(__cust_access::__as_const((_Tp&&)__e)); }
- {
- return _RBegin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
- }
- };
-
- struct _CREnd
- {
- template<typename _Tp>
- constexpr auto
- operator()(_Tp&& __e) const
- noexcept(noexcept(_REnd{}(__cust_access::__as_const((_Tp&&)__e))))
- requires requires { _REnd{}(__cust_access::__as_const((_Tp&&)__e)); }
- {
- return _REnd{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
- }
- };
-
- template<typename _Tp>
- concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
- && requires(_Tp&& __t)
- {
- { __decay_copy(std::forward<_Tp>(__t).size()) }
- -> __detail::__is_integer_like;
- };
-
- void size(auto&) = delete;
- void size(const auto&) = delete;
-
- template<typename _Tp>
- concept __adl_size = __class_or_enum<remove_reference_t<_Tp>>
- && !disable_sized_range<remove_cvref_t<_Tp>>
- && requires(_Tp&& __t)
- {
- { __decay_copy(size(std::forward<_Tp>(__t))) }
- -> __detail::__is_integer_like;
- };
-
- template<typename _Tp>
- concept __sentinel_size = requires(_Tp&& __t)
- {
- { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
-
- { _End{}(std::forward<_Tp>(__t)) }
- -> sized_sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
- };
-
- struct _Size
- {
- private:
- template<typename _Tp>
- static constexpr bool
- _S_noexcept()
- {
- if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
- return true;
- else if constexpr (__member_size<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp>().size()));
- else if constexpr (__adl_size<_Tp>)
- return noexcept(__decay_copy(size(std::declval<_Tp>())));
- else if constexpr (__sentinel_size<_Tp>)
- return noexcept(_End{}(std::declval<_Tp>())
- - _Begin{}(std::declval<_Tp>()));
- }
-
- public:
- template<typename _Tp>
- requires is_bounded_array_v<remove_reference_t<_Tp>>
- || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
- constexpr auto
- operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
- {
- if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
- {
- return extent_v<remove_reference_t<_Tp>>;
- }
- else if constexpr (__member_size<_Tp>)
- return std::forward<_Tp>(__e).size();
- else if constexpr (__adl_size<_Tp>)
- return size(std::forward<_Tp>(__e));
- else if constexpr (__sentinel_size<_Tp>)
- return __detail::__to_unsigned_like(
- _End{}(std::forward<_Tp>(__e))
- - _Begin{}(std::forward<_Tp>(__e)));
- }
- };
-
- struct _SSize
- {
- template<typename _Tp>
- requires requires (_Tp&& __e)
- {
- _Begin{}(std::forward<_Tp>(__e));
- _Size{}(std::forward<_Tp>(__e));
- }
- constexpr auto
- operator()(_Tp&& __e) const
- noexcept(noexcept(_Size{}(std::forward<_Tp>(__e))))
- {
- using __iter_type = decltype(_Begin{}(std::forward<_Tp>(__e)));
- using __diff_type = iter_difference_t<__iter_type>;
- using __gnu_cxx::__int_traits;
- auto __size = _Size{}(std::forward<_Tp>(__e));
- if constexpr (integral<__diff_type>)
- {
- if constexpr (__int_traits<__diff_type>::__digits
- < __int_traits<ptrdiff_t>::__digits)
- return static_cast<ptrdiff_t>(__size);
- }
- return static_cast<__diff_type>(__size);
- }
- };
-
- template<typename _Tp>
- concept __member_empty = requires(_Tp&& __t)
- { bool(std::forward<_Tp>(__t).empty()); };
-
- template<typename _Tp>
- concept __size0_empty = requires(_Tp&& __t)
- { _Size{}(std::forward<_Tp>(__t)) == 0; };
-
- template<typename _Tp>
- concept __eq_iter_empty = requires(_Tp&& __t)
- {
- { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
- bool(_Begin{}(std::forward<_Tp>(__t))
- == _End{}(std::forward<_Tp>(__t)));
- };
-
- struct _Empty
- {
- private:
- template<typename _Tp>
- static constexpr bool
- _S_noexcept()
- {
- if constexpr (__member_empty<_Tp>)
- return noexcept(std::declval<_Tp>().empty());
- else if constexpr (__size0_empty<_Tp>)
- return noexcept(_Size{}(std::declval<_Tp>()) == 0);
- else
- return noexcept(bool(_Begin{}(std::declval<_Tp>())
- == _End{}(std::declval<_Tp>())));
- }
-
- public:
- template<typename _Tp>
- requires __member_empty<_Tp> || __size0_empty<_Tp>
- || __eq_iter_empty<_Tp>
- constexpr bool
- operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
- {
- if constexpr (__member_empty<_Tp>)
- return bool(std::forward<_Tp>(__e).empty());
- else if constexpr (__size0_empty<_Tp>)
- return _Size{}(std::forward<_Tp>(__e)) == 0;
- else
- return bool(_Begin{}(std::forward<_Tp>(__e))
- == _End{}(std::forward<_Tp>(__e)));
- }
- };
-
- template<typename _Tp>
- concept __pointer_to_object = is_pointer_v<_Tp>
- && is_object_v<remove_pointer_t<_Tp>>;
-
- template<typename _Tp>
- concept __member_data = is_lvalue_reference_v<_Tp>
- && requires(_Tp __t) { { __t.data() } -> __pointer_to_object; };
-
- template<typename _Tp>
- concept __begin_data = requires(_Tp&& __t)
- { { _Begin{}(std::forward<_Tp>(__t)) } -> contiguous_iterator; };
-
- struct _Data
- {
- private:
- template<typename _Tp>
- static constexpr bool
- _S_noexcept()
- {
- if constexpr (__member_data<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp>().data()));
- else
- return noexcept(_Begin{}(std::declval<_Tp>()));
- }
-
- public:
- template<__maybe_borrowed_range _Tp>
- requires __member_data<_Tp> || __begin_data<_Tp>
- constexpr auto
- operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
- {
- if constexpr (__member_data<_Tp>)
- return __e.data();
- else
- return std::to_address(_Begin{}(std::forward<_Tp>(__e)));
- }
- };
-
- struct _CData
- {
- template<typename _Tp>
- constexpr auto
- operator()(_Tp&& __e) const
- noexcept(noexcept(_Data{}(__cust_access::__as_const((_Tp&&)__e))))
- requires requires { _Data{}(__cust_access::__as_const((_Tp&&)__e)); }
- {
- return _Data{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
- }
- };
-
- } // namespace __cust_access
-
- inline namespace __cust
- {
- inline constexpr __cust_access::_Begin begin{};
- inline constexpr __cust_access::_End end{};
- inline constexpr __cust_access::_CBegin cbegin{};
- inline constexpr __cust_access::_CEnd cend{};
- inline constexpr __cust_access::_RBegin rbegin{};
- inline constexpr __cust_access::_REnd rend{};
- inline constexpr __cust_access::_CRBegin crbegin{};
- inline constexpr __cust_access::_CREnd crend{};
- inline constexpr __cust_access::_Size size{};
- inline constexpr __cust_access::_SSize ssize{};
- inline constexpr __cust_access::_Empty empty{};
- inline constexpr __cust_access::_Data data{};
- inline constexpr __cust_access::_CData cdata{};
- }
-
- /// [range.range] The range concept.
- template<typename _Tp>
- concept range = requires(_Tp& __t)
- {
- ranges::begin(__t);
- ranges::end(__t);
- };
-
- /// [range.range] The borrowed_range concept.
- template<typename _Tp>
- concept borrowed_range
- = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>;
-
- template<typename _Tp>
- using iterator_t = std::__detail::__range_iter_t<_Tp>;
-
- template<range _Range>
- using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
-
- template<range _Range>
- using range_difference_t = iter_difference_t<iterator_t<_Range>>;
-
- template<range _Range>
- using range_value_t = iter_value_t<iterator_t<_Range>>;
-
- template<range _Range>
- using range_reference_t = iter_reference_t<iterator_t<_Range>>;
-
- template<range _Range>
- using range_rvalue_reference_t
- = iter_rvalue_reference_t<iterator_t<_Range>>;
-
- /// [range.sized] The sized_range concept.
- template<typename _Tp>
- concept sized_range = range<_Tp>
- && requires(_Tp& __t) { ranges::size(__t); };
-
- template<sized_range _Range>
- using range_size_t = decltype(ranges::size(std::declval<_Range&>()));
-
- // [range.refinements]
-
- /// A range for which ranges::begin returns an output iterator.
- template<typename _Range, typename _Tp>
- concept output_range
- = range<_Range> && output_iterator<iterator_t<_Range>, _Tp>;
-
- /// A range for which ranges::begin returns an input iterator.
- template<typename _Tp>
- concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
-
- /// A range for which ranges::begin returns a forward iterator.
- template<typename _Tp>
- concept forward_range
- = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
-
- /// A range for which ranges::begin returns a bidirectional iterator.
- template<typename _Tp>
- concept bidirectional_range
- = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
-
- /// A range for which ranges::begin returns a random access iterator.
- template<typename _Tp>
- concept random_access_range
- = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
-
- /// A range for which ranges::begin returns a contiguous iterator.
- template<typename _Tp>
- concept contiguous_range
- = random_access_range<_Tp> && contiguous_iterator<iterator_t<_Tp>>
- && requires(_Tp& __t)
- {
- { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
- };
-
- /// A range for which ranges::begin and ranges::end return the same type.
- template<typename _Tp>
- concept common_range
- = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
-
- // [range.iter.ops] range iterator operations
-
- template<input_or_output_iterator _It>
- constexpr void
- advance(_It& __it, iter_difference_t<_It> __n)
- {
- if constexpr (random_access_iterator<_It>)
- __it += __n;
- else if constexpr (bidirectional_iterator<_It>)
- {
- if (__n > 0)
- {
- do
- {
- ++__it;
- }
- while (--__n);
- }
- else if (__n < 0)
- {
- do
- {
- --__it;
- }
- while (++__n);
- }
- }
- else
- {
- // cannot decrement a non-bidirectional iterator
- __glibcxx_assert(__n >= 0);
- while (__n-- > 0)
- ++__it;
- }
- }
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr void
- advance(_It& __it, _Sent __bound)
- {
- if constexpr (assignable_from<_It&, _Sent>)
- __it = std::move(__bound);
- else if constexpr (sized_sentinel_for<_Sent, _It>)
- ranges::advance(__it, __bound - __it);
- else
- {
- while (__it != __bound)
- ++__it;
- }
- }
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr iter_difference_t<_It>
- advance(_It& __it, iter_difference_t<_It> __n, _Sent __bound)
- {
- if constexpr (sized_sentinel_for<_Sent, _It>)
- {
- const auto __diff = __bound - __it;
-#ifdef __cpp_lib_is_constant_evaluated
- if (std::is_constant_evaluated()
- && !(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0)))
- throw "inconsistent directions for distance and bound";
-#endif
- // n and bound must not lead in opposite directions:
- __glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0));
- const auto __absdiff = __diff < 0 ? -__diff : __diff;
- const auto __absn = __n < 0 ? -__n : __n;;
- if (__absn >= __absdiff)
- {
- ranges::advance(__it, __bound);
- return __n - __diff;
- }
- else
- {
- ranges::advance(__it, __n);
- return 0;
- }
- }
- else if (__it == __bound || __n == 0)
- return iter_difference_t<_It>(0);
- else if (__n > 0)
- {
- iter_difference_t<_It> __m = 0;
- do
- {
- ++__it;
- ++__m;
- }
- while (__m != __n && __it != __bound);
- return __n - __m;
- }
- else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
- {
- iter_difference_t<_It> __m = 0;
- do
- {
- --__it;
- --__m;
- }
- while (__m != __n && __it != __bound);
- return __n - __m;
- }
- else
- {
- // cannot decrement a non-bidirectional iterator
- __glibcxx_assert(__n >= 0);
- return __n;
- }
- }
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr iter_difference_t<_It>
- distance(_It __first, _Sent __last)
- {
- if constexpr (sized_sentinel_for<_Sent, _It>)
- return __last - __first;
- else
- {
- iter_difference_t<_It> __n = 0;
- while (__first != __last)
- {
- ++__first;
- ++__n;
- }
- return __n;
- }
- }
-
- template<range _Range>
- constexpr range_difference_t<_Range>
- distance(_Range&& __r)
- {
- if constexpr (sized_range<_Range>)
- return static_cast<range_difference_t<_Range>>(ranges::size(__r));
- else
- return ranges::distance(ranges::begin(__r), ranges::end(__r));
- }
-
- template<input_or_output_iterator _It>
- constexpr _It
- next(_It __x)
- {
- ++__x;
- return __x;
- }
-
- template<input_or_output_iterator _It>
- constexpr _It
- next(_It __x, iter_difference_t<_It> __n)
- {
- ranges::advance(__x, __n);
- return __x;
- }
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr _It
- next(_It __x, _Sent __bound)
- {
- ranges::advance(__x, __bound);
- return __x;
- }
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr _It
- next(_It __x, iter_difference_t<_It> __n, _Sent __bound)
- {
- ranges::advance(__x, __n, __bound);
- return __x;
- }
-
- template<bidirectional_iterator _It>
- constexpr _It
- prev(_It __x)
- {
- --__x;
- return __x;
- }
-
- template<bidirectional_iterator _It>
- constexpr _It
- prev(_It __x, iter_difference_t<_It> __n)
- {
- ranges::advance(__x, -__n);
- return __x;
- }
-
- template<bidirectional_iterator _It>
- constexpr _It
- prev(_It __x, iter_difference_t<_It> __n, _It __bound)
- {
- ranges::advance(__x, -__n, __bound);
- return __x;
- }
-
-} // namespace ranges
-#endif // library concepts
#endif // C++20
+
+#endif // C++17
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif // C++11
-
#endif // _GLIBCXX_RANGE_ACCESS_H
+++ /dev/null
-// Concept-constrained comparison implementations -*- C++ -*-
-
-// Copyright (C) 2019-2020 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-// <http://www.gnu.org/licenses/>.
-
-/** @file bits/range_cmp.h
- * This is an internal header file, included by other library headers.
- * Do not attempt to use it directly. @headername{functional}
- */
-
-#ifndef _RANGE_CMP_H
-#define _RANGE_CMP_H 1
-
-#if __cplusplus > 201703L
-# include <bits/move.h>
-# include <concepts>
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- struct __is_transparent; // not defined
-
- // Define std::identity here so that <iterator> and <ranges>
- // don't need to include <bits/stl_function.h> to get it.
-
- /// [func.identity] The identity function.
- struct identity
- {
- template<typename _Tp>
- constexpr _Tp&&
- operator()(_Tp&& __t) const noexcept
- { return std::forward<_Tp>(__t); }
-
- using is_transparent = __is_transparent;
- };
-
-#ifdef __cpp_lib_concepts
-// Define this here, included by all the headers that need to define it.
-#define __cpp_lib_ranges 201911L
-
-namespace ranges
-{
- namespace __detail
- {
- // BUILTIN-PTR-CMP(T, ==, U)
- template<typename _Tp, typename _Up>
- concept __eq_builtin_ptr_cmp
- = requires (_Tp&& __t, _Up&& __u) { { __t == __u } -> same_as<bool>; }
- && convertible_to<_Tp, const volatile void*>
- && convertible_to<_Up, const volatile void*>
- && (! requires(_Tp&& __t, _Up&& __u)
- { operator==(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
- &&
- ! requires(_Tp&& __t, _Up&& __u)
- { std::forward<_Tp>(__t).operator==(std::forward<_Up>(__u)); });
-
- // BUILTIN-PTR-CMP(T, <, U)
- template<typename _Tp, typename _Up>
- concept __less_builtin_ptr_cmp
- = requires (_Tp&& __t, _Up&& __u) { { __t < __u } -> same_as<bool>; }
- && convertible_to<_Tp, const volatile void*>
- && convertible_to<_Up, const volatile void*>
- && (! requires(_Tp&& __t, _Up&& __u)
- { operator<(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
- && ! requires(_Tp&& __t, _Up&& __u)
- { std::forward<_Tp>(__t).operator<(std::forward<_Up>(__u)); });
- } // namespace __detail
-
- // [range.cmp] Concept-constrained comparisons
-
- /// ranges::equal_to function object type.
- struct equal_to
- {
- template<typename _Tp, typename _Up>
- requires equality_comparable_with<_Tp, _Up>
- || __detail::__eq_builtin_ptr_cmp<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
- noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>()))
- { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); }
-
- using is_transparent = __is_transparent;
- };
-
- /// ranges::not_equal_to function object type.
- struct not_equal_to
- {
- template<typename _Tp, typename _Up>
- requires equality_comparable_with<_Tp, _Up>
- || __detail::__eq_builtin_ptr_cmp<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
- noexcept(noexcept(std::declval<_Up>() == std::declval<_Tp>()))
- { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
-
- using is_transparent = __is_transparent;
- };
-
- /// ranges::less function object type.
- struct less
- {
- template<typename _Tp, typename _Up>
- requires totally_ordered_with<_Tp, _Up>
- || __detail::__less_builtin_ptr_cmp<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
- noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>()))
- {
- if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>)
- {
-#ifdef __cpp_lib_is_constant_evaluated
- if (std::is_constant_evaluated())
- return __t < __u;
-#endif
- auto __x = reinterpret_cast<__UINTPTR_TYPE__>(
- static_cast<const volatile void*>(std::forward<_Tp>(__t)));
- auto __y = reinterpret_cast<__UINTPTR_TYPE__>(
- static_cast<const volatile void*>(std::forward<_Up>(__u)));
- return __x < __y;
- }
- else
- return std::forward<_Tp>(__t) < std::forward<_Up>(__u);
- }
-
- using is_transparent = __is_transparent;
- };
-
- /// ranges::greater function object type.
- struct greater
- {
- template<typename _Tp, typename _Up>
- requires totally_ordered_with<_Tp, _Up>
- || __detail::__less_builtin_ptr_cmp<_Up, _Tp>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
- noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>()))
- { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); }
-
- using is_transparent = __is_transparent;
- };
-
- /// ranges::greater_equal function object type.
- struct greater_equal
- {
- template<typename _Tp, typename _Up>
- requires totally_ordered_with<_Tp, _Up>
- || __detail::__less_builtin_ptr_cmp<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
- noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>()))
- { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
-
- using is_transparent = __is_transparent;
- };
-
- /// ranges::less_equal function object type.
- struct less_equal
- {
- template<typename _Tp, typename _Up>
- requires totally_ordered_with<_Tp, _Up>
- || __detail::__less_builtin_ptr_cmp<_Up, _Tp>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
- noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>()))
- { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); }
-
- using is_transparent = __is_transparent;
- };
-
-} // namespace ranges
-#endif // library concepts
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace std
-#endif // C++20
-#endif // _RANGE_CMP_H
#if __cplusplus > 201703L
#include <bits/ranges_algobase.h>
+#include <bits/ranges_util.h>
#include <bits/uniform_int_dist.h> // concept uniform_random_bit_generator
#if __cpp_lib_concepts
#include <compare>
#include <iterator>
-// #include <bits/range_concepts.h>
-#include <ranges>
-#include <bits/invoke.h>
+#include <bits/ranges_base.h> // ranges::begin, ranges::range etc.
+#include <bits/invoke.h> // __invoke
#include <bits/cpp_type_traits.h> // __is_byte
#if __cpp_lib_concepts
--- /dev/null
+// Core concepts and definitions for <ranges> -*- C++ -*-
+
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/ranges_base.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{ranges}
+ */
+
+#ifndef _GLIBCXX_RANGES_BASE_H
+#define _GLIBCXX_RANGES_BASE_H 1
+
+#pragma GCC system_header
+
+#if __cplusplus > 201703L
+#include <bits/iterator_concepts.h>
+#include <ext/numeric_traits.h>
+#include <bits/max_size_type.h>
+
+#ifdef __cpp_lib_concepts
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace ranges
+{
+ template<typename>
+ inline constexpr bool disable_sized_range = false;
+
+ template<typename _Tp>
+ inline constexpr bool enable_borrowed_range = false;
+
+ namespace __detail
+ {
+ constexpr __max_size_type
+ __to_unsigned_like(__max_size_type __t) noexcept
+ { return __t; }
+
+ constexpr __max_size_type
+ __to_unsigned_like(__max_diff_type __t) noexcept
+ { return __max_size_type(__t); }
+
+ template<integral _Tp>
+ constexpr auto
+ __to_unsigned_like(_Tp __t) noexcept
+ { return static_cast<make_unsigned_t<_Tp>>(__t); }
+
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ constexpr unsigned __int128
+ __to_unsigned_like(__int128 __t) noexcept
+ { return __t; }
+
+ constexpr unsigned __int128
+ __to_unsigned_like(unsigned __int128 __t) noexcept
+ { return __t; }
+#endif
+
+ template<typename _Tp>
+ using __make_unsigned_like_t
+ = decltype(__detail::__to_unsigned_like(std::declval<_Tp>()));
+
+ // Part of the constraints of ranges::borrowed_range
+ template<typename _Tp>
+ concept __maybe_borrowed_range
+ = is_lvalue_reference_v<_Tp>
+ || enable_borrowed_range<remove_cvref_t<_Tp>>;
+
+ } // namespace __detail
+
+ namespace __cust_access
+ {
+ using std::ranges::__detail::__maybe_borrowed_range;
+ using std::__detail::__class_or_enum;
+ using std::__detail::__decay_copy;
+ using std::__detail::__member_begin;
+ using std::__detail::__adl_begin;
+
+ struct _Begin
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (is_array_v<remove_reference_t<_Tp>>)
+ return true;
+ else if constexpr (__member_begin<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp&>().begin()));
+ else
+ return noexcept(__decay_copy(begin(std::declval<_Tp&>())));
+ }
+
+ public:
+ template<__maybe_borrowed_range _Tp>
+ requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
+ || __adl_begin<_Tp>
+ constexpr auto
+ operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (is_array_v<remove_reference_t<_Tp>>)
+ {
+ static_assert(is_lvalue_reference_v<_Tp>);
+ using _Up = remove_all_extents_t<remove_reference_t<_Tp>>;
+ static_assert(sizeof(_Up) != 0, "not array of incomplete type");
+ return __t + 0;
+ }
+ else if constexpr (__member_begin<_Tp>)
+ return __t.begin();
+ else
+ return begin(__t);
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_end = requires(_Tp& __t)
+ {
+ { __decay_copy(__t.end()) }
+ -> sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
+ };
+
+ void end(auto&) = delete;
+ void end(const auto&) = delete;
+
+ template<typename _Tp>
+ concept __adl_end = __class_or_enum<remove_reference_t<_Tp>>
+ && requires(_Tp& __t)
+ {
+ { __decay_copy(end(__t)) }
+ -> sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
+ };
+
+ struct _End
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
+ return true;
+ else if constexpr (__member_end<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp&>().end()));
+ else
+ return noexcept(__decay_copy(end(std::declval<_Tp&>())));
+ }
+
+ public:
+ template<__maybe_borrowed_range _Tp>
+ requires is_bounded_array_v<remove_reference_t<_Tp>> || __member_end<_Tp>
+ || __adl_end<_Tp>
+ constexpr auto
+ operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
+ {
+ static_assert(is_lvalue_reference_v<_Tp>);
+ return __t + extent_v<remove_reference_t<_Tp>>;
+ }
+ else if constexpr (__member_end<_Tp>)
+ return __t.end();
+ else
+ return end(__t);
+ }
+ };
+
+ template<typename _Tp>
+ constexpr decltype(auto)
+ __as_const(_Tp&& __t) noexcept
+ {
+ if constexpr (is_lvalue_reference_v<_Tp>)
+ return static_cast<const remove_reference_t<_Tp>&>(__t);
+ else
+ return static_cast<const _Tp&&>(__t);
+ }
+
+ struct _CBegin
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_Begin{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _Begin{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _Begin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ struct _CEnd
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_End{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _End{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _End{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_rbegin = requires(_Tp& __t)
+ {
+ { __decay_copy(__t.rbegin()) } -> input_or_output_iterator;
+ };
+
+ void rbegin(auto&) = delete;
+ void rbegin(const auto&) = delete;
+
+ template<typename _Tp>
+ concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>>
+ && requires(_Tp& __t)
+ {
+ { __decay_copy(rbegin(__t)) } -> input_or_output_iterator;
+ };
+
+ template<typename _Tp>
+ concept __reversable = requires(_Tp& __t)
+ {
+ { _Begin{}(__t) } -> bidirectional_iterator;
+ { _End{}(__t) } -> same_as<decltype(_Begin{}(__t))>;
+ };
+
+ struct _RBegin
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_rbegin<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp&>().rbegin()));
+ else if constexpr (__adl_rbegin<_Tp>)
+ return noexcept(__decay_copy(rbegin(std::declval<_Tp&>())));
+ else
+ {
+ if constexpr (noexcept(_End{}(std::declval<_Tp&>())))
+ {
+ using _It = decltype(_End{}(std::declval<_Tp&>()));
+ // std::reverse_iterator copy-initializes its member.
+ return is_nothrow_copy_constructible_v<_It>;
+ }
+ else
+ return false;
+ }
+ }
+
+ public:
+ template<__maybe_borrowed_range _Tp>
+ requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
+ constexpr auto
+ operator()(_Tp&& __t) const
+ noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_rbegin<_Tp>)
+ return __t.rbegin();
+ else if constexpr (__adl_rbegin<_Tp>)
+ return rbegin(__t);
+ else
+ return std::make_reverse_iterator(_End{}(__t));
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_rend = requires(_Tp& __t)
+ {
+ { __decay_copy(__t.rend()) }
+ -> sentinel_for<decltype(_RBegin{}(__t))>;
+ };
+
+ void rend(auto&) = delete;
+ void rend(const auto&) = delete;
+
+ template<typename _Tp>
+ concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>>
+ && requires(_Tp& __t)
+ {
+ { __decay_copy(rend(__t)) }
+ -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
+ };
+
+ struct _REnd
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_rend<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp&>().rend()));
+ else if constexpr (__adl_rend<_Tp>)
+ return noexcept(__decay_copy(rend(std::declval<_Tp&>())));
+ else
+ {
+ if constexpr (noexcept(_Begin{}(std::declval<_Tp&>())))
+ {
+ using _It = decltype(_Begin{}(std::declval<_Tp&>()));
+ // std::reverse_iterator copy-initializes its member.
+ return is_nothrow_copy_constructible_v<_It>;
+ }
+ else
+ return false;
+ }
+ }
+
+ public:
+ template<__maybe_borrowed_range _Tp>
+ requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
+ constexpr auto
+ operator()(_Tp&& __t) const
+ noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_rend<_Tp>)
+ return __t.rend();
+ else if constexpr (__adl_rend<_Tp>)
+ return rend(__t);
+ else
+ return std::make_reverse_iterator(_Begin{}(__t));
+ }
+ };
+
+ struct _CRBegin
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_RBegin{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _RBegin{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _RBegin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ struct _CREnd
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_REnd{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _REnd{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _REnd{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
+ && requires(_Tp&& __t)
+ {
+ { __decay_copy(std::forward<_Tp>(__t).size()) }
+ -> __detail::__is_integer_like;
+ };
+
+ void size(auto&) = delete;
+ void size(const auto&) = delete;
+
+ template<typename _Tp>
+ concept __adl_size = __class_or_enum<remove_reference_t<_Tp>>
+ && !disable_sized_range<remove_cvref_t<_Tp>>
+ && requires(_Tp&& __t)
+ {
+ { __decay_copy(size(std::forward<_Tp>(__t))) }
+ -> __detail::__is_integer_like;
+ };
+
+ template<typename _Tp>
+ concept __sentinel_size = requires(_Tp&& __t)
+ {
+ { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
+
+ { _End{}(std::forward<_Tp>(__t)) }
+ -> sized_sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
+ };
+
+ struct _Size
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
+ return true;
+ else if constexpr (__member_size<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp>().size()));
+ else if constexpr (__adl_size<_Tp>)
+ return noexcept(__decay_copy(size(std::declval<_Tp>())));
+ else if constexpr (__sentinel_size<_Tp>)
+ return noexcept(_End{}(std::declval<_Tp>())
+ - _Begin{}(std::declval<_Tp>()));
+ }
+
+ public:
+ template<typename _Tp>
+ requires is_bounded_array_v<remove_reference_t<_Tp>>
+ || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
+ {
+ return extent_v<remove_reference_t<_Tp>>;
+ }
+ else if constexpr (__member_size<_Tp>)
+ return std::forward<_Tp>(__e).size();
+ else if constexpr (__adl_size<_Tp>)
+ return size(std::forward<_Tp>(__e));
+ else if constexpr (__sentinel_size<_Tp>)
+ return __detail::__to_unsigned_like(
+ _End{}(std::forward<_Tp>(__e))
+ - _Begin{}(std::forward<_Tp>(__e)));
+ }
+ };
+
+ struct _SSize
+ {
+ template<typename _Tp>
+ requires requires (_Tp&& __e)
+ {
+ _Begin{}(std::forward<_Tp>(__e));
+ _Size{}(std::forward<_Tp>(__e));
+ }
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_Size{}(std::forward<_Tp>(__e))))
+ {
+ using __iter_type = decltype(_Begin{}(std::forward<_Tp>(__e)));
+ using __diff_type = iter_difference_t<__iter_type>;
+ using __gnu_cxx::__int_traits;
+ auto __size = _Size{}(std::forward<_Tp>(__e));
+ if constexpr (integral<__diff_type>)
+ {
+ if constexpr (__int_traits<__diff_type>::__digits
+ < __int_traits<ptrdiff_t>::__digits)
+ return static_cast<ptrdiff_t>(__size);
+ }
+ return static_cast<__diff_type>(__size);
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_empty = requires(_Tp&& __t)
+ { bool(std::forward<_Tp>(__t).empty()); };
+
+ template<typename _Tp>
+ concept __size0_empty = requires(_Tp&& __t)
+ { _Size{}(std::forward<_Tp>(__t)) == 0; };
+
+ template<typename _Tp>
+ concept __eq_iter_empty = requires(_Tp&& __t)
+ {
+ { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
+ bool(_Begin{}(std::forward<_Tp>(__t))
+ == _End{}(std::forward<_Tp>(__t)));
+ };
+
+ struct _Empty
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_empty<_Tp>)
+ return noexcept(std::declval<_Tp>().empty());
+ else if constexpr (__size0_empty<_Tp>)
+ return noexcept(_Size{}(std::declval<_Tp>()) == 0);
+ else
+ return noexcept(bool(_Begin{}(std::declval<_Tp>())
+ == _End{}(std::declval<_Tp>())));
+ }
+
+ public:
+ template<typename _Tp>
+ requires __member_empty<_Tp> || __size0_empty<_Tp>
+ || __eq_iter_empty<_Tp>
+ constexpr bool
+ operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_empty<_Tp>)
+ return bool(std::forward<_Tp>(__e).empty());
+ else if constexpr (__size0_empty<_Tp>)
+ return _Size{}(std::forward<_Tp>(__e)) == 0;
+ else
+ return bool(_Begin{}(std::forward<_Tp>(__e))
+ == _End{}(std::forward<_Tp>(__e)));
+ }
+ };
+
+ template<typename _Tp>
+ concept __pointer_to_object = is_pointer_v<_Tp>
+ && is_object_v<remove_pointer_t<_Tp>>;
+
+ template<typename _Tp>
+ concept __member_data = is_lvalue_reference_v<_Tp>
+ && requires(_Tp __t) { { __t.data() } -> __pointer_to_object; };
+
+ template<typename _Tp>
+ concept __begin_data = requires(_Tp&& __t)
+ { { _Begin{}(std::forward<_Tp>(__t)) } -> contiguous_iterator; };
+
+ struct _Data
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_data<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp>().data()));
+ else
+ return noexcept(_Begin{}(std::declval<_Tp>()));
+ }
+
+ public:
+ template<__maybe_borrowed_range _Tp>
+ requires __member_data<_Tp> || __begin_data<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_data<_Tp>)
+ return __e.data();
+ else
+ return std::to_address(_Begin{}(std::forward<_Tp>(__e)));
+ }
+ };
+
+ struct _CData
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_Data{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _Data{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _Data{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ } // namespace __cust_access
+
+ inline namespace __cust
+ {
+ inline constexpr __cust_access::_Begin begin{};
+ inline constexpr __cust_access::_End end{};
+ inline constexpr __cust_access::_CBegin cbegin{};
+ inline constexpr __cust_access::_CEnd cend{};
+ inline constexpr __cust_access::_RBegin rbegin{};
+ inline constexpr __cust_access::_REnd rend{};
+ inline constexpr __cust_access::_CRBegin crbegin{};
+ inline constexpr __cust_access::_CREnd crend{};
+ inline constexpr __cust_access::_Size size{};
+ inline constexpr __cust_access::_SSize ssize{};
+ inline constexpr __cust_access::_Empty empty{};
+ inline constexpr __cust_access::_Data data{};
+ inline constexpr __cust_access::_CData cdata{};
+ }
+
+ /// [range.range] The range concept.
+ template<typename _Tp>
+ concept range = requires(_Tp& __t)
+ {
+ ranges::begin(__t);
+ ranges::end(__t);
+ };
+
+ /// [range.range] The borrowed_range concept.
+ template<typename _Tp>
+ concept borrowed_range
+ = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>;
+
+ template<typename _Tp>
+ using iterator_t = std::__detail::__range_iter_t<_Tp>;
+
+ template<range _Range>
+ using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
+
+ template<range _Range>
+ using range_difference_t = iter_difference_t<iterator_t<_Range>>;
+
+ template<range _Range>
+ using range_value_t = iter_value_t<iterator_t<_Range>>;
+
+ template<range _Range>
+ using range_reference_t = iter_reference_t<iterator_t<_Range>>;
+
+ template<range _Range>
+ using range_rvalue_reference_t
+ = iter_rvalue_reference_t<iterator_t<_Range>>;
+
+ /// [range.sized] The sized_range concept.
+ template<typename _Tp>
+ concept sized_range = range<_Tp>
+ && requires(_Tp& __t) { ranges::size(__t); };
+
+ template<sized_range _Range>
+ using range_size_t = decltype(ranges::size(std::declval<_Range&>()));
+
+ /// [range.view] The ranges::view_base type.
+ struct view_base { };
+
+ /// [range.view] The ranges::enable_view boolean.
+ template<typename _Tp>
+ inline constexpr bool enable_view = derived_from<_Tp, view_base>;
+
+ /// [range.view] The ranges::view concept.
+ template<typename _Tp>
+ concept view
+ = range<_Tp> && movable<_Tp> && default_initializable<_Tp>
+ && enable_view<_Tp>;
+
+ // [range.refinements]
+
+ /// A range for which ranges::begin returns an output iterator.
+ template<typename _Range, typename _Tp>
+ concept output_range
+ = range<_Range> && output_iterator<iterator_t<_Range>, _Tp>;
+
+ /// A range for which ranges::begin returns an input iterator.
+ template<typename _Tp>
+ concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
+
+ /// A range for which ranges::begin returns a forward iterator.
+ template<typename _Tp>
+ concept forward_range
+ = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
+
+ /// A range for which ranges::begin returns a bidirectional iterator.
+ template<typename _Tp>
+ concept bidirectional_range
+ = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
+
+ /// A range for which ranges::begin returns a random access iterator.
+ template<typename _Tp>
+ concept random_access_range
+ = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
+
+ /// A range for which ranges::begin returns a contiguous iterator.
+ template<typename _Tp>
+ concept contiguous_range
+ = random_access_range<_Tp> && contiguous_iterator<iterator_t<_Tp>>
+ && requires(_Tp& __t)
+ {
+ { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
+ };
+
+ /// A range for which ranges::begin and ranges::end return the same type.
+ template<typename _Tp>
+ concept common_range
+ = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
+
+ /// A range which can be safely converted to a view.
+ template<typename _Tp>
+ concept viewable_range = range<_Tp>
+ && (borrowed_range<_Tp> || view<remove_cvref_t<_Tp>>);
+
+ // [range.iter.ops] range iterator operations
+
+ template<input_or_output_iterator _It>
+ constexpr void
+ advance(_It& __it, iter_difference_t<_It> __n)
+ {
+ if constexpr (random_access_iterator<_It>)
+ __it += __n;
+ else if constexpr (bidirectional_iterator<_It>)
+ {
+ if (__n > 0)
+ {
+ do
+ {
+ ++__it;
+ }
+ while (--__n);
+ }
+ else if (__n < 0)
+ {
+ do
+ {
+ --__it;
+ }
+ while (++__n);
+ }
+ }
+ else
+ {
+ // cannot decrement a non-bidirectional iterator
+ __glibcxx_assert(__n >= 0);
+ while (__n-- > 0)
+ ++__it;
+ }
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr void
+ advance(_It& __it, _Sent __bound)
+ {
+ if constexpr (assignable_from<_It&, _Sent>)
+ __it = std::move(__bound);
+ else if constexpr (sized_sentinel_for<_Sent, _It>)
+ ranges::advance(__it, __bound - __it);
+ else
+ {
+ while (__it != __bound)
+ ++__it;
+ }
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr iter_difference_t<_It>
+ advance(_It& __it, iter_difference_t<_It> __n, _Sent __bound)
+ {
+ if constexpr (sized_sentinel_for<_Sent, _It>)
+ {
+ const auto __diff = __bound - __it;
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated()
+ && !(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0)))
+ throw "inconsistent directions for distance and bound";
+#endif
+ // n and bound must not lead in opposite directions:
+ __glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0));
+ const auto __absdiff = __diff < 0 ? -__diff : __diff;
+ const auto __absn = __n < 0 ? -__n : __n;;
+ if (__absn >= __absdiff)
+ {
+ ranges::advance(__it, __bound);
+ return __n - __diff;
+ }
+ else
+ {
+ ranges::advance(__it, __n);
+ return 0;
+ }
+ }
+ else if (__it == __bound || __n == 0)
+ return iter_difference_t<_It>(0);
+ else if (__n > 0)
+ {
+ iter_difference_t<_It> __m = 0;
+ do
+ {
+ ++__it;
+ ++__m;
+ }
+ while (__m != __n && __it != __bound);
+ return __n - __m;
+ }
+ else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
+ {
+ iter_difference_t<_It> __m = 0;
+ do
+ {
+ --__it;
+ --__m;
+ }
+ while (__m != __n && __it != __bound);
+ return __n - __m;
+ }
+ else
+ {
+ // cannot decrement a non-bidirectional iterator
+ __glibcxx_assert(__n >= 0);
+ return __n;
+ }
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr iter_difference_t<_It>
+ distance(_It __first, _Sent __last)
+ {
+ if constexpr (sized_sentinel_for<_Sent, _It>)
+ return __last - __first;
+ else
+ {
+ iter_difference_t<_It> __n = 0;
+ while (__first != __last)
+ {
+ ++__first;
+ ++__n;
+ }
+ return __n;
+ }
+ }
+
+ template<range _Range>
+ constexpr range_difference_t<_Range>
+ distance(_Range&& __r)
+ {
+ if constexpr (sized_range<_Range>)
+ return static_cast<range_difference_t<_Range>>(ranges::size(__r));
+ else
+ return ranges::distance(ranges::begin(__r), ranges::end(__r));
+ }
+
+ template<input_or_output_iterator _It>
+ constexpr _It
+ next(_It __x)
+ {
+ ++__x;
+ return __x;
+ }
+
+ template<input_or_output_iterator _It>
+ constexpr _It
+ next(_It __x, iter_difference_t<_It> __n)
+ {
+ ranges::advance(__x, __n);
+ return __x;
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr _It
+ next(_It __x, _Sent __bound)
+ {
+ ranges::advance(__x, __bound);
+ return __x;
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr _It
+ next(_It __x, iter_difference_t<_It> __n, _Sent __bound)
+ {
+ ranges::advance(__x, __n, __bound);
+ return __x;
+ }
+
+ template<bidirectional_iterator _It>
+ constexpr _It
+ prev(_It __x)
+ {
+ --__x;
+ return __x;
+ }
+
+ template<bidirectional_iterator _It>
+ constexpr _It
+ prev(_It __x, iter_difference_t<_It> __n)
+ {
+ ranges::advance(__x, -__n);
+ return __x;
+ }
+
+ template<bidirectional_iterator _It>
+ constexpr _It
+ prev(_It __x, iter_difference_t<_It> __n, _It __bound)
+ {
+ ranges::advance(__x, -__n, __bound);
+ return __x;
+ }
+
+ /// Type returned by algorithms instead of a dangling iterator or subrange.
+ struct dangling
+ {
+ constexpr dangling() noexcept = default;
+ template<typename... _Args>
+ constexpr dangling(_Args&&...) noexcept { }
+ };
+
+ template<range _Range>
+ using borrowed_iterator_t = conditional_t<borrowed_range<_Range>,
+ iterator_t<_Range>,
+ dangling>;
+
+} // namespace ranges
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // library concepts
+#endif // C++20
+#endif // _GLIBCXX_RANGES_BASE_H
--- /dev/null
+// Concept-constrained comparison implementations -*- C++ -*-
+
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/ranges_cmp.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _RANGES_CMP_H
+#define _RANGES_CMP_H 1
+
+#if __cplusplus > 201703L
+# include <bits/move.h>
+# include <concepts>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ struct __is_transparent; // not defined
+
+ // Define std::identity here so that <iterator> and <ranges>
+ // don't need to include <bits/stl_function.h> to get it.
+
+ /// [func.identity] The identity function.
+ struct identity
+ {
+ template<typename _Tp>
+ constexpr _Tp&&
+ operator()(_Tp&& __t) const noexcept
+ { return std::forward<_Tp>(__t); }
+
+ using is_transparent = __is_transparent;
+ };
+
+#ifdef __cpp_lib_concepts
+// Define this here, included by all the headers that need to define it.
+#define __cpp_lib_ranges 201911L
+
+namespace ranges
+{
+ namespace __detail
+ {
+ // BUILTIN-PTR-CMP(T, ==, U)
+ template<typename _Tp, typename _Up>
+ concept __eq_builtin_ptr_cmp
+ = requires (_Tp&& __t, _Up&& __u) { { __t == __u } -> same_as<bool>; }
+ && convertible_to<_Tp, const volatile void*>
+ && convertible_to<_Up, const volatile void*>
+ && (! requires(_Tp&& __t, _Up&& __u)
+ { operator==(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
+ &&
+ ! requires(_Tp&& __t, _Up&& __u)
+ { std::forward<_Tp>(__t).operator==(std::forward<_Up>(__u)); });
+
+ // BUILTIN-PTR-CMP(T, <, U)
+ template<typename _Tp, typename _Up>
+ concept __less_builtin_ptr_cmp
+ = requires (_Tp&& __t, _Up&& __u) { { __t < __u } -> same_as<bool>; }
+ && convertible_to<_Tp, const volatile void*>
+ && convertible_to<_Up, const volatile void*>
+ && (! requires(_Tp&& __t, _Up&& __u)
+ { operator<(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
+ && ! requires(_Tp&& __t, _Up&& __u)
+ { std::forward<_Tp>(__t).operator<(std::forward<_Up>(__u)); });
+ } // namespace __detail
+
+ // [range.cmp] Concept-constrained comparisons
+
+ /// ranges::equal_to function object type.
+ struct equal_to
+ {
+ template<typename _Tp, typename _Up>
+ requires equality_comparable_with<_Tp, _Up>
+ || __detail::__eq_builtin_ptr_cmp<_Tp, _Up>
+ constexpr bool
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>()))
+ { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); }
+
+ using is_transparent = __is_transparent;
+ };
+
+ /// ranges::not_equal_to function object type.
+ struct not_equal_to
+ {
+ template<typename _Tp, typename _Up>
+ requires equality_comparable_with<_Tp, _Up>
+ || __detail::__eq_builtin_ptr_cmp<_Tp, _Up>
+ constexpr bool
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::declval<_Up>() == std::declval<_Tp>()))
+ { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
+
+ using is_transparent = __is_transparent;
+ };
+
+ /// ranges::less function object type.
+ struct less
+ {
+ template<typename _Tp, typename _Up>
+ requires totally_ordered_with<_Tp, _Up>
+ || __detail::__less_builtin_ptr_cmp<_Tp, _Up>
+ constexpr bool
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>()))
+ {
+ if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>)
+ {
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated())
+ return __t < __u;
+#endif
+ auto __x = reinterpret_cast<__UINTPTR_TYPE__>(
+ static_cast<const volatile void*>(std::forward<_Tp>(__t)));
+ auto __y = reinterpret_cast<__UINTPTR_TYPE__>(
+ static_cast<const volatile void*>(std::forward<_Up>(__u)));
+ return __x < __y;
+ }
+ else
+ return std::forward<_Tp>(__t) < std::forward<_Up>(__u);
+ }
+
+ using is_transparent = __is_transparent;
+ };
+
+ /// ranges::greater function object type.
+ struct greater
+ {
+ template<typename _Tp, typename _Up>
+ requires totally_ordered_with<_Tp, _Up>
+ || __detail::__less_builtin_ptr_cmp<_Up, _Tp>
+ constexpr bool
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>()))
+ { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); }
+
+ using is_transparent = __is_transparent;
+ };
+
+ /// ranges::greater_equal function object type.
+ struct greater_equal
+ {
+ template<typename _Tp, typename _Up>
+ requires totally_ordered_with<_Tp, _Up>
+ || __detail::__less_builtin_ptr_cmp<_Tp, _Up>
+ constexpr bool
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>()))
+ { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
+
+ using is_transparent = __is_transparent;
+ };
+
+ /// ranges::less_equal function object type.
+ struct less_equal
+ {
+ template<typename _Tp, typename _Up>
+ requires totally_ordered_with<_Tp, _Up>
+ || __detail::__less_builtin_ptr_cmp<_Up, _Tp>
+ constexpr bool
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>()))
+ { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); }
+
+ using is_transparent = __is_transparent;
+ };
+
+} // namespace ranges
+#endif // library concepts
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+#endif // _RANGES_CMP_H
--- /dev/null
+// Utilities for representing and manipulating ranges -*- C++ -*-
+
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/ranges_util.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{ranges}
+ */
+
+#ifndef _RANGES_UTIL_H
+#define _RANGES_UTIL_H 1
+
+#if __cplusplus > 201703L
+# include <bits/ranges_base.h>
+
+#ifdef __cpp_lib_ranges
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace ranges
+{
+ // C++20 24.5 [range.utility] Range utilities
+
+ namespace __detail
+ {
+ template<typename _Range>
+ concept __simple_view = view<_Range> && range<const _Range>
+ && same_as<iterator_t<_Range>, iterator_t<const _Range>>
+ && same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
+
+ template<typename _It>
+ concept __has_arrow = input_iterator<_It>
+ && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); });
+
+ template<typename _Tp, typename _Up>
+ concept __not_same_as
+ = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
+ } // namespace __detail
+
+ /// The ranges::view_interface class template
+ template<typename _Derived>
+ requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
+ class view_interface : public view_base
+ {
+ private:
+ constexpr _Derived& _M_derived() noexcept
+ {
+ static_assert(derived_from<_Derived, view_interface<_Derived>>);
+ static_assert(view<_Derived>);
+ return static_cast<_Derived&>(*this);
+ }
+
+ constexpr const _Derived& _M_derived() const noexcept
+ {
+ static_assert(derived_from<_Derived, view_interface<_Derived>>);
+ static_assert(view<_Derived>);
+ return static_cast<const _Derived&>(*this);
+ }
+
+ public:
+ constexpr bool
+ empty() requires forward_range<_Derived>
+ { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); }
+
+ constexpr bool
+ empty() const requires forward_range<const _Derived>
+ { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); }
+
+ constexpr explicit
+ operator bool() requires requires { ranges::empty(_M_derived()); }
+ { return !ranges::empty(_M_derived()); }
+
+ constexpr explicit
+ operator bool() const requires requires { ranges::empty(_M_derived()); }
+ { return !ranges::empty(_M_derived()); }
+
+ constexpr auto
+ data() requires contiguous_iterator<iterator_t<_Derived>>
+ { return to_address(ranges::begin(_M_derived())); }
+
+ constexpr auto
+ data() const
+ requires range<const _Derived>
+ && contiguous_iterator<iterator_t<const _Derived>>
+ { return to_address(ranges::begin(_M_derived())); }
+
+ constexpr auto
+ size()
+ requires forward_range<_Derived>
+ && sized_sentinel_for<sentinel_t<_Derived>, iterator_t<_Derived>>
+ { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); }
+
+ constexpr auto
+ size() const
+ requires forward_range<const _Derived>
+ && sized_sentinel_for<sentinel_t<const _Derived>,
+ iterator_t<const _Derived>>
+ { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); }
+
+ constexpr decltype(auto)
+ front() requires forward_range<_Derived>
+ {
+ __glibcxx_assert(!empty());
+ return *ranges::begin(_M_derived());
+ }
+
+ constexpr decltype(auto)
+ front() const requires forward_range<const _Derived>
+ {
+ __glibcxx_assert(!empty());
+ return *ranges::begin(_M_derived());
+ }
+
+ constexpr decltype(auto)
+ back()
+ requires bidirectional_range<_Derived> && common_range<_Derived>
+ {
+ __glibcxx_assert(!empty());
+ return *ranges::prev(ranges::end(_M_derived()));
+ }
+
+ constexpr decltype(auto)
+ back() const
+ requires bidirectional_range<const _Derived>
+ && common_range<const _Derived>
+ {
+ __glibcxx_assert(!empty());
+ return *ranges::prev(ranges::end(_M_derived()));
+ }
+
+ template<random_access_range _Range = _Derived>
+ constexpr decltype(auto)
+ operator[](range_difference_t<_Range> __n)
+ { return ranges::begin(_M_derived())[__n]; }
+
+ template<random_access_range _Range = const _Derived>
+ constexpr decltype(auto)
+ operator[](range_difference_t<_Range> __n) const
+ { return ranges::begin(_M_derived())[__n]; }
+ };
+
+ namespace __detail
+ {
+ template<class _From, class _To>
+ concept __convertible_to_non_slicing = convertible_to<_From, _To>
+ && !(is_pointer_v<decay_t<_From>> && is_pointer_v<decay_t<_To>>
+ && __not_same_as<remove_pointer_t<decay_t<_From>>,
+ remove_pointer_t<decay_t<_To>>>);
+
+ template<typename _Tp>
+ concept __pair_like
+ = !is_reference_v<_Tp> && requires(_Tp __t)
+ {
+ typename tuple_size<_Tp>::type;
+ requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>;
+ typename tuple_element_t<0, remove_const_t<_Tp>>;
+ typename tuple_element_t<1, remove_const_t<_Tp>>;
+ { get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>;
+ { get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>;
+ };
+
+ template<typename _Tp, typename _Up, typename _Vp>
+ concept __pair_like_convertible_from
+ = !range<_Tp> && __pair_like<_Tp>
+ && constructible_from<_Tp, _Up, _Vp>
+ && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>>
+ && convertible_to<_Vp, tuple_element_t<1, _Tp>>;
+
+ template<typename _Tp>
+ concept __iterator_sentinel_pair
+ = !range<_Tp> && __pair_like<_Tp>
+ && sentinel_for<tuple_element_t<1, _Tp>, tuple_element_t<0, _Tp>>;
+
+ } // namespace __detail
+
+ enum class subrange_kind : bool { unsized, sized };
+
+ /// The ranges::subrange class template
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent = _It,
+ subrange_kind _Kind = sized_sentinel_for<_Sent, _It>
+ ? subrange_kind::sized : subrange_kind::unsized>
+ requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>)
+ class subrange : public view_interface<subrange<_It, _Sent, _Kind>>
+ {
+ private:
+ // XXX: gcc complains when using constexpr here
+ static const bool _S_store_size
+ = _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>;
+
+ _It _M_begin = _It();
+ _Sent _M_end = _Sent();
+
+ template<typename, bool = _S_store_size>
+ struct _Size
+ { };
+
+ template<typename _Tp>
+ struct _Size<_Tp, true>
+ { __detail::__make_unsigned_like_t<_Tp> _M_size; };
+
+ [[no_unique_address]] _Size<iter_difference_t<_It>> _M_size = {};
+
+ public:
+ subrange() = default;
+
+ constexpr
+ subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s)
+ requires (!_S_store_size)
+ : _M_begin(std::move(__i)), _M_end(__s)
+ { }
+
+ constexpr
+ subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s,
+ __detail::__make_unsigned_like_t<iter_difference_t<_It>> __n)
+ requires (_Kind == subrange_kind::sized)
+ : _M_begin(std::move(__i)), _M_end(__s)
+ {
+ using __detail::__to_unsigned_like;
+ __glibcxx_assert(__n == __to_unsigned_like(ranges::distance(__i, __s)));
+ if constexpr (_S_store_size)
+ _M_size._M_size = __n;
+ }
+
+ template<__detail::__not_same_as<subrange> _Rng>
+ requires borrowed_range<_Rng>
+ && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
+ && convertible_to<sentinel_t<_Rng>, _Sent>
+ constexpr
+ subrange(_Rng&& __r) requires _S_store_size && sized_range<_Rng>
+ : subrange{__r, ranges::size(__r)}
+ { }
+
+ template<__detail::__not_same_as<subrange> _Rng>
+ requires borrowed_range<_Rng>
+ && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
+ && convertible_to<sentinel_t<_Rng>, _Sent>
+ constexpr
+ subrange(_Rng&& __r) requires (!_S_store_size)
+ : subrange{ranges::begin(__r), ranges::end(__r)}
+ { }
+
+ template<borrowed_range _Rng>
+ requires __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
+ && convertible_to<sentinel_t<_Rng>, _Sent>
+ constexpr
+ subrange(_Rng&& __r,
+ __detail::__make_unsigned_like_t<iter_difference_t<_It>> __n)
+ requires (_Kind == subrange_kind::sized)
+ : subrange{ranges::begin(__r), ranges::end(__r), __n}
+ { }
+
+ template<__detail::__not_same_as<subrange> _PairLike>
+ requires __detail::__pair_like_convertible_from<_PairLike, const _It&,
+ const _Sent&>
+ constexpr
+ operator _PairLike() const
+ { return _PairLike(_M_begin, _M_end); }
+
+ constexpr _It
+ begin() const requires copyable<_It>
+ { return _M_begin; }
+
+ [[nodiscard]] constexpr _It
+ begin() requires (!copyable<_It>)
+ { return std::move(_M_begin); }
+
+ constexpr _Sent end() const { return _M_end; }
+
+ constexpr bool empty() const { return _M_begin == _M_end; }
+
+ constexpr __detail::__make_unsigned_like_t<iter_difference_t<_It>>
+ size() const requires (_Kind == subrange_kind::sized)
+ {
+ if constexpr (_S_store_size)
+ return _M_size._M_size;
+ else
+ return __detail::__to_unsigned_like(_M_end - _M_begin);
+ }
+
+ [[nodiscard]] constexpr subrange
+ next(iter_difference_t<_It> __n = 1) const &
+ requires forward_iterator<_It>
+ {
+ auto __tmp = *this;
+ __tmp.advance(__n);
+ return __tmp;
+ }
+
+ [[nodiscard]] constexpr subrange
+ next(iter_difference_t<_It> __n = 1) &&
+ {
+ advance(__n);
+ return std::move(*this);
+ }
+
+ [[nodiscard]] constexpr subrange
+ prev(iter_difference_t<_It> __n = 1) const
+ requires bidirectional_iterator<_It>
+ {
+ auto __tmp = *this;
+ __tmp.advance(-__n);
+ return __tmp;
+ }
+
+ constexpr subrange&
+ advance(iter_difference_t<_It> __n)
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3433. subrange::advance(n) has UB when n < 0
+ if constexpr (bidirectional_iterator<_It>)
+ if (__n < 0)
+ {
+ ranges::advance(_M_begin, __n);
+ if constexpr (_S_store_size)
+ _M_size._M_size += __detail::__to_unsigned_like(-__n);
+ return *this;
+ }
+
+ __glibcxx_assert(__n >= 0);
+ auto __d = __n - ranges::advance(_M_begin, __n, _M_end);
+ if constexpr (_S_store_size)
+ _M_size._M_size -= __detail::__to_unsigned_like(__d);
+ return *this;
+ }
+ };
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ subrange(_It, _Sent) -> subrange<_It, _Sent>;
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ subrange(_It, _Sent,
+ __detail::__make_unsigned_like_t<iter_difference_t<_It>>)
+ -> subrange<_It, _Sent, subrange_kind::sized>;
+
+ template<__detail::__iterator_sentinel_pair _Pr>
+ subrange(_Pr)
+ -> subrange<tuple_element_t<0, _Pr>, tuple_element_t<1, _Pr>>;
+
+ template<__detail::__iterator_sentinel_pair _Pr>
+ subrange(_Pr, __detail::__make_unsigned_like_t<iter_difference_t<
+ tuple_element_t<0, _Pr>>>)
+ -> subrange<tuple_element_t<0, _Pr>, tuple_element_t<1, _Pr>,
+ subrange_kind::sized>;
+
+ template<borrowed_range _Rng>
+ subrange(_Rng&&)
+ -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>,
+ (sized_range<_Rng>
+ || sized_sentinel_for<sentinel_t<_Rng>, iterator_t<_Rng>>)
+ ? subrange_kind::sized : subrange_kind::unsized>;
+
+ template<borrowed_range _Rng>
+ subrange(_Rng&&,
+ __detail::__make_unsigned_like_t<range_difference_t<_Rng>>)
+ -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>, subrange_kind::sized>;
+
+ template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
+ requires (_Num < 2)
+ constexpr auto
+ get(const subrange<_It, _Sent, _Kind>& __r)
+ {
+ if constexpr (_Num == 0)
+ return __r.begin();
+ else
+ return __r.end();
+ }
+
+ template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
+ requires (_Num < 2)
+ constexpr auto
+ get(subrange<_It, _Sent, _Kind>&& __r)
+ {
+ if constexpr (_Num == 0)
+ return __r.begin();
+ else
+ return __r.end();
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent,
+ subrange_kind _Kind>
+ inline constexpr bool
+ enable_borrowed_range<subrange<_It, _Sent, _Kind>> = true;
+
+ template<range _Range>
+ using borrowed_subrange_t = conditional_t<borrowed_range<_Range>,
+ subrange<iterator_t<_Range>>,
+ dangling>;
+
+} // namespace ranges
+
+ using ranges::get;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // library concepts
+#endif // C++20
+#endif // _RANGES_UTIL_H
#include <string>
#include <limits>
+#include <bits/ranges_base.h> // enable_borrowed_range, enable_view
#include <experimental/bits/lfts_config.h>
namespace std _GLIBCXX_VISIBILITY(default)
# include <bits/stl_algo.h>
#endif
#if __cplusplus > 201703L
-# include <bits/range_cmp.h>
+# include <bits/ranges_cmp.h>
# include <compare>
#endif
#if __cpp_lib_concepts
-#include <bits/refwrap.h>
#include <compare>
#include <initializer_list>
#include <iterator>
#include <optional>
#include <tuple>
+#include <bits/ranges_util.h>
+#include <bits/refwrap.h>
/**
* @defgroup ranges Ranges
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace ranges
{
- // [range.range] The range concept.
- // [range.sized] The sized_range concept.
- // Defined in <bits/range_access.h>
-
- // [range.refinements]
- // Defined in <bits/range_access.h>
-
- struct view_base { };
-
- template<typename _Tp>
- inline constexpr bool enable_view = derived_from<_Tp, view_base>;
-
- template<typename _Tp>
- concept view
- = range<_Tp> && movable<_Tp> && default_initializable<_Tp>
- && enable_view<_Tp>;
-
- /// A range which can be safely converted to a view.
- template<typename _Tp>
- concept viewable_range = range<_Tp>
- && (borrowed_range<_Tp> || view<remove_cvref_t<_Tp>>);
-
- namespace __detail
- {
- template<typename _Range>
- concept __simple_view = view<_Range> && range<const _Range>
- && same_as<iterator_t<_Range>, iterator_t<const _Range>>
- && same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
-
- template<typename _It>
- concept __has_arrow = input_iterator<_It>
- && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); });
-
- template<typename _Tp, typename _Up>
- concept __not_same_as
- = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
- } // namespace __detail
-
- template<typename _Derived>
- requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
- class view_interface : public view_base
- {
- private:
- constexpr _Derived& _M_derived() noexcept
- {
- static_assert(derived_from<_Derived, view_interface<_Derived>>);
- static_assert(view<_Derived>);
- return static_cast<_Derived&>(*this);
- }
-
- constexpr const _Derived& _M_derived() const noexcept
- {
- static_assert(derived_from<_Derived, view_interface<_Derived>>);
- static_assert(view<_Derived>);
- return static_cast<const _Derived&>(*this);
- }
-
- public:
- constexpr bool
- empty() requires forward_range<_Derived>
- { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); }
-
- constexpr bool
- empty() const requires forward_range<const _Derived>
- { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); }
-
- constexpr explicit
- operator bool() requires requires { ranges::empty(_M_derived()); }
- { return !ranges::empty(_M_derived()); }
-
- constexpr explicit
- operator bool() const requires requires { ranges::empty(_M_derived()); }
- { return !ranges::empty(_M_derived()); }
-
- constexpr auto
- data() requires contiguous_iterator<iterator_t<_Derived>>
- { return to_address(ranges::begin(_M_derived())); }
-
- constexpr auto
- data() const
- requires range<const _Derived>
- && contiguous_iterator<iterator_t<const _Derived>>
- { return to_address(ranges::begin(_M_derived())); }
-
- constexpr auto
- size()
- requires forward_range<_Derived>
- && sized_sentinel_for<sentinel_t<_Derived>, iterator_t<_Derived>>
- { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); }
-
- constexpr auto
- size() const
- requires forward_range<const _Derived>
- && sized_sentinel_for<sentinel_t<const _Derived>,
- iterator_t<const _Derived>>
- { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); }
-
- constexpr decltype(auto)
- front() requires forward_range<_Derived>
- {
- __glibcxx_assert(!empty());
- return *ranges::begin(_M_derived());
- }
-
- constexpr decltype(auto)
- front() const requires forward_range<const _Derived>
- {
- __glibcxx_assert(!empty());
- return *ranges::begin(_M_derived());
- }
-
- constexpr decltype(auto)
- back()
- requires bidirectional_range<_Derived> && common_range<_Derived>
- {
- __glibcxx_assert(!empty());
- return *ranges::prev(ranges::end(_M_derived()));
- }
-
- constexpr decltype(auto)
- back() const
- requires bidirectional_range<const _Derived>
- && common_range<const _Derived>
- {
- __glibcxx_assert(!empty());
- return *ranges::prev(ranges::end(_M_derived()));
- }
-
- template<random_access_range _Range = _Derived>
- constexpr decltype(auto)
- operator[](range_difference_t<_Range> __n)
- { return ranges::begin(_M_derived())[__n]; }
-
- template<random_access_range _Range = const _Derived>
- constexpr decltype(auto)
- operator[](range_difference_t<_Range> __n) const
- { return ranges::begin(_M_derived())[__n]; }
- };
-
- namespace __detail
- {
- template<class _From, class _To>
- concept __convertible_to_non_slicing = convertible_to<_From, _To>
- && !(is_pointer_v<decay_t<_From>> && is_pointer_v<decay_t<_To>>
- && __not_same_as<remove_pointer_t<decay_t<_From>>,
- remove_pointer_t<decay_t<_To>>>);
-
- template<typename _Tp>
- concept __pair_like
- = !is_reference_v<_Tp> && requires(_Tp __t)
- {
- typename tuple_size<_Tp>::type;
- requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>;
- typename tuple_element_t<0, remove_const_t<_Tp>>;
- typename tuple_element_t<1, remove_const_t<_Tp>>;
- { get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>;
- { get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>;
- };
-
- template<typename _Tp, typename _Up, typename _Vp>
- concept __pair_like_convertible_from
- = !range<_Tp> && __pair_like<_Tp>
- && constructible_from<_Tp, _Up, _Vp>
- && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>>
- && convertible_to<_Vp, tuple_element_t<1, _Tp>>;
-
- template<typename _Tp>
- concept __iterator_sentinel_pair
- = !range<_Tp> && __pair_like<_Tp>
- && sentinel_for<tuple_element_t<1, _Tp>, tuple_element_t<0, _Tp>>;
-
- } // namespace __detail
-
- enum class subrange_kind : bool { unsized, sized };
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent = _It,
- subrange_kind _Kind = sized_sentinel_for<_Sent, _It>
- ? subrange_kind::sized : subrange_kind::unsized>
- requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>)
- class subrange : public view_interface<subrange<_It, _Sent, _Kind>>
- {
- private:
- // XXX: gcc complains when using constexpr here
- static const bool _S_store_size
- = _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>;
-
- _It _M_begin = _It();
- _Sent _M_end = _Sent();
-
- template<typename, bool = _S_store_size>
- struct _Size
- { };
-
- template<typename _Tp>
- struct _Size<_Tp, true>
- { __detail::__make_unsigned_like_t<_Tp> _M_size; };
-
- [[no_unique_address]] _Size<iter_difference_t<_It>> _M_size = {};
-
- public:
- subrange() = default;
-
- constexpr
- subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s)
- requires (!_S_store_size)
- : _M_begin(std::move(__i)), _M_end(__s)
- { }
-
- constexpr
- subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s,
- __detail::__make_unsigned_like_t<iter_difference_t<_It>> __n)
- requires (_Kind == subrange_kind::sized)
- : _M_begin(std::move(__i)), _M_end(__s)
- {
- using __detail::__to_unsigned_like;
- __glibcxx_assert(__n == __to_unsigned_like(ranges::distance(__i, __s)));
- if constexpr (_S_store_size)
- _M_size._M_size = __n;
- }
-
- template<__detail::__not_same_as<subrange> _Rng>
- requires borrowed_range<_Rng>
- && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
- && convertible_to<sentinel_t<_Rng>, _Sent>
- constexpr
- subrange(_Rng&& __r) requires _S_store_size && sized_range<_Rng>
- : subrange{__r, ranges::size(__r)}
- { }
-
- template<__detail::__not_same_as<subrange> _Rng>
- requires borrowed_range<_Rng>
- && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
- && convertible_to<sentinel_t<_Rng>, _Sent>
- constexpr
- subrange(_Rng&& __r) requires (!_S_store_size)
- : subrange{ranges::begin(__r), ranges::end(__r)}
- { }
-
- template<borrowed_range _Rng>
- requires __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
- && convertible_to<sentinel_t<_Rng>, _Sent>
- constexpr
- subrange(_Rng&& __r,
- __detail::__make_unsigned_like_t<iter_difference_t<_It>> __n)
- requires (_Kind == subrange_kind::sized)
- : subrange{ranges::begin(__r), ranges::end(__r), __n}
- { }
-
- template<__detail::__not_same_as<subrange> _PairLike>
- requires __detail::__pair_like_convertible_from<_PairLike, const _It&,
- const _Sent&>
- constexpr
- operator _PairLike() const
- { return _PairLike(_M_begin, _M_end); }
-
- constexpr _It
- begin() const requires copyable<_It>
- { return _M_begin; }
-
- [[nodiscard]] constexpr _It
- begin() requires (!copyable<_It>)
- { return std::move(_M_begin); }
-
- constexpr _Sent end() const { return _M_end; }
-
- constexpr bool empty() const { return _M_begin == _M_end; }
-
- constexpr __detail::__make_unsigned_like_t<iter_difference_t<_It>>
- size() const requires (_Kind == subrange_kind::sized)
- {
- if constexpr (_S_store_size)
- return _M_size._M_size;
- else
- return __detail::__to_unsigned_like(_M_end - _M_begin);
- }
-
- [[nodiscard]] constexpr subrange
- next(iter_difference_t<_It> __n = 1) const &
- requires forward_iterator<_It>
- {
- auto __tmp = *this;
- __tmp.advance(__n);
- return __tmp;
- }
-
- [[nodiscard]] constexpr subrange
- next(iter_difference_t<_It> __n = 1) &&
- {
- advance(__n);
- return std::move(*this);
- }
-
- [[nodiscard]] constexpr subrange
- prev(iter_difference_t<_It> __n = 1) const
- requires bidirectional_iterator<_It>
- {
- auto __tmp = *this;
- __tmp.advance(-__n);
- return __tmp;
- }
-
- constexpr subrange&
- advance(iter_difference_t<_It> __n)
- {
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 3433. subrange::advance(n) has UB when n < 0
- if constexpr (bidirectional_iterator<_It>)
- if (__n < 0)
- {
- ranges::advance(_M_begin, __n);
- if constexpr (_S_store_size)
- _M_size._M_size += __detail::__to_unsigned_like(-__n);
- return *this;
- }
-
- __glibcxx_assert(__n >= 0);
- auto __d = __n - ranges::advance(_M_begin, __n, _M_end);
- if constexpr (_S_store_size)
- _M_size._M_size -= __detail::__to_unsigned_like(__d);
- return *this;
- }
- };
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- subrange(_It, _Sent) -> subrange<_It, _Sent>;
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- subrange(_It, _Sent,
- __detail::__make_unsigned_like_t<iter_difference_t<_It>>)
- -> subrange<_It, _Sent, subrange_kind::sized>;
-
- template<__detail::__iterator_sentinel_pair _Pr>
- subrange(_Pr)
- -> subrange<tuple_element_t<0, _Pr>, tuple_element_t<1, _Pr>>;
-
- template<__detail::__iterator_sentinel_pair _Pr>
- subrange(_Pr, __detail::__make_unsigned_like_t<iter_difference_t<
- tuple_element_t<0, _Pr>>>)
- -> subrange<tuple_element_t<0, _Pr>, tuple_element_t<1, _Pr>,
- subrange_kind::sized>;
-
- template<borrowed_range _Rng>
- subrange(_Rng&&)
- -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>,
- (sized_range<_Rng>
- || sized_sentinel_for<sentinel_t<_Rng>, iterator_t<_Rng>>)
- ? subrange_kind::sized : subrange_kind::unsized>;
-
- template<borrowed_range _Rng>
- subrange(_Rng&&,
- __detail::__make_unsigned_like_t<range_difference_t<_Rng>>)
- -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>, subrange_kind::sized>;
-
- template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
- requires (_Num < 2)
- constexpr auto
- get(const subrange<_It, _Sent, _Kind>& __r)
- {
- if constexpr (_Num == 0)
- return __r.begin();
- else
- return __r.end();
- }
-
- template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
- requires (_Num < 2)
- constexpr auto
- get(subrange<_It, _Sent, _Kind>&& __r)
- {
- if constexpr (_Num == 0)
- return __r.begin();
- else
- return __r.end();
- }
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent,
- subrange_kind _Kind>
- inline constexpr bool
- enable_borrowed_range<subrange<_It, _Sent, _Kind>> = true;
-
-} // namespace ranges
-
- using ranges::get;
-
-namespace ranges
-{
- /// Type returned by algorithms instead of a dangling iterator or subrange.
- struct dangling
- {
- constexpr dangling() noexcept = default;
- template<typename... _Args>
- constexpr dangling(_Args&&...) noexcept { }
- };
+ // [range.access] customization point objects
+ // [range.req] range and view concepts
+ // [range.dangling] dangling iterator handling
+ // Defined in <bits/ranges_base.h>
- template<range _Range>
- using borrowed_iterator_t = conditional_t<borrowed_range<_Range>,
- iterator_t<_Range>,
- dangling>;
+ // [view.interface] View interface
+ // [range.subrange] Sub-ranges
+ // Defined in <bits/ranges_util.h>
- template<range _Range>
- using borrowed_subrange_t = conditional_t<borrowed_range<_Range>,
- subrange<iterator_t<_Range>>,
- dangling>;
+ // C++20 24.6 [range.factories] Range factories
+ /// A view that contains no elements.
template<typename _Tp> requires is_object_v<_Tp>
class empty_view
: public view_interface<empty_view<_Tp>>
istream_view(basic_istream<_CharT, _Traits>& __s)
{ return basic_istream_view<_Val, _CharT, _Traits>{__s}; }
+ // C++20 24.7 [range.adaptors] Range adaptors
+
namespace __detail
{
struct _Empty { };
#include <type_traits>
#include <array>
#include <bits/stl_iterator.h>
-#include <bits/range_access.h>
+#include <bits/ranges_base.h>
#if __cpp_lib_concepts
namespace std _GLIBCXX_VISIBILITY(default)
#include <bits/char_traits.h>
#include <bits/functional_hash.h>
#include <bits/range_access.h>
+#include <bits/ranges_base.h>
#include <bits/ostream_insert.h>
#include <ext/numeric_traits.h>
#include <iterator>
#include <algorithm>
#include <vector>
+#include <ranges>
#include <testsuite_hooks.h>
namespace ranges = std::ranges;
#include <iterator>
#include <algorithm>
#include <deque>
+#include <ranges>
#include <testsuite_hooks.h>
namespace ranges = std::ranges;