|
- /// \file
- // Range v3 library
- //
- // Copyright Eric Niebler 2013-present
- //
- // Use, modification and distribution is subject to the
- // Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // Project home: https://github.com/ericniebler/range-v3
- //
-
- #ifndef RANGES_V3_ITERATOR_CONCEPTS_HPP
- #define RANGES_V3_ITERATOR_CONCEPTS_HPP
-
- #include <iterator>
- #include <type_traits>
-
- #include <meta/meta.hpp>
-
- #include <concepts/concepts.hpp>
-
- #include <range/v3/range_fwd.hpp>
-
- #include <range/v3/functional/comparisons.hpp>
- #include <range/v3/functional/concepts.hpp>
- #include <range/v3/functional/identity.hpp>
- #include <range/v3/functional/invoke.hpp>
- #include <range/v3/iterator/access.hpp>
- #include <range/v3/iterator/traits.hpp>
-
- #ifdef _GLIBCXX_DEBUG
- #include <debug/safe_iterator.h>
- #endif
-
- namespace ranges
- {
- /// \addtogroup group-iterator
- /// @{
-
- /// \cond
- namespace detail
- {
- template<typename I>
- using iter_traits_t = if_then_t<is_std_iterator_traits_specialized_v<I>,
- std::iterator_traits<I>, I>;
-
- #if defined(_GLIBCXX_DEBUG)
- template<typename I, typename T, typename Seq>
- auto iter_concept_(__gnu_debug::_Safe_iterator<T *, Seq>, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, __gnu_debug::_Safe_iterator<T *, Seq>>);
- #endif
- #if defined(__GLIBCXX__)
- template<typename I, typename T, typename Seq>
- auto iter_concept_(__gnu_cxx::__normal_iterator<T *, Seq>, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, __gnu_cxx::__normal_iterator<T *, Seq>>);
- #endif
- #if defined(_LIBCPP_VERSION)
- template<typename I, typename T>
- auto iter_concept_(std::__wrap_iter<T *>, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, std::__wrap_iter<T *>>);
- #endif
- #if defined(_MSVC_STL_VERSION)
- template<typename I>
- auto iter_concept_(I, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, class I::_Array_iterator>);
- template<typename I>
- auto iter_concept_(I, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, class I::_Array_const_iterator>);
- template<typename I>
- auto iter_concept_(I, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, class I::_Vector_iterator>);
- template<typename I>
- auto iter_concept_(I, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, class I::_Vector_const_iterator>);
- template<typename I>
- auto iter_concept_(I, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, class I::_String_iterator>);
- template<typename I>
- auto iter_concept_(I, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, class I::_String_const_iterator>);
- template<typename I>
- auto iter_concept_(I, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, class I::_String_view_iterator>);
- #endif
- template<typename I, typename T>
- auto iter_concept_(T *, priority_tag<3>)
- -> CPP_ret(ranges::contiguous_iterator_tag)( //
- requires same_as<I, T *>);
- template<typename I>
- auto iter_concept_(I, priority_tag<2>) ->
- typename iter_traits_t<I>::iterator_concept;
- template<typename I>
- auto iter_concept_(I, priority_tag<1>) ->
- typename iter_traits_t<I>::iterator_category;
- template<typename I>
- auto iter_concept_(I, priority_tag<0>)
- -> enable_if_t<!is_std_iterator_traits_specialized_v<I>,
- std::random_access_iterator_tag>;
-
- template<typename I>
- using iter_concept_t =
- decltype(iter_concept_<I>(std::declval<I>(), priority_tag<3>{}));
-
- using ::concepts::detail::weakly_equality_comparable_with_;
- } // namespace detail
- /// \endcond
-
- // clang-format off
- CPP_def
- (
- template(typename I)
- concept readable,
- common_reference_with<iter_reference_t<I> &&,
- iter_value_t<std::remove_reference_t<I>> &> &&
- common_reference_with<iter_reference_t<I> &&,
- iter_rvalue_reference_t<I> &&> &&
- common_reference_with<iter_rvalue_reference_t<I> &&,
- iter_value_t<std::remove_reference_t<I>> const &>
- );
-
- CPP_def
- (
- template(typename Out, typename T)
- concept writable,
- requires (Out &&o, T &&t)
- (
- *o = static_cast<T &&>(t),
- *((Out &&) o) = static_cast<T &&>(t),
- const_cast<iter_reference_t<Out> const &&>(*o) = static_cast<T &&>(t),
- const_cast<iter_reference_t<Out> const &&>(*((Out &&) o)) =
- static_cast<T &&>(t)
- )
- );
- // clang-format on
-
- /// \cond
- namespace detail
- {
- template<typename D>
- RANGES_INLINE_VAR constexpr bool _is_integer_like_ = std::is_integral<D>::value;
-
- // clang-format off
- CPP_def
- (
- template(typename D)
- concept integer_like_,
- _is_integer_like_<D>
- // TODO additional syntactic and semantic requirements
- );
-
- #ifdef RANGES_WORKAROUND_MSVC_792338
- CPP_def
- (
- template(typename D)
- concept signed_integer_like_,
- concepts::type<decltype(std::integral_constant<bool, (D(-1) < D(0))>{})> &&
- std::integral_constant<bool, (D(-1) < D(0))>::value
- );
- #else // ^^^ workaround / no workaround vvv
- CPP_def
- (
- template(typename D)
- concept signed_integer_like_,
- integer_like_<D> &&
- concepts::type<std::integral_constant<bool, (D(-1) < D(0))>> &&
- std::integral_constant<bool, (D(-1) < D(0))>::value
- );
- #endif // RANGES_WORKAROUND_MSVC_792338
- // clang-format on
- } // namespace detail
- /// \endcond
-
- // clang-format off
- CPP_def
- (
- template(typename I)
- concept weakly_incrementable,
- requires (I i)
- (
- ++i,
- i++,
- concepts::requires_<same_as<I&, decltype(++i)>>
- ) &&
- concepts::type<iter_difference_t<I>> &&
- detail::signed_integer_like_<iter_difference_t<I>> &&
- semiregular<I>
- );
-
- CPP_def
- (
- template(typename I)
- concept incrementable,
- requires (I i)
- (
- concepts::requires_<same_as<I, decltype(i++)>>
- ) &&
- regular<I> && weakly_incrementable<I>
- );
-
- CPP_def
- (
- template(typename I)
- concept input_or_output_iterator,
- requires (I i)
- (
- *i
- ) &&
- weakly_incrementable<I>
- );
-
- CPP_def
- (
- template(typename S, typename I)
- concept sentinel_for,
- semiregular<S> && input_or_output_iterator<I> &&
- detail::weakly_equality_comparable_with_<S, I>
- );
-
- CPP_def
- (
- template(typename S, typename I)
- concept sized_sentinel_for,
- requires (S const &s, I const &i)
- (
- s - i,
- i - s,
- concepts::requires_<same_as<iter_difference_t<I>, decltype(s - i)>>,
- concepts::requires_<same_as<iter_difference_t<I>, decltype(i - s)>>
- ) &&
- // Short-circuit the test for sentinel_for if we're emulating concepts:
- (!defer::is_true<disable_sized_sentinel<meta::_t<std::remove_cv<S>>, meta::_t<std::remove_cv<I>>>> &&
- defer::sentinel_for<S, I>)
- );
-
- CPP_def
- (
- template(typename Out, typename T)
- concept output_iterator,
- requires (Out o, T &&t)
- (
- *o++ = static_cast<T &&>(t)
- ) &&
- input_or_output_iterator<Out> && writable<Out, T>
- );
-
- CPP_def
- (
- template(typename I)
- concept input_iterator,
- input_or_output_iterator<I> && readable<I> &&
- derived_from<detail::iter_concept_t<I>, std::input_iterator_tag>
- );
-
- CPP_def
- (
- template(typename I)
- concept forward_iterator,
- input_iterator<I> && incrementable<I> &&
- sentinel_for<I, I> &&
- derived_from<detail::iter_concept_t<I>, std::forward_iterator_tag>
- );
-
- CPP_def
- (
- template(typename I)
- concept bidirectional_iterator,
- requires (I i)
- (
- --i,
- i--,
- concepts::requires_<same_as<I&, decltype(--i)>>,
- concepts::requires_<same_as<I, decltype(i--)>>
- ) &&
- forward_iterator<I> &&
- derived_from<detail::iter_concept_t<I>, std::bidirectional_iterator_tag>
- );
-
- CPP_def
- (
- template(typename I)
- concept random_access_iterator,
- requires (I i, iter_difference_t<I> n)
- (
- i + n,
- n + i,
- i - n,
- i += n,
- i -= n,
- concepts::requires_<same_as<decltype(i + n), I>>,
- concepts::requires_<same_as<decltype(n + i), I>>,
- concepts::requires_<same_as<decltype(i - n), I>>,
- concepts::requires_<same_as<decltype(i += n), I&>>,
- concepts::requires_<same_as<decltype(i -= n), I&>>,
- concepts::requires_<same_as<decltype(i[n]), iter_reference_t<I>>>
- ) &&
- bidirectional_iterator<I> &&
- totally_ordered<I> &&
- sized_sentinel_for<I, I> &&
- derived_from<detail::iter_concept_t<I>, std::random_access_iterator_tag>
- );
-
- CPP_def
- (
- template(typename I)
- concept contiguous_iterator,
- random_access_iterator<I> &&
- derived_from<detail::iter_concept_t<I>, ranges::contiguous_iterator_tag> &&
- std::is_lvalue_reference<iter_reference_t<I>>::value &&
- same_as<iter_value_t<I>, uncvref_t<iter_reference_t<I>>>
- );
- // clang-format on
-
- /////////////////////////////////////////////////////////////////////////////////////
- // iterator_tag_of
- template<typename T>
- using iterator_tag_of = concepts::tag_of<
- meta::list<contiguous_iterator_concept, random_access_iterator_concept,
- bidirectional_iterator_concept, forward_iterator_concept,
- input_iterator_concept>,
- T>;
-
- /// \cond
- namespace detail
- {
- template<typename, bool>
- struct iterator_category_
- {};
-
- template<typename I>
- struct iterator_category_<I, true>
- {
- private:
- static std::input_iterator_tag test(detail::input_iterator_tag_);
- static std::forward_iterator_tag test(detail::forward_iterator_tag_);
- static std::bidirectional_iterator_tag test(
- detail::bidirectional_iterator_tag_);
- static std::random_access_iterator_tag test(
- detail::random_access_iterator_tag_);
- static ranges::contiguous_iterator_tag test(detail::contiguous_iterator_tag_);
-
- public:
- using type = decltype(iterator_category_::test(iterator_tag_of<I>{}));
- };
-
- template<typename T>
- using iterator_category =
- iterator_category_<meta::_t<std::remove_const<T>>,
- (bool)input_iterator<meta::_t<std::remove_const<T>>>>;
- } // namespace detail
- /// \endcond
-
- /// \cond
- // Generally useful to know if an iterator is single-pass or not:
- // clang-format off
- CPP_def
- (
- template(typename I)
- concept single_pass_iterator_,
- input_or_output_iterator<I> && !forward_iterator<I>
- );
- // clang-format on
- /// \endcond
-
- ////////////////////////////////////////////////////////////////////////////////////////////
- // indirect_result_t
- template<typename Fun, typename... Is>
- using indirect_result_t =
- detail::enable_if_t<(bool)and_v<(bool)readable<Is>...>,
- invoke_result_t<Fun, iter_reference_t<Is>...>>;
-
- /// \cond
- namespace detail
- {
- // clang-format off
- CPP_def
- (
- template(typename T1, typename T2, typename T3, typename T4)
- concept common_reference_with_4_,
- concepts::type<common_reference_t<T1, T2, T3, T4>> &&
- convertible_to<T1, common_reference_t<T1, T2, T3, T4>> &&
- convertible_to<T2, common_reference_t<T1, T2, T3, T4>> &&
- convertible_to<T3, common_reference_t<T1, T2, T3, T4>> &&
- convertible_to<T4, common_reference_t<T1, T2, T3, T4>>
- // axiom: all permutations of T1,T2,T3,T4 have the same
- // common reference type.
- );
-
- CPP_def
- (
- template(typename F, typename I)
- concept indirectly_unary_invocable_,
- readable<I> &&
- invocable<F &, iter_value_t<I> &> &&
- invocable<F &, iter_reference_t<I>> &&
- invocable<F &, iter_common_reference_t<I>> &&
- common_reference_with<
- invoke_result_t<F &, iter_value_t<I> &>,
- invoke_result_t<F &, iter_reference_t<I>>>
- );
- // clang-format on
- } // namespace detail
- /// \endcond
-
- // clang-format off
- CPP_def
- (
- template(typename F, typename I)
- concept indirectly_unary_invocable,
- detail::indirectly_unary_invocable_<F, I> &&
- copy_constructible<F>
- );
-
- CPP_def
- (
- template(typename F, typename I)
- concept indirectly_regular_unary_invocable,
- readable<I> &&
- copy_constructible<F> &&
- regular_invocable<F &, iter_value_t<I> &> &&
- regular_invocable<F &, iter_reference_t<I>> &&
- regular_invocable<F &, iter_common_reference_t<I>> &&
- common_reference_with<
- invoke_result_t<F &, iter_value_t<I> &>,
- invoke_result_t<F &, iter_reference_t<I>>>
- );
-
- /// \cond
- // Non-standard indirect invocable concepts
- CPP_def
- (
- template(typename F, typename I1, typename I2)
- concept indirectly_binary_invocable_,
- readable<I1> && readable<I2> &&
- copy_constructible<F> &&
- invocable<F &, iter_value_t<I1> &, iter_value_t<I2> &> &&
- invocable<F &, iter_value_t<I1> &, iter_reference_t<I2>> &&
- invocable<F &, iter_reference_t<I1>, iter_value_t<I2> &> &&
- invocable<F &, iter_reference_t<I1>, iter_reference_t<I2>> &&
- invocable<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>> &&
- detail::common_reference_with_4_<
- invoke_result_t<F &, iter_value_t<I1> &, iter_value_t<I2> &>,
- invoke_result_t<F &, iter_value_t<I1> &, iter_reference_t<I2>>,
- invoke_result_t<F &, iter_reference_t<I1>, iter_value_t<I2> &>,
- invoke_result_t<F &, iter_reference_t<I1>, iter_reference_t<I2>>>
- );
-
- CPP_def
- (
- template(typename F, typename I1, typename I2)
- concept indirectly_regular_binary_invocable_,
- readable<I1> && readable<I2> &&
- copy_constructible<F> &&
- regular_invocable<F &, iter_value_t<I1> &, iter_value_t<I2> &> &&
- regular_invocable<F &, iter_value_t<I1> &, iter_reference_t<I2>> &&
- regular_invocable<F &, iter_reference_t<I1>, iter_value_t<I2> &> &&
- regular_invocable<F &, iter_reference_t<I1>, iter_reference_t<I2>> &&
- regular_invocable<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>> &&
- detail::common_reference_with_4_<
- invoke_result_t<F &, iter_value_t<I1> &, iter_value_t<I2> &>,
- invoke_result_t<F &, iter_value_t<I1> &, iter_reference_t<I2>>,
- invoke_result_t<F &, iter_reference_t<I1>, iter_value_t<I2> &>,
- invoke_result_t<F &, iter_reference_t<I1>, iter_reference_t<I2>>>
- );
- /// \endcond
-
- CPP_def
- (
- template(typename F, typename I)
- concept indirect_unary_predicate,
- readable<I> &&
- copy_constructible<F> &&
- predicate<F &, iter_value_t<I> &> &&
- predicate<F &, iter_reference_t<I>> &&
- predicate<F &, iter_common_reference_t<I>>
- );
-
- CPP_def
- (
- template(typename F, typename I1, typename I2)
- concept indirect_binary_predicate_,
- readable<I1> && readable<I2> &&
- copy_constructible<F> &&
- predicate<F &, iter_value_t<I1> &, iter_value_t<I2> &> &&
- predicate<F &, iter_value_t<I1> &, iter_reference_t<I2>> &&
- predicate<F &, iter_reference_t<I1>, iter_value_t<I2> &> &&
- predicate<F &, iter_reference_t<I1>, iter_reference_t<I2>> &&
- predicate<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
- );
-
- CPP_def
- (
- template(typename F, typename I1, typename I2 = I1)
- (concept indirect_relation)(F, I1, I2),
- readable<I1> && readable<I2> &&
- copy_constructible<F> &&
- relation<F &, iter_value_t<I1> &, iter_value_t<I2> &> &&
- relation<F &, iter_value_t<I1> &, iter_reference_t<I2>> &&
- relation<F &, iter_reference_t<I1>, iter_value_t<I2> &> &&
- relation<F &, iter_reference_t<I1>, iter_reference_t<I2>> &&
- relation<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
- );
-
- CPP_def
- (
- template(class F, class I1, class I2 = I1)
- (concept indirect_strict_weak_order)(F, I1, I2),
- readable<I1> && readable<I2> &&
- copy_constructible<F> &&
- strict_weak_order<F &, iter_value_t<I1> &, iter_value_t<I2> &> &&
- strict_weak_order<F &, iter_value_t<I1> &, iter_reference_t<I2>> &&
- strict_weak_order<F &, iter_reference_t<I1>, iter_value_t<I2> &> &&
- strict_weak_order<F &, iter_reference_t<I1>, iter_reference_t<I2>> &&
- strict_weak_order<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
- );
- // clang-format on
-
- ////////////////////////////////////////////////////////////////////////////////////////////
- // projected struct, for "projecting" a readable with a unary callable
- /// \cond
- namespace detail
- {
- RANGES_DIAGNOSTIC_PUSH
- RANGES_DIAGNOSTIC_IGNORE_UNDEFINED_INTERNAL
- template<typename I, typename Proj>
- struct projected_
- {
- using reference = indirect_result_t<Proj &, I>;
- using value_type = uncvref_t<reference>;
- reference operator*() const;
- };
- RANGES_DIAGNOSTIC_POP
-
- template<typename Proj>
- struct select_projected_
- {
- template<typename I>
- using apply =
- detail::enable_if_t<(bool)indirectly_regular_unary_invocable<Proj, I>,
- detail::projected_<I, Proj>>;
- };
-
- template<>
- struct select_projected_<identity>
- {
- template<typename I>
- using apply = detail::enable_if_t<(bool)readable<I>, I>;
- };
- } // namespace detail
- /// \endcond
-
- template<typename I, typename Proj>
- using projected = typename detail::select_projected_<Proj>::template apply<I>;
-
- template<typename I, typename Proj>
- struct incrementable_traits<detail::projected_<I, Proj>> : incrementable_traits<I>
- {};
-
- // clang-format off
- CPP_def
- (
- template(typename I, typename O)
- concept indirectly_movable,
- readable<I> && writable<O, iter_rvalue_reference_t<I>>
- );
-
- CPP_def
- (
- template(typename I, typename O)
- concept indirectly_movable_storable,
- indirectly_movable<I, O> &&
- writable<O, iter_value_t<I>> &&
- movable<iter_value_t<I>> &&
- constructible_from<iter_value_t<I>, iter_rvalue_reference_t<I>> &&
- assignable_from<iter_value_t<I> &, iter_rvalue_reference_t<I>>
- );
-
- CPP_def
- (
- template(typename I, typename O)
- concept indirectly_copyable,
- readable<I> &&
- writable<O, iter_reference_t<I>>
- );
-
- CPP_def
- (
- template(typename I, typename O)
- concept indirectly_copyable_storable,
- indirectly_copyable<I, O> &&
- writable<O, iter_value_t<I> const &> &&
- copyable<iter_value_t<I>> &&
- constructible_from<iter_value_t<I>, iter_reference_t<I>> &&
- assignable_from<iter_value_t<I> &, iter_reference_t<I>>
- );
-
- CPP_def
- (
- template(typename I1, typename I2 = I1)
- (concept indirectly_swappable)(I1, I2),
- requires (I1 && i1, I2 && i2)
- (
- ranges::iter_swap((I1 &&) i1, (I2 &&) i2),
- ranges::iter_swap((I1 &&) i1, (I1 &&) i1),
- ranges::iter_swap((I2 &&) i2, (I2 &&) i2),
- ranges::iter_swap((I2 &&) i2, (I1 &&) i1)
- ) &&
- readable<I1> && readable<I2>
- );
-
- CPP_def
- (
- template(typename I1, typename I2, typename C,
- typename P1 = identity, typename P2 = identity)
- (concept indirectly_comparable)(I1, I2, C, P1, P2),
- indirect_relation<C, projected<I1, P1>, projected<I2, P2>>
- );
-
- ////////////////////////////////////////////////////////////////////////////////////////////
- // Composite concepts for use defining algorithms:
- CPP_def
- (
- template(typename I)
- concept permutable,
- forward_iterator<I> &&
- indirectly_swappable<I, I> &&
- indirectly_movable_storable<I, I>
- );
-
- CPP_def
- (
- template(typename I0, typename I1, typename Out, typename C = less,
- typename P0 = identity, typename P1 = identity)
- (concept mergeable)(I0, I1, Out, C, P0, P1),
- input_iterator<I0> &&
- input_iterator<I1> &&
- weakly_incrementable<Out> &&
- indirectly_copyable<I0, Out> &&
- indirectly_copyable<I1, Out> &&
- indirect_strict_weak_order<C, projected<I0, P0>, projected<I1, P1>>
- );
-
- CPP_def
- (
- template(typename I, typename C = less, typename P = identity)
- (concept sortable)(I, C, P),
- permutable<I> &&
- indirect_strict_weak_order<C, projected<I, P>>
- );
- // clang-format on
-
- using sentinel_tag = concepts::tag<sentinel_for_concept>;
- using sized_sentinel_tag = concepts::tag<sized_sentinel_for_concept, sentinel_tag>;
-
- template<typename S, typename I>
- using sentinel_tag_of =
- concepts::tag_of<meta::list<sized_sentinel_for_concept, sentinel_for_concept>, S,
- I>;
-
- // Deprecated things:
- /// \cond
- template<typename I>
- using iterator_category RANGES_DEPRECATED(
- "iterator_category is deprecated. Use the iterator concepts instead") =
- detail::iterator_category<I>;
-
- template<typename I>
- using iterator_category_t RANGES_DEPRECATED(
- "iterator_category_t is deprecated. Use the iterator concepts instead") =
- meta::_t<detail::iterator_category<I>>;
-
- template<typename Fun, typename... Is>
- using indirect_invoke_result_t RANGES_DEPRECATED(
- "Please switch to indirect_result_t") = indirect_result_t<Fun, Is...>;
-
- template<typename Fun, typename... Is>
- struct RANGES_DEPRECATED("Please switch to indirect_result_t") indirect_invoke_result
- : meta::defer<indirect_result_t, Fun, Is...>
- {};
-
- template<typename Sig>
- struct indirect_result_of
- {};
-
- template<typename Fun, typename... Is>
- struct RANGES_DEPRECATED("Please switch to indirect_result_t")
- indirect_result_of<Fun(Is...)> : meta::defer<indirect_result_t, Fun, Is...>
- {};
-
- template<typename Sig>
- using indirect_result_of_t RANGES_DEPRECATED("Please switch to indirect_result_t") =
- meta::_t<indirect_result_of<Sig>>;
- /// \endcond
-
- namespace cpp20
- {
- using ranges::bidirectional_iterator;
- using ranges::contiguous_iterator;
- using ranges::forward_iterator;
- using ranges::incrementable;
- using ranges::indirect_relation;
- using ranges::indirect_result_t;
- using ranges::indirect_strict_weak_order;
- using ranges::indirect_unary_predicate;
- using ranges::indirectly_comparable;
- using ranges::indirectly_copyable;
- using ranges::indirectly_copyable_storable;
- using ranges::indirectly_movable;
- using ranges::indirectly_movable_storable;
- using ranges::indirectly_regular_unary_invocable;
- using ranges::indirectly_swappable;
- using ranges::indirectly_unary_invocable;
- using ranges::input_iterator;
- using ranges::input_or_output_iterator;
- using ranges::mergeable;
- using ranges::output_iterator;
- using ranges::permutable;
- using ranges::projected;
- using ranges::random_access_iterator;
- using ranges::readable;
- using ranges::sentinel_for;
- using ranges::sortable;
- using ranges::weakly_incrementable;
- using ranges::writable;
- } // namespace cpp20
- /// @}
- } // namespace ranges
-
- #ifdef _GLIBCXX_DEBUG
- // HACKHACK: workaround underconstrained operator- for libstdc++ debug iterator wrapper
- // by intentionally creating an ambiguity when the wrapped types don't support the
- // necessary operation.
- namespace __gnu_debug
- {
- template<typename I1, typename I2, typename Seq>
- auto operator-(_Safe_iterator<I1, Seq> const &, _Safe_iterator<I2, Seq> const &)
- -> CPP_ret(void)( //
- requires(!::ranges::sized_sentinel_for<I1, I2>)) = delete;
-
- template<typename I1, typename Seq>
- auto operator-(_Safe_iterator<I1, Seq> const &, _Safe_iterator<I1, Seq> const &)
- -> CPP_ret(void)( //
- requires(!::ranges::sized_sentinel_for<I1, I1>)) = delete;
- } // namespace __gnu_debug
- #endif
-
- #if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 3900)
- // HACKHACK: workaround libc++ (https://llvm.org/bugs/show_bug.cgi?id=28421)
- // and libstdc++ (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71771)
- // underconstrained operator- for reverse_iterator by disabling sized_sentinel_for
- // when the base iterators do not model sized_sentinel_for.
- namespace ranges
- {
- template<typename S, typename I>
- /*inline*/ constexpr bool
- disable_sized_sentinel<std::reverse_iterator<S>, std::reverse_iterator<I>> =
- !static_cast<bool>(sized_sentinel_for<I, S>);
- }
- #endif // defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 3900)
-
- #endif // RANGES_V3_ITERATOR_CONCEPTS_HPP
|