/// \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 #include #include #include #include #include #include #include #include #include #include #ifdef _GLIBCXX_DEBUG #include #endif #include namespace ranges { /// \addtogroup group-iterator-concepts /// @{ /// \cond namespace detail { template using iter_traits_t = meta::conditional_t, std::iterator_traits, I>; #if defined(_GLIBCXX_DEBUG) template(typename I, typename T, typename Seq)( requires same_as>) auto iter_concept_(__gnu_debug::_Safe_iterator, priority_tag<3>) -> ranges::contiguous_iterator_tag; #endif #if defined(__GLIBCXX__) template(typename I, typename T, typename Seq)( requires same_as>) auto iter_concept_(__gnu_cxx::__normal_iterator, priority_tag<3>) -> ranges::contiguous_iterator_tag; #endif #if defined(_LIBCPP_VERSION) template(typename I, typename T)( requires same_as>) auto iter_concept_(std::__wrap_iter, priority_tag<3>) -> ranges::contiguous_iterator_tag; #endif #if defined(_MSVC_STL_VERSION) || defined(_IS_WRS) template(typename I)( requires same_as) auto iter_concept_(I, priority_tag<3>) -> ranges::contiguous_iterator_tag; template(typename I)( requires same_as) auto iter_concept_(I, priority_tag<3>) -> ranges::contiguous_iterator_tag; template(typename I)( requires same_as) auto iter_concept_(I, priority_tag<3>) -> ranges::contiguous_iterator_tag; template(typename I)( requires same_as) auto iter_concept_(I, priority_tag<3>) -> ranges::contiguous_iterator_tag; template(typename I)( requires same_as) auto iter_concept_(I, priority_tag<3>) -> ranges::contiguous_iterator_tag; template(typename I)( requires same_as) auto iter_concept_(I, priority_tag<3>) -> ranges::contiguous_iterator_tag; template(typename I)( requires same_as) auto iter_concept_(I, priority_tag<3>) -> ranges::contiguous_iterator_tag; #endif template(typename I, typename T)( requires same_as) auto iter_concept_(T *, priority_tag<3>) -> ranges::contiguous_iterator_tag; template auto iter_concept_(I, priority_tag<2>) -> typename iter_traits_t::iterator_concept; template auto iter_concept_(I, priority_tag<1>) -> typename iter_traits_t::iterator_category; template auto iter_concept_(I, priority_tag<0>) -> enable_if_t, std::random_access_iterator_tag>; template using iter_concept_t = decltype(iter_concept_(std::declval(), priority_tag<3>{})); using ::concepts::detail::weakly_equality_comparable_with_; template using readable_types_t = meta::list, iter_reference_t, iter_rvalue_reference_t>; } // namespace detail /// \endcond // clang-format off /// \concept readable_ /// \brief The \c readable_ concept template(typename I)( concept (readable_)(I), // requires (I const i) // ( // { *i } -> same_as>; // { iter_move(i) } -> same_as>; // ) && same_as, iter_reference_t> AND same_as, iter_rvalue_reference_t> AND common_reference_with &&, iter_value_t &> AND common_reference_with &&, iter_rvalue_reference_t &&> AND common_reference_with &&, iter_value_t const &> ); /// \concept indirectly_readable /// \brief The \c indirectly_readable concept template CPP_concept indirectly_readable = // CPP_concept_ref(ranges::readable_, uncvref_t); template RANGES_DEPRECATED("Please use ranges::indirectly_readable instead") RANGES_INLINE_VAR constexpr bool readable = // indirectly_readable; /// \concept writable_ /// \brief The \c writable_ concept template CPP_requires(writable_, requires(O && o, T && t) // ( *o = (T &&) t, *(O &&) o = (T &&) t, const_cast const &&>(*o) = (T &&) t, const_cast const &&>(*(O &&) o) = (T &&) t )); /// \concept indirectly_writable /// \brief The \c indirectly_writable concept template CPP_concept indirectly_writable = // CPP_requires_ref(ranges::writable_, O, T); template RANGES_DEPRECATED("Please use ranges::indirectly_writable instead") RANGES_INLINE_VAR constexpr bool writable = // indirectly_writable; // clang-format on /// \cond namespace detail { #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17 template inline constexpr bool _is_integer_like_ = std::is_integral::value; #else template constexpr bool _is_integer_like_ = std::is_integral::value; #endif // gcc10 uses for std::ranges::range_difference_t< // std::ranges::iota_view> == __int128 #if __SIZEOF_INT128__ __extension__ typedef __int128 int128_t; #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17 template<> inline constexpr bool _is_integer_like_ = true; #else template constexpr bool _is_integer_like_ = true; #endif #endif // __SIZEOF_INT128__ // clang-format off /// \concept integer_like_ /// \brief The \c integer_like_ concept template CPP_concept integer_like_ = _is_integer_like_; // TODO additional syntactic and semantic requirements #ifdef RANGES_WORKAROUND_MSVC_792338 template constexpr bool _is_signed_(D *) { return Signed; } constexpr bool _is_signed_(void *) { return false; } /// \concept signed_integer_like_ /// \brief The \c signed_integer_like_ concept template CPP_concept signed_integer_like_ = integer_like_ && detail::_is_signed_((D*) nullptr); #else // ^^^ workaround / no workaround vvv /// \concept signed_integer_like_impl_ /// \brief The \c signed_integer_like_impl_ concept template(typename D)( concept (signed_integer_like_impl_)(D), integer_like_ AND concepts::type> AND std::integral_constant::value ); /// \concept signed_integer_like_ /// \brief The \c signed_integer_like_ concept template CPP_concept signed_integer_like_ = integer_like_ && CPP_concept_ref(detail::signed_integer_like_impl_, D); #endif // RANGES_WORKAROUND_MSVC_792338 // clang-format on } // namespace detail /// \endcond // clang-format off /// \concept weakly_incrementable_ /// \brief The \c weakly_incrementable_ concept template CPP_requires(weakly_incrementable_, requires(I i) // ( ++i, i++, concepts::requires_> )); /// \concept weakly_incrementable_ /// \brief The \c weakly_incrementable_ concept template(typename I)( concept (weakly_incrementable_)(I), concepts::type> AND detail::signed_integer_like_>); /// \concept weakly_incrementable /// \brief The \c weakly_incrementable concept template CPP_concept weakly_incrementable = copyable && CPP_requires_ref(ranges::weakly_incrementable_, I) && CPP_concept_ref(ranges::weakly_incrementable_, I); /// \concept incrementable_ /// \brief The \c incrementable_ concept template CPP_requires(incrementable_, requires(I i) // ( concepts::requires_> )); /// \concept incrementable /// \brief The \c incrementable concept template CPP_concept incrementable = regular && weakly_incrementable && CPP_requires_ref(ranges::incrementable_, I); /// \concept input_or_output_iterator_ /// \brief The \c input_or_output_iterator_ concept template(typename I)( concept (input_or_output_iterator_)(I), detail::dereferenceable_ ); /// \concept input_or_output_iterator /// \brief The \c input_or_output_iterator concept template CPP_concept input_or_output_iterator = weakly_incrementable && CPP_concept_ref(ranges::input_or_output_iterator_, I); /// \concept sentinel_for /// \brief The \c sentinel_for concept template CPP_concept sentinel_for = semiregular && input_or_output_iterator && detail::weakly_equality_comparable_with_; /// \concept sized_sentinel_for_ /// \brief The \c sized_sentinel_for_ concept template CPP_requires(sized_sentinel_for_, requires(S const & s, I const & i) // ( s - i, i - s, concepts::requires_, decltype(s - i)>>, concepts::requires_, decltype(i - s)>> )); /// \concept sized_sentinel_for_ /// \brief The \c sized_sentinel_for_ concept template(typename S, typename I)( concept (sized_sentinel_for_)(S, I), (!disable_sized_sentinel, std::remove_cv_t>) AND sentinel_for); /// \concept sized_sentinel_for /// \brief The \c sized_sentinel_for concept template CPP_concept sized_sentinel_for = CPP_concept_ref(sized_sentinel_for_, S, I) && CPP_requires_ref(ranges::sized_sentinel_for_, S, I); /// \concept output_iterator_ /// \brief The \c output_iterator_ concept template CPP_requires(output_iterator_, requires(Out o, T && t) // ( *o++ = (T &&) t )); /// \concept output_iterator /// \brief The \c output_iterator concept template CPP_concept output_iterator = input_or_output_iterator && indirectly_writable && CPP_requires_ref(ranges::output_iterator_, Out, T); /// \concept with_category_ /// \brief The \c with_category_ concept template(typename I, typename Tag)( concept (with_category_)(I, Tag), derived_from, Tag> ); /// \concept input_iterator /// \brief The \c input_iterator concept template CPP_concept input_iterator = input_or_output_iterator && indirectly_readable && CPP_concept_ref(ranges::with_category_, I, std::input_iterator_tag); /// \concept forward_iterator /// \brief The \c forward_iterator concept template CPP_concept forward_iterator = input_iterator && incrementable && sentinel_for && CPP_concept_ref(ranges::with_category_, I, std::forward_iterator_tag); /// \concept bidirectional_iterator_ /// \brief The \c bidirectional_iterator_ concept template CPP_requires(bidirectional_iterator_, requires(I i) // ( --i, i--, concepts::requires_>, concepts::requires_> )); /// \concept bidirectional_iterator /// \brief The \c bidirectional_iterator concept template CPP_concept bidirectional_iterator = forward_iterator && CPP_requires_ref(ranges::bidirectional_iterator_, I) && CPP_concept_ref(ranges::with_category_, I, std::bidirectional_iterator_tag); /// \concept random_access_iterator_ /// \brief The \c random_access_iterator_ concept template CPP_requires(random_access_iterator_, requires(I i, iter_difference_t n) ( i + n, n + i, i - n, i += n, i -= n, concepts::requires_>, concepts::requires_>, concepts::requires_>, concepts::requires_>, concepts::requires_>, concepts::requires_>> )); /// \concept random_access_iterator /// \brief The \c random_access_iterator concept template CPP_concept random_access_iterator = bidirectional_iterator && totally_ordered && sized_sentinel_for && CPP_requires_ref(ranges::random_access_iterator_, I) && CPP_concept_ref(ranges::with_category_, I, std::random_access_iterator_tag); /// \concept contiguous_iterator_ /// \brief The \c contiguous_iterator_ concept template(typename I)( concept (contiguous_iterator_)(I), std::is_lvalue_reference>::value AND same_as, uncvref_t>> AND derived_from, ranges::contiguous_iterator_tag> ); /// \concept contiguous_iterator /// \brief The \c contiguous_iterator concept template CPP_concept contiguous_iterator = random_access_iterator && CPP_concept_ref(ranges::contiguous_iterator_, I); // clang-format on ///////////////////////////////////////////////////////////////////////////////////// // iterator_tag_of template using iterator_tag_of = // std::enable_if_t< // input_iterator, // meta::conditional_t< // contiguous_iterator, // ranges::contiguous_iterator_tag, // meta::conditional_t< // random_access_iterator, // std::random_access_iterator_tag, // meta::conditional_t< // bidirectional_iterator, // std::bidirectional_iterator_tag, // meta::conditional_t< // forward_iterator, // std::forward_iterator_tag, // std::input_iterator_tag>>>>>; /// \cond namespace detail { template struct iterator_category_ {}; template struct iterator_category_ { using type = iterator_tag_of; }; template>> using iterator_category = iterator_category_>; } // namespace detail /// \endcond /// \cond // Generally useful to know if an iterator is single-pass or not: // clang-format off /// \concept single_pass_iterator_ /// \brief The \c single_pass_iterator_ concept template CPP_concept single_pass_iterator_ = input_or_output_iterator && !forward_iterator; // clang-format on /// \endcond ////////////////////////////////////////////////////////////////////////////////////// // indirect_result_t template using indirect_result_t = detail::enable_if_t<(bool)and_v<(bool)indirectly_readable...>, invoke_result_t...>>; /// \cond namespace detail { // clang-format off /// \concept common_reference_with_4_impl_ /// \brief The \c common_reference_with_4_impl_ concept template(typename T1, typename T2, typename T3, typename T4)( concept (common_reference_with_4_impl_)(T1, T2, T3, T4), concepts::type> AND convertible_to> AND convertible_to> AND convertible_to> AND convertible_to> ); /// \concept common_reference_with_4_ /// \brief The \c common_reference_with_4_ concept template CPP_concept common_reference_with_4_ = CPP_concept_ref(detail::common_reference_with_4_impl_, T1, T2, T3, T4); // axiom: all permutations of T1,T2,T3,T4 have the same // common reference type. /// \concept indirectly_unary_invocable_impl_ /// \brief The \c indirectly_unary_invocable_impl_ concept template(typename F, typename I)( concept (indirectly_unary_invocable_impl_)(F, I), invocable &> AND invocable> AND invocable> AND common_reference_with< invoke_result_t &>, invoke_result_t>> ); /// \concept indirectly_unary_invocable_ /// \brief The \c indirectly_unary_invocable_ concept template CPP_concept indirectly_unary_invocable_ = indirectly_readable && CPP_concept_ref(detail::indirectly_unary_invocable_impl_, F, I); // clang-format on } // namespace detail /// \endcond // clang-format off /// \concept indirectly_unary_invocable /// \brief The \c indirectly_unary_invocable concept template CPP_concept indirectly_unary_invocable = detail::indirectly_unary_invocable_ && copy_constructible; /// \concept indirectly_regular_unary_invocable_ /// \brief The \c indirectly_regular_unary_invocable_ concept template(typename F, typename I)( concept (indirectly_regular_unary_invocable_)(F, I), regular_invocable &> AND regular_invocable> AND regular_invocable> AND common_reference_with< invoke_result_t &>, invoke_result_t>> ); /// \concept indirectly_regular_unary_invocable /// \brief The \c indirectly_regular_unary_invocable concept template CPP_concept indirectly_regular_unary_invocable = indirectly_readable && copy_constructible && CPP_concept_ref(ranges::indirectly_regular_unary_invocable_, F, I); /// \cond // Non-standard indirect invocable concepts /// \concept indirectly_binary_invocable_impl_ /// \brief The \c indirectly_binary_invocable_impl_ concept template(typename F, typename I1, typename I2)( concept (indirectly_binary_invocable_impl_)(F, I1, I2), invocable &, iter_value_t &> AND invocable &, iter_reference_t> AND invocable, iter_value_t &> AND invocable, iter_reference_t> AND invocable, iter_common_reference_t> AND detail::common_reference_with_4_< invoke_result_t &, iter_value_t &>, invoke_result_t &, iter_reference_t>, invoke_result_t, iter_value_t &>, invoke_result_t, iter_reference_t>> ); /// \concept indirectly_binary_invocable_ /// \brief The \c indirectly_binary_invocable_ concept template CPP_concept indirectly_binary_invocable_ = indirectly_readable && indirectly_readable && copy_constructible && CPP_concept_ref(ranges::indirectly_binary_invocable_impl_, F, I1, I2); /// \concept indirectly_regular_binary_invocable_impl_ /// \brief The \c indirectly_regular_binary_invocable_impl_ concept template(typename F, typename I1, typename I2)( concept (indirectly_regular_binary_invocable_impl_)(F, I1, I2), regular_invocable &, iter_value_t &> AND regular_invocable &, iter_reference_t> AND regular_invocable, iter_value_t &> AND regular_invocable, iter_reference_t> AND regular_invocable, iter_common_reference_t> AND detail::common_reference_with_4_< invoke_result_t &, iter_value_t &>, invoke_result_t &, iter_reference_t>, invoke_result_t, iter_value_t &>, invoke_result_t, iter_reference_t>> ); /// \concept indirectly_regular_binary_invocable_ /// \brief The \c indirectly_regular_binary_invocable_ concept template CPP_concept indirectly_regular_binary_invocable_ = indirectly_readable && indirectly_readable && copy_constructible && CPP_concept_ref(ranges::indirectly_regular_binary_invocable_impl_, F, I1, I2); /// \endcond /// \concept indirect_unary_predicate_ /// \brief The \c indirect_unary_predicate_ concept template(typename F, typename I)( concept (indirect_unary_predicate_)(F, I), predicate &> AND predicate> AND predicate> ); /// \concept indirect_unary_predicate /// \brief The \c indirect_unary_predicate concept template CPP_concept indirect_unary_predicate = indirectly_readable && copy_constructible && CPP_concept_ref(ranges::indirect_unary_predicate_, F, I); /// \concept indirect_binary_predicate_impl_ /// \brief The \c indirect_binary_predicate_impl_ concept template(typename F, typename I1, typename I2)( concept (indirect_binary_predicate_impl_)(F, I1, I2), predicate &, iter_value_t &> AND predicate &, iter_reference_t> AND predicate, iter_value_t &> AND predicate, iter_reference_t> AND predicate, iter_common_reference_t> ); /// \concept indirect_binary_predicate_ /// \brief The \c indirect_binary_predicate_ concept template CPP_concept indirect_binary_predicate_ = indirectly_readable && indirectly_readable && copy_constructible && CPP_concept_ref(ranges::indirect_binary_predicate_impl_, F, I1, I2); /// \concept indirect_relation_ /// \brief The \c indirect_relation_ concept template(typename F, typename I1, typename I2)( concept (indirect_relation_)(F, I1, I2), relation &, iter_value_t &> AND relation &, iter_reference_t> AND relation, iter_value_t &> AND relation, iter_reference_t> AND relation, iter_common_reference_t> ); /// \concept indirect_relation /// \brief The \c indirect_relation concept template CPP_concept indirect_relation = indirectly_readable && indirectly_readable && copy_constructible && CPP_concept_ref(ranges::indirect_relation_, F, I1, I2); /// \concept indirect_strict_weak_order_ /// \brief The \c indirect_strict_weak_order_ concept template(typename F, typename I1, typename I2)( concept (indirect_strict_weak_order_)(F, I1, I2), strict_weak_order &, iter_value_t &> AND strict_weak_order &, iter_reference_t> AND strict_weak_order, iter_value_t &> AND strict_weak_order, iter_reference_t> AND strict_weak_order, iter_common_reference_t> ); /// \concept indirect_strict_weak_order /// \brief The \c indirect_strict_weak_order concept template CPP_concept indirect_strict_weak_order = indirectly_readable && indirectly_readable && copy_constructible && CPP_concept_ref(ranges::indirect_strict_weak_order_, F, I1, 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 struct projected_ { struct type { using reference = indirect_result_t; using value_type = uncvref_t; reference operator*() const; }; }; RANGES_DIAGNOSTIC_POP template struct select_projected_ { template using apply = meta::_t< detail::enable_if_t< (bool)indirectly_regular_unary_invocable, detail::projected_>>; }; template<> struct select_projected_ { template using apply = detail::enable_if_t<(bool)indirectly_readable, I>; }; } // namespace detail /// \endcond template using projected = typename detail::select_projected_::template apply; template struct incrementable_traits> : incrementable_traits {}; // clang-format off /// \concept indirectly_movable_ /// \brief The \c indirectly_movable_ concept template(typename I, typename O)( concept (indirectly_movable_)(I, O), indirectly_writable> ); /// \concept indirectly_movable /// \brief The \c indirectly_movable concept template CPP_concept indirectly_movable = indirectly_readable && CPP_concept_ref(ranges::indirectly_movable_, I, O); /// \concept indirectly_movable_storable_ /// \brief The \c indirectly_movable_storable_ concept template(typename I, typename O)( concept (indirectly_movable_storable_)(I, O), indirectly_writable> AND movable> AND constructible_from, iter_rvalue_reference_t> AND assignable_from &, iter_rvalue_reference_t> ); /// \concept indirectly_movable_storable /// \brief The \c indirectly_movable_storable concept template CPP_concept indirectly_movable_storable = indirectly_movable && CPP_concept_ref(ranges::indirectly_movable_storable_, I, O); /// \concept indirectly_copyable_ /// \brief The \c indirectly_copyable_ concept template(typename I, typename O)( concept (indirectly_copyable_)(I, O), indirectly_writable> ); /// \concept indirectly_copyable /// \brief The \c indirectly_copyable concept template CPP_concept indirectly_copyable = indirectly_readable && CPP_concept_ref(ranges::indirectly_copyable_, I, O); /// \concept indirectly_copyable_storable_ /// \brief The \c indirectly_copyable_storable_ concept template(typename I, typename O)( concept (indirectly_copyable_storable_)(I, O), indirectly_writable const &> AND copyable> AND constructible_from, iter_reference_t> AND assignable_from &, iter_reference_t> ); /// \concept indirectly_copyable_storable /// \brief The \c indirectly_copyable_storable concept template CPP_concept indirectly_copyable_storable = indirectly_copyable && CPP_concept_ref(ranges::indirectly_copyable_storable_, I, O); /// \concept indirectly_swappable_ /// \brief The \c indirectly_swappable_ concept template CPP_requires(indirectly_swappable_, requires(I1 const i1, I2 const i2) // ( ranges::iter_swap(i1, i2), ranges::iter_swap(i1, i1), ranges::iter_swap(i2, i2), ranges::iter_swap(i2, i1) )); /// \concept indirectly_swappable /// \brief The \c indirectly_swappable concept template CPP_concept indirectly_swappable = indirectly_readable && // indirectly_readable && // CPP_requires_ref(ranges::indirectly_swappable_, I1, I2); /// \concept projected_indirect_relation_ /// \brief The \c projected_indirect_relation_ concept template(typename C, typename I1, typename P1, typename I2, typename P2)( concept (projected_indirect_relation_)(C, I1, P1, I2, P2), indirect_relation, projected> ); /// \concept indirectly_comparable /// \brief The \c indirectly_comparable concept template CPP_concept indirectly_comparable = CPP_concept_ref(ranges::projected_indirect_relation_, C, I1, P1, I2, P2); ////////////////////////////////////////////////////////////////////////////////////// // Composite concepts for use defining algorithms: /// \concept permutable /// \brief The \c permutable concept template CPP_concept permutable = forward_iterator && indirectly_swappable && indirectly_movable_storable; /// \concept projected_indirect_strict_weak_order_ /// \brief The \c projected_indirect_strict_weak_order_ concept template(typename C, typename I1, typename P1, typename I2, typename P2)( concept (projected_indirect_strict_weak_order_)(C, I1, P1, I2, P2), indirect_strict_weak_order, projected> ); template CPP_concept mergeable = input_iterator && input_iterator && weakly_incrementable && indirectly_copyable && indirectly_copyable && CPP_concept_ref(ranges::projected_indirect_strict_weak_order_, C, I1, P1, I2, P2); /// \concept sortable /// \brief The \c sortable concept template CPP_concept sortable = permutable && CPP_concept_ref(ranges::projected_indirect_strict_weak_order_, C, I, P, I, P); // clang-format on struct sentinel_tag {}; struct sized_sentinel_tag : sentinel_tag {}; template using sentinel_tag_of = // std::enable_if_t< // sentinel_for, // meta::conditional_t< // sized_sentinel_for, // sized_sentinel_tag, // sentinel_tag>>; // Deprecated things: /// \cond template using iterator_category RANGES_DEPRECATED( "iterator_category is deprecated. Use the iterator concepts instead") = detail::iterator_category; template using iterator_category_t RANGES_DEPRECATED( "iterator_category_t is deprecated. Use the iterator concepts instead") = meta::_t>; template using indirect_invoke_result_t RANGES_DEPRECATED( "Please switch to indirect_result_t") = indirect_result_t; template struct RANGES_DEPRECATED("Please switch to indirect_result_t") indirect_invoke_result : meta::defer {}; template struct indirect_result_of {}; template struct RANGES_DEPRECATED("Please switch to indirect_result_t") indirect_result_of : meta::defer {}; template using indirect_result_of_t RANGES_DEPRECATED("Please switch to indirect_result_t") = meta::_t>; /// \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_readable; using ranges::indirectly_regular_unary_invocable; using ranges::indirectly_swappable; using ranges::indirectly_unary_invocable; using ranges::indirectly_writable; 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::sentinel_for; using ranges::sized_sentinel_for; using ranges::sortable; using ranges::weakly_incrementable; } // 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)( requires (!::ranges::sized_sentinel_for)) // void operator-(_Safe_iterator const &, _Safe_iterator const &) = delete; template(typename I1, typename Seq)( requires (!::ranges::sized_sentinel_for)) // void operator-(_Safe_iterator const &, _Safe_iterator const &) = 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 /*inline*/ constexpr bool disable_sized_sentinel, std::reverse_iterator> = !static_cast(sized_sentinel_for); } // namespace ranges #endif // defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 3900) #include #endif // RANGES_V3_ITERATOR_CONCEPTS_HPP