Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:26:41

0001 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Eric Niebler 2013-present
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
0012 //
0013 
0014 #ifndef RANGES_V3_ITERATOR_CONCEPTS_HPP
0015 #define RANGES_V3_ITERATOR_CONCEPTS_HPP
0016 
0017 #include <iterator>
0018 #include <type_traits>
0019 
0020 #include <meta/meta.hpp>
0021 
0022 #include <concepts/concepts.hpp>
0023 
0024 #include <range/v3/range_fwd.hpp>
0025 
0026 #include <range/v3/functional/comparisons.hpp>
0027 #include <range/v3/functional/concepts.hpp>
0028 #include <range/v3/functional/identity.hpp>
0029 #include <range/v3/functional/invoke.hpp>
0030 #include <range/v3/iterator/access.hpp>
0031 #include <range/v3/iterator/traits.hpp>
0032 
0033 #ifdef _GLIBCXX_DEBUG
0034 #include <debug/safe_iterator.h>
0035 #endif
0036 
0037 #include <range/v3/detail/prologue.hpp>
0038 
0039 namespace ranges
0040 {
0041     /// \addtogroup group-iterator-concepts
0042     /// @{
0043 
0044     /// \cond
0045     namespace detail
0046     {
0047         template<typename I>
0048         using iter_traits_t = meta::conditional_t<is_std_iterator_traits_specialized_v<I>,
0049                                         std::iterator_traits<I>, I>;
0050 
0051 #if defined(_GLIBCXX_DEBUG)
0052         template(typename I, typename T, typename Seq)(
0053             requires same_as<I, __gnu_debug::_Safe_iterator<T *, Seq>>)
0054         auto iter_concept_(__gnu_debug::_Safe_iterator<T *, Seq>, priority_tag<3>)
0055             -> ranges::contiguous_iterator_tag;
0056 #endif
0057 #if defined(__GLIBCXX__)
0058         template(typename I, typename T, typename Seq)(
0059             requires same_as<I, __gnu_cxx::__normal_iterator<T *, Seq>>)
0060         auto iter_concept_(__gnu_cxx::__normal_iterator<T *, Seq>, priority_tag<3>)
0061             -> ranges::contiguous_iterator_tag;
0062 #endif
0063 #if defined(_LIBCPP_VERSION)
0064         template(typename I, typename T)(
0065             requires same_as<I, std::__wrap_iter<T *>>)
0066         auto iter_concept_(std::__wrap_iter<T *>, priority_tag<3>)
0067             -> ranges::contiguous_iterator_tag;
0068 #endif
0069 #if defined(_MSVC_STL_VERSION) || defined(_IS_WRS)
0070         template(typename I)(
0071             requires same_as<I, class I::_Array_iterator>)
0072         auto iter_concept_(I, priority_tag<3>)
0073             -> ranges::contiguous_iterator_tag;
0074         template(typename I)(
0075             requires same_as<I, class I::_Array_const_iterator>)
0076         auto iter_concept_(I, priority_tag<3>)
0077             -> ranges::contiguous_iterator_tag;
0078         template(typename I)(
0079             requires same_as<I, class I::_Vector_iterator>)
0080         auto iter_concept_(I, priority_tag<3>)
0081             -> ranges::contiguous_iterator_tag;
0082         template(typename I)(
0083             requires same_as<I, class I::_Vector_const_iterator>)
0084         auto iter_concept_(I, priority_tag<3>)
0085             -> ranges::contiguous_iterator_tag;
0086         template(typename I)(
0087             requires same_as<I, class I::_String_iterator>)
0088         auto iter_concept_(I, priority_tag<3>)
0089             -> ranges::contiguous_iterator_tag;
0090         template(typename I)(
0091             requires same_as<I, class I::_String_const_iterator>)
0092         auto iter_concept_(I, priority_tag<3>)
0093             -> ranges::contiguous_iterator_tag;
0094         template(typename I)(
0095             requires same_as<I, class I::_String_view_iterator>)
0096         auto iter_concept_(I, priority_tag<3>)
0097             -> ranges::contiguous_iterator_tag;
0098 #endif
0099         template(typename I, typename T)(
0100             requires same_as<I, T *>)
0101         auto iter_concept_(T *, priority_tag<3>)
0102             -> ranges::contiguous_iterator_tag;
0103         template<typename I>
0104         auto iter_concept_(I, priority_tag<2>) ->
0105             typename iter_traits_t<I>::iterator_concept;
0106         template<typename I>
0107         auto iter_concept_(I, priority_tag<1>) ->
0108             typename iter_traits_t<I>::iterator_category;
0109         template<typename I>
0110         auto iter_concept_(I, priority_tag<0>)
0111             -> enable_if_t<!is_std_iterator_traits_specialized_v<I>,
0112                            std::random_access_iterator_tag>;
0113 
0114         template<typename I>
0115         using iter_concept_t =
0116             decltype(iter_concept_<I>(std::declval<I>(), priority_tag<3>{}));
0117 
0118         using ::concepts::detail::weakly_equality_comparable_with_;
0119 
0120         template<typename I>
0121         using readable_types_t =
0122             meta::list<iter_value_t<I>, iter_reference_t<I>, iter_rvalue_reference_t<I>>;
0123     } // namespace detail
0124       /// \endcond
0125 
0126     // clang-format off
0127     /// \concept readable_
0128     /// \brief The \c readable_ concept
0129     template(typename I)(
0130     concept (readable_)(I),
0131         // requires (I const i)
0132         // (
0133         //     { *i } -> same_as<iter_reference_t<I>>;
0134         //     { iter_move(i) } -> same_as<iter_rvalue_reference_t<I>>;
0135         // ) &&
0136         same_as<iter_reference_t<I const>, iter_reference_t<I>> AND
0137         same_as<iter_rvalue_reference_t<I const>, iter_rvalue_reference_t<I>> AND
0138         common_reference_with<iter_reference_t<I> &&, iter_value_t<I> &> AND
0139         common_reference_with<iter_reference_t<I> &&,
0140                               iter_rvalue_reference_t<I> &&> AND
0141         common_reference_with<iter_rvalue_reference_t<I> &&, iter_value_t<I> const &>
0142     );
0143 
0144     /// \concept indirectly_readable
0145     /// \brief The \c indirectly_readable concept
0146     template<typename I>
0147     CPP_concept indirectly_readable = //
0148         CPP_concept_ref(ranges::readable_, uncvref_t<I>);
0149 
0150     template<typename I>
0151     RANGES_DEPRECATED("Please use ranges::indirectly_readable instead")
0152     RANGES_INLINE_VAR constexpr bool readable = //
0153         indirectly_readable<I>;
0154 
0155     /// \concept writable_
0156     /// \brief The \c writable_ concept
0157     template<typename O, typename T>
0158     CPP_requires(writable_,
0159         requires(O && o, T && t) //
0160         (
0161             *o = (T &&) t,
0162             *(O &&) o = (T &&) t,
0163             const_cast<iter_reference_t<O> const &&>(*o) = (T &&) t,
0164             const_cast<iter_reference_t<O> const &&>(*(O &&) o) = (T &&) t
0165         ));
0166     /// \concept indirectly_writable
0167     /// \brief The \c indirectly_writable concept
0168     template<typename O, typename T>
0169     CPP_concept indirectly_writable = //
0170         CPP_requires_ref(ranges::writable_, O, T);
0171 
0172     template<typename O, typename T>
0173     RANGES_DEPRECATED("Please use ranges::indirectly_writable instead")
0174     RANGES_INLINE_VAR constexpr bool writable = //
0175         indirectly_writable<O, T>;
0176     // clang-format on
0177 
0178     /// \cond
0179     namespace detail
0180     {
0181 #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
0182         template<typename D>
0183         inline constexpr bool _is_integer_like_ = std::is_integral<D>::value;
0184 #else
0185         template<typename D, typename = void>
0186         constexpr bool _is_integer_like_ = std::is_integral<D>::value;
0187 #endif
0188 
0189         // gcc10 uses for std::ranges::range_difference_t<
0190         // std::ranges::iota_view<size_t, size_t>> == __int128
0191 #if __SIZEOF_INT128__
0192         __extension__ typedef __int128 int128_t;
0193 #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
0194         template<>
0195         inline constexpr bool _is_integer_like_<int128_t> = true;
0196 #else
0197         template<typename Enable>
0198         constexpr bool _is_integer_like_<int128_t, Enable> = true;
0199 #endif
0200 #endif // __SIZEOF_INT128__
0201 
0202         // clang-format off
0203         /// \concept integer_like_
0204         /// \brief The \c integer_like_ concept
0205         template<typename D>
0206         CPP_concept integer_like_ = _is_integer_like_<D>;
0207             // TODO additional syntactic and semantic requirements
0208 
0209 #ifdef RANGES_WORKAROUND_MSVC_792338
0210         template<typename D, bool Signed = (D(-1) < D(0))>
0211         constexpr bool _is_signed_(D *)
0212         {
0213             return Signed;
0214         }
0215         constexpr bool _is_signed_(void *)
0216         {
0217             return false;
0218         }
0219 
0220         /// \concept signed_integer_like_
0221         /// \brief The \c signed_integer_like_ concept
0222         template<typename D>
0223         CPP_concept signed_integer_like_ =
0224             integer_like_<D> && detail::_is_signed_((D*) nullptr);
0225 #else // ^^^ workaround / no workaround vvv
0226         /// \concept signed_integer_like_impl_
0227         /// \brief The \c signed_integer_like_impl_ concept
0228         template(typename D)(
0229         concept (signed_integer_like_impl_)(D),
0230             integer_like_<D> AND
0231             concepts::type<std::integral_constant<bool, (D(-1) < D(0))>> AND
0232             std::integral_constant<bool, (D(-1) < D(0))>::value
0233         );
0234 
0235         /// \concept signed_integer_like_
0236         /// \brief The \c signed_integer_like_ concept
0237         template<typename D>
0238         CPP_concept signed_integer_like_ =
0239             integer_like_<D> &&
0240             CPP_concept_ref(detail::signed_integer_like_impl_, D);
0241 #endif // RANGES_WORKAROUND_MSVC_792338
0242         // clang-format on
0243     } // namespace detail
0244       /// \endcond
0245 
0246     // clang-format off
0247     /// \concept weakly_incrementable_
0248     /// \brief The \c weakly_incrementable_ concept
0249     template<typename I>
0250     CPP_requires(weakly_incrementable_,
0251         requires(I i) //
0252         (
0253             ++i,
0254             i++,
0255             concepts::requires_<same_as<I&, decltype(++i)>>
0256         ));
0257 
0258     /// \concept weakly_incrementable_
0259     /// \brief The \c weakly_incrementable_ concept
0260     template(typename I)(
0261     concept (weakly_incrementable_)(I),
0262         concepts::type<iter_difference_t<I>> AND
0263         detail::signed_integer_like_<iter_difference_t<I>>);
0264 
0265     /// \concept weakly_incrementable
0266     /// \brief The \c weakly_incrementable concept
0267     template<typename I>
0268     CPP_concept weakly_incrementable =
0269         copyable<I> &&
0270         CPP_requires_ref(ranges::weakly_incrementable_, I) &&
0271         CPP_concept_ref(ranges::weakly_incrementable_, I);
0272 
0273     /// \concept incrementable_
0274     /// \brief The \c incrementable_ concept
0275     template<typename I>
0276     CPP_requires(incrementable_,
0277         requires(I i) //
0278         (
0279             concepts::requires_<same_as<I, decltype(i++)>>
0280         ));
0281     /// \concept incrementable
0282     /// \brief The \c incrementable concept
0283     template<typename I>
0284     CPP_concept incrementable =
0285         regular<I> &&
0286         weakly_incrementable<I> &&
0287         CPP_requires_ref(ranges::incrementable_, I);
0288 
0289     /// \concept input_or_output_iterator_
0290     /// \brief The \c input_or_output_iterator_ concept
0291     template(typename I)(
0292     concept (input_or_output_iterator_)(I),
0293         detail::dereferenceable_<I&>
0294     );
0295 
0296     /// \concept input_or_output_iterator
0297     /// \brief The \c input_or_output_iterator concept
0298     template<typename I>
0299     CPP_concept input_or_output_iterator =
0300         weakly_incrementable<I> &&
0301         CPP_concept_ref(ranges::input_or_output_iterator_, I);
0302 
0303     /// \concept sentinel_for
0304     /// \brief The \c sentinel_for concept
0305     template<typename S, typename I>
0306     CPP_concept sentinel_for =
0307         semiregular<S> &&
0308         input_or_output_iterator<I> &&
0309         detail::weakly_equality_comparable_with_<S, I>;
0310 
0311     /// \concept sized_sentinel_for_
0312     /// \brief The \c sized_sentinel_for_ concept
0313     template<typename S, typename I>
0314     CPP_requires(sized_sentinel_for_,
0315         requires(S const & s, I const & i) //
0316         (
0317             s - i,
0318             i - s,
0319             concepts::requires_<same_as<iter_difference_t<I>, decltype(s - i)>>,
0320             concepts::requires_<same_as<iter_difference_t<I>, decltype(i - s)>>
0321         ));
0322     /// \concept sized_sentinel_for_
0323     /// \brief The \c sized_sentinel_for_ concept
0324     template(typename S, typename I)(
0325     concept (sized_sentinel_for_)(S, I),
0326         (!disable_sized_sentinel<std::remove_cv_t<S>, std::remove_cv_t<I>>) AND
0327         sentinel_for<S, I>);
0328 
0329     /// \concept sized_sentinel_for
0330     /// \brief The \c sized_sentinel_for concept
0331     template<typename S, typename I>
0332     CPP_concept sized_sentinel_for =
0333         CPP_concept_ref(sized_sentinel_for_, S, I) &&
0334         CPP_requires_ref(ranges::sized_sentinel_for_, S, I);
0335 
0336     /// \concept output_iterator_
0337     /// \brief The \c output_iterator_ concept
0338     template<typename Out, typename T>
0339     CPP_requires(output_iterator_,
0340         requires(Out o, T && t) //
0341         (
0342             *o++ = (T &&) t
0343         ));
0344     /// \concept output_iterator
0345     /// \brief The \c output_iterator concept
0346     template<typename Out, typename T>
0347     CPP_concept output_iterator =
0348         input_or_output_iterator<Out> &&
0349         indirectly_writable<Out, T> &&
0350         CPP_requires_ref(ranges::output_iterator_, Out, T);
0351 
0352     /// \concept with_category_
0353     /// \brief The \c with_category_ concept
0354     template(typename I, typename Tag)(
0355     concept (with_category_)(I, Tag),
0356         derived_from<detail::iter_concept_t<I>, Tag>
0357     );
0358 
0359     /// \concept input_iterator
0360     /// \brief The \c input_iterator concept
0361     template<typename I>
0362     CPP_concept input_iterator =
0363         input_or_output_iterator<I> &&
0364         indirectly_readable<I> &&
0365         CPP_concept_ref(ranges::with_category_, I, std::input_iterator_tag);
0366 
0367     /// \concept forward_iterator
0368     /// \brief The \c forward_iterator concept
0369     template<typename I>
0370     CPP_concept forward_iterator =
0371         input_iterator<I> &&
0372         incrementable<I> &&
0373         sentinel_for<I, I> &&
0374         CPP_concept_ref(ranges::with_category_, I, std::forward_iterator_tag);
0375 
0376     /// \concept bidirectional_iterator_
0377     /// \brief The \c bidirectional_iterator_ concept
0378     template<typename I>
0379     CPP_requires(bidirectional_iterator_,
0380         requires(I i) //
0381         (
0382             --i,
0383             i--,
0384             concepts::requires_<same_as<I&, decltype(--i)>>,
0385             concepts::requires_<same_as<I, decltype(i--)>>
0386         ));
0387     /// \concept bidirectional_iterator
0388     /// \brief The \c bidirectional_iterator concept
0389     template<typename I>
0390     CPP_concept bidirectional_iterator =
0391         forward_iterator<I> &&
0392         CPP_requires_ref(ranges::bidirectional_iterator_, I) &&
0393         CPP_concept_ref(ranges::with_category_, I, std::bidirectional_iterator_tag);
0394 
0395     /// \concept random_access_iterator_
0396     /// \brief The \c random_access_iterator_ concept
0397     template<typename I>
0398     CPP_requires(random_access_iterator_,
0399         requires(I i, iter_difference_t<I> n)
0400         (
0401             i + n,
0402             n + i,
0403             i - n,
0404             i += n,
0405             i -= n,
0406             concepts::requires_<same_as<decltype(i + n), I>>,
0407             concepts::requires_<same_as<decltype(n + i), I>>,
0408             concepts::requires_<same_as<decltype(i - n), I>>,
0409             concepts::requires_<same_as<decltype(i += n), I&>>,
0410             concepts::requires_<same_as<decltype(i -= n), I&>>,
0411             concepts::requires_<same_as<decltype(i[n]), iter_reference_t<I>>>
0412         ));
0413     /// \concept random_access_iterator
0414     /// \brief The \c random_access_iterator concept
0415     template<typename I>
0416     CPP_concept random_access_iterator =
0417         bidirectional_iterator<I> &&
0418         totally_ordered<I> &&
0419         sized_sentinel_for<I, I> &&
0420         CPP_requires_ref(ranges::random_access_iterator_, I) &&
0421         CPP_concept_ref(ranges::with_category_, I, std::random_access_iterator_tag);
0422 
0423     /// \concept contiguous_iterator_
0424     /// \brief The \c contiguous_iterator_ concept
0425     template(typename I)(
0426     concept (contiguous_iterator_)(I),
0427         std::is_lvalue_reference<iter_reference_t<I>>::value AND
0428         same_as<iter_value_t<I>, uncvref_t<iter_reference_t<I>>> AND
0429         derived_from<detail::iter_concept_t<I>, ranges::contiguous_iterator_tag>
0430     );
0431 
0432     /// \concept contiguous_iterator
0433     /// \brief The \c contiguous_iterator concept
0434     template<typename I>
0435     CPP_concept contiguous_iterator =
0436         random_access_iterator<I> &&
0437         CPP_concept_ref(ranges::contiguous_iterator_, I);
0438     // clang-format on
0439 
0440     /////////////////////////////////////////////////////////////////////////////////////
0441     // iterator_tag_of
0442     template<typename Rng>
0443     using iterator_tag_of =                              //
0444         std::enable_if_t<                                //
0445             input_iterator<Rng>,                         //
0446             meta::conditional_t<                           //
0447                 contiguous_iterator<Rng>,                //
0448                 ranges::contiguous_iterator_tag,         //
0449                 meta::conditional_t<                       //
0450                     random_access_iterator<Rng>,         //
0451                     std::random_access_iterator_tag,     //
0452                     meta::conditional_t<                   //
0453                         bidirectional_iterator<Rng>,     //
0454                         std::bidirectional_iterator_tag, //
0455                         meta::conditional_t<               //
0456                             forward_iterator<Rng>,       //
0457                             std::forward_iterator_tag,   //
0458                             std::input_iterator_tag>>>>>;
0459 
0460     /// \cond
0461     namespace detail
0462     {
0463         template<typename, bool>
0464         struct iterator_category_
0465         {};
0466 
0467         template<typename I>
0468         struct iterator_category_<I, true>
0469         {
0470             using type = iterator_tag_of<I>;
0471         };
0472 
0473         template<typename T, typename U = meta::_t<std::remove_const<T>>>
0474         using iterator_category = iterator_category_<U, (bool)input_iterator<U>>;
0475     } // namespace detail
0476     /// \endcond
0477 
0478     /// \cond
0479     // Generally useful to know if an iterator is single-pass or not:
0480     // clang-format off
0481     /// \concept single_pass_iterator_
0482     /// \brief The \c single_pass_iterator_ concept
0483     template<typename I>
0484     CPP_concept single_pass_iterator_ =
0485         input_or_output_iterator<I> && !forward_iterator<I>;
0486     // clang-format on
0487     /// \endcond
0488 
0489     //////////////////////////////////////////////////////////////////////////////////////
0490     // indirect_result_t
0491     template<typename Fun, typename... Is>
0492     using indirect_result_t =
0493         detail::enable_if_t<(bool)and_v<(bool)indirectly_readable<Is>...>,
0494                             invoke_result_t<Fun, iter_reference_t<Is>...>>;
0495 
0496     /// \cond
0497     namespace detail
0498     {
0499         // clang-format off
0500         /// \concept common_reference_with_4_impl_
0501         /// \brief The \c common_reference_with_4_impl_ concept
0502         template(typename T1, typename T2, typename T3, typename T4)(
0503         concept (common_reference_with_4_impl_)(T1, T2, T3, T4),
0504             concepts::type<common_reference_t<T1, T2, T3, T4>>     AND
0505             convertible_to<T1, common_reference_t<T1, T2, T3, T4>> AND
0506             convertible_to<T2, common_reference_t<T1, T2, T3, T4>> AND
0507             convertible_to<T3, common_reference_t<T1, T2, T3, T4>> AND
0508             convertible_to<T4, common_reference_t<T1, T2, T3, T4>>
0509         );
0510 
0511         /// \concept common_reference_with_4_
0512         /// \brief The \c common_reference_with_4_ concept
0513         template<typename T1, typename T2, typename T3, typename T4>
0514         CPP_concept common_reference_with_4_ =
0515             CPP_concept_ref(detail::common_reference_with_4_impl_, T1, T2, T3, T4);
0516         // axiom: all permutations of T1,T2,T3,T4 have the same
0517         // common reference type.
0518 
0519         /// \concept indirectly_unary_invocable_impl_
0520         /// \brief The \c indirectly_unary_invocable_impl_ concept
0521         template(typename F, typename I)(
0522         concept (indirectly_unary_invocable_impl_)(F, I),
0523             invocable<F &, iter_value_t<I> &> AND
0524             invocable<F &, iter_reference_t<I>> AND
0525             invocable<F &, iter_common_reference_t<I>> AND
0526             common_reference_with<
0527                 invoke_result_t<F &, iter_value_t<I> &>,
0528                 invoke_result_t<F &, iter_reference_t<I>>>
0529         );
0530 
0531         /// \concept indirectly_unary_invocable_
0532         /// \brief The \c indirectly_unary_invocable_ concept
0533         template<typename F, typename I>
0534         CPP_concept indirectly_unary_invocable_ =
0535             indirectly_readable<I> &&
0536             CPP_concept_ref(detail::indirectly_unary_invocable_impl_, F, I);
0537         // clang-format on
0538     } // namespace detail
0539       /// \endcond
0540 
0541     // clang-format off
0542     /// \concept indirectly_unary_invocable
0543     /// \brief The \c indirectly_unary_invocable concept
0544     template<typename F, typename I>
0545     CPP_concept indirectly_unary_invocable =
0546         detail::indirectly_unary_invocable_<F, I> &&
0547         copy_constructible<F>;
0548 
0549     /// \concept indirectly_regular_unary_invocable_
0550     /// \brief The \c indirectly_regular_unary_invocable_ concept
0551     template(typename F, typename I)(
0552     concept (indirectly_regular_unary_invocable_)(F, I),
0553         regular_invocable<F &, iter_value_t<I> &> AND
0554         regular_invocable<F &, iter_reference_t<I>> AND
0555         regular_invocable<F &, iter_common_reference_t<I>> AND
0556         common_reference_with<
0557             invoke_result_t<F &, iter_value_t<I> &>,
0558             invoke_result_t<F &, iter_reference_t<I>>>
0559     );
0560 
0561     /// \concept indirectly_regular_unary_invocable
0562     /// \brief The \c indirectly_regular_unary_invocable concept
0563     template<typename F, typename I>
0564     CPP_concept indirectly_regular_unary_invocable =
0565         indirectly_readable<I> &&
0566         copy_constructible<F> &&
0567         CPP_concept_ref(ranges::indirectly_regular_unary_invocable_, F, I);
0568 
0569     /// \cond
0570     // Non-standard indirect invocable concepts
0571     /// \concept indirectly_binary_invocable_impl_
0572     /// \brief The \c indirectly_binary_invocable_impl_ concept
0573     template(typename F, typename I1, typename I2)(
0574     concept (indirectly_binary_invocable_impl_)(F, I1, I2),
0575         invocable<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
0576         invocable<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
0577         invocable<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
0578         invocable<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
0579         invocable<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>> AND
0580         detail::common_reference_with_4_<
0581             invoke_result_t<F &, iter_value_t<I1> &, iter_value_t<I2> &>,
0582             invoke_result_t<F &, iter_value_t<I1> &, iter_reference_t<I2>>,
0583             invoke_result_t<F &, iter_reference_t<I1>, iter_value_t<I2> &>,
0584             invoke_result_t<F &, iter_reference_t<I1>, iter_reference_t<I2>>>
0585     );
0586 
0587     /// \concept indirectly_binary_invocable_
0588     /// \brief The \c indirectly_binary_invocable_ concept
0589     template<typename F, typename I1, typename I2>
0590     CPP_concept indirectly_binary_invocable_ =
0591         indirectly_readable<I1> && indirectly_readable<I2> &&
0592         copy_constructible<F> &&
0593         CPP_concept_ref(ranges::indirectly_binary_invocable_impl_, F, I1, I2);
0594 
0595     /// \concept indirectly_regular_binary_invocable_impl_
0596     /// \brief The \c indirectly_regular_binary_invocable_impl_ concept
0597     template(typename F, typename I1, typename I2)(
0598     concept (indirectly_regular_binary_invocable_impl_)(F, I1, I2),
0599         regular_invocable<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
0600         regular_invocable<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
0601         regular_invocable<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
0602         regular_invocable<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
0603         regular_invocable<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>> AND
0604         detail::common_reference_with_4_<
0605             invoke_result_t<F &, iter_value_t<I1> &, iter_value_t<I2> &>,
0606             invoke_result_t<F &, iter_value_t<I1> &, iter_reference_t<I2>>,
0607             invoke_result_t<F &, iter_reference_t<I1>, iter_value_t<I2> &>,
0608             invoke_result_t<F &, iter_reference_t<I1>, iter_reference_t<I2>>>
0609     );
0610 
0611     /// \concept indirectly_regular_binary_invocable_
0612     /// \brief The \c indirectly_regular_binary_invocable_ concept
0613     template<typename F, typename I1, typename I2>
0614     CPP_concept indirectly_regular_binary_invocable_ =
0615         indirectly_readable<I1> && indirectly_readable<I2> &&
0616         copy_constructible<F> &&
0617         CPP_concept_ref(ranges::indirectly_regular_binary_invocable_impl_, F, I1, I2);
0618     /// \endcond
0619 
0620     /// \concept indirect_unary_predicate_
0621     /// \brief The \c indirect_unary_predicate_ concept
0622     template(typename F, typename I)(
0623     concept (indirect_unary_predicate_)(F, I),
0624         predicate<F &, iter_value_t<I> &> AND
0625         predicate<F &, iter_reference_t<I>> AND
0626         predicate<F &, iter_common_reference_t<I>>
0627     );
0628 
0629     /// \concept indirect_unary_predicate
0630     /// \brief The \c indirect_unary_predicate concept
0631     template<typename F, typename I>
0632     CPP_concept indirect_unary_predicate =
0633         indirectly_readable<I> &&
0634         copy_constructible<F> &&
0635         CPP_concept_ref(ranges::indirect_unary_predicate_, F, I);
0636 
0637     /// \concept indirect_binary_predicate_impl_
0638     /// \brief The \c indirect_binary_predicate_impl_ concept
0639     template(typename F, typename I1, typename I2)(
0640     concept (indirect_binary_predicate_impl_)(F, I1, I2),
0641         predicate<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
0642         predicate<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
0643         predicate<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
0644         predicate<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
0645         predicate<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
0646     );
0647 
0648     /// \concept indirect_binary_predicate_
0649     /// \brief The \c indirect_binary_predicate_ concept
0650     template<typename F, typename I1, typename I2>
0651     CPP_concept indirect_binary_predicate_ =
0652         indirectly_readable<I1> && indirectly_readable<I2> &&
0653         copy_constructible<F> &&
0654         CPP_concept_ref(ranges::indirect_binary_predicate_impl_, F, I1, I2);
0655 
0656     /// \concept indirect_relation_
0657     /// \brief The \c indirect_relation_ concept
0658     template(typename F, typename I1, typename I2)(
0659     concept (indirect_relation_)(F, I1, I2),
0660         relation<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
0661         relation<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
0662         relation<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
0663         relation<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
0664         relation<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
0665     );
0666 
0667     /// \concept indirect_relation
0668     /// \brief The \c indirect_relation concept
0669     template<typename F, typename I1, typename I2 = I1>
0670     CPP_concept indirect_relation =
0671         indirectly_readable<I1> && indirectly_readable<I2> &&
0672         copy_constructible<F> &&
0673         CPP_concept_ref(ranges::indirect_relation_, F, I1, I2);
0674 
0675     /// \concept indirect_strict_weak_order_
0676     /// \brief The \c indirect_strict_weak_order_ concept
0677     template(typename F, typename I1, typename I2)(
0678     concept (indirect_strict_weak_order_)(F, I1, I2),
0679         strict_weak_order<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
0680         strict_weak_order<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
0681         strict_weak_order<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
0682         strict_weak_order<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
0683         strict_weak_order<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
0684     );
0685 
0686     /// \concept indirect_strict_weak_order
0687     /// \brief The \c indirect_strict_weak_order concept
0688     template<typename F, typename I1, typename I2 = I1>
0689     CPP_concept indirect_strict_weak_order =
0690         indirectly_readable<I1> && indirectly_readable<I2> &&
0691         copy_constructible<F> &&
0692         CPP_concept_ref(ranges::indirect_strict_weak_order_, F, I1, I2);
0693     // clang-format on
0694 
0695     //////////////////////////////////////////////////////////////////////////////////////
0696     // projected struct, for "projecting" a readable with a unary callable
0697     /// \cond
0698     namespace detail
0699     {
0700         RANGES_DIAGNOSTIC_PUSH
0701         RANGES_DIAGNOSTIC_IGNORE_UNDEFINED_INTERNAL
0702         template<typename I, typename Proj>
0703         struct projected_
0704         {
0705             struct type
0706             {
0707                 using reference = indirect_result_t<Proj &, I>;
0708                 using value_type = uncvref_t<reference>;
0709                 reference operator*() const;
0710             };
0711         };
0712         RANGES_DIAGNOSTIC_POP
0713 
0714         template<typename Proj>
0715         struct select_projected_
0716         {
0717             template<typename I>
0718             using apply =
0719                 meta::_t<
0720                     detail::enable_if_t<
0721                         (bool)indirectly_regular_unary_invocable<Proj, I>,
0722                         detail::projected_<I, Proj>>>;
0723         };
0724 
0725         template<>
0726         struct select_projected_<identity>
0727         {
0728             template<typename I>
0729             using apply = detail::enable_if_t<(bool)indirectly_readable<I>, I>;
0730         };
0731     } // namespace detail
0732     /// \endcond
0733 
0734     template<typename I, typename Proj>
0735     using projected = typename detail::select_projected_<Proj>::template apply<I>;
0736 
0737     template<typename I, typename Proj>
0738     struct incrementable_traits<detail::projected_<I, Proj>> : incrementable_traits<I>
0739     {};
0740 
0741     // clang-format off
0742     /// \concept indirectly_movable_
0743     /// \brief The \c indirectly_movable_ concept
0744     template(typename I, typename O)(
0745     concept (indirectly_movable_)(I, O),
0746         indirectly_writable<O, iter_rvalue_reference_t<I>>
0747     );
0748 
0749     /// \concept indirectly_movable
0750     /// \brief The \c indirectly_movable concept
0751     template<typename I, typename O>
0752     CPP_concept indirectly_movable =
0753         indirectly_readable<I> && CPP_concept_ref(ranges::indirectly_movable_, I, O);
0754 
0755     /// \concept indirectly_movable_storable_
0756     /// \brief The \c indirectly_movable_storable_ concept
0757     template(typename I, typename O)(
0758     concept (indirectly_movable_storable_)(I, O),
0759         indirectly_writable<O, iter_value_t<I>> AND
0760         movable<iter_value_t<I>> AND
0761         constructible_from<iter_value_t<I>, iter_rvalue_reference_t<I>> AND
0762         assignable_from<iter_value_t<I> &, iter_rvalue_reference_t<I>>
0763     );
0764 
0765     /// \concept indirectly_movable_storable
0766     /// \brief The \c indirectly_movable_storable concept
0767     template<typename I, typename O>
0768     CPP_concept indirectly_movable_storable =
0769         indirectly_movable<I, O> &&
0770         CPP_concept_ref(ranges::indirectly_movable_storable_, I, O);
0771 
0772     /// \concept indirectly_copyable_
0773     /// \brief The \c indirectly_copyable_ concept
0774     template(typename I, typename O)(
0775     concept (indirectly_copyable_)(I, O),
0776         indirectly_writable<O, iter_reference_t<I>>
0777     );
0778 
0779     /// \concept indirectly_copyable
0780     /// \brief The \c indirectly_copyable concept
0781     template<typename I, typename O>
0782     CPP_concept indirectly_copyable =
0783         indirectly_readable<I> && CPP_concept_ref(ranges::indirectly_copyable_, I, O);
0784 
0785     /// \concept indirectly_copyable_storable_
0786     /// \brief The \c indirectly_copyable_storable_ concept
0787     template(typename I, typename O)(
0788     concept (indirectly_copyable_storable_)(I, O),
0789         indirectly_writable<O, iter_value_t<I> const &> AND
0790         copyable<iter_value_t<I>> AND
0791         constructible_from<iter_value_t<I>, iter_reference_t<I>> AND
0792         assignable_from<iter_value_t<I> &, iter_reference_t<I>>
0793     );
0794 
0795     /// \concept indirectly_copyable_storable
0796     /// \brief The \c indirectly_copyable_storable concept
0797     template<typename I, typename O>
0798     CPP_concept indirectly_copyable_storable =
0799         indirectly_copyable<I, O> &&
0800         CPP_concept_ref(ranges::indirectly_copyable_storable_, I, O);
0801 
0802     /// \concept indirectly_swappable_
0803     /// \brief The \c indirectly_swappable_ concept
0804     template<typename I1, typename I2>
0805     CPP_requires(indirectly_swappable_,
0806         requires(I1 const i1, I2 const i2) //
0807         (
0808             ranges::iter_swap(i1, i2),
0809             ranges::iter_swap(i1, i1),
0810             ranges::iter_swap(i2, i2),
0811             ranges::iter_swap(i2, i1)
0812         ));
0813     /// \concept indirectly_swappable
0814     /// \brief The \c indirectly_swappable concept
0815     template<typename I1, typename I2 = I1>
0816     CPP_concept indirectly_swappable =
0817         indirectly_readable<I1> && //
0818         indirectly_readable<I2> && //
0819         CPP_requires_ref(ranges::indirectly_swappable_, I1, I2);
0820 
0821     /// \concept projected_indirect_relation_
0822     /// \brief The \c projected_indirect_relation_ concept
0823     template(typename C, typename I1, typename P1, typename I2, typename P2)(
0824     concept (projected_indirect_relation_)(C, I1, P1, I2, P2),
0825         indirect_relation<C, projected<I1, P1>, projected<I2, P2>>
0826     );
0827 
0828     /// \concept indirectly_comparable
0829     /// \brief The \c indirectly_comparable concept
0830     template<typename I1, typename I2, typename C, typename P1 = identity,
0831         typename P2 = identity>
0832     CPP_concept indirectly_comparable =
0833         CPP_concept_ref(ranges::projected_indirect_relation_, C, I1, P1, I2, P2);
0834 
0835     //////////////////////////////////////////////////////////////////////////////////////
0836     // Composite concepts for use defining algorithms:
0837     /// \concept permutable
0838     /// \brief The \c permutable concept
0839     template<typename I>
0840     CPP_concept permutable =
0841         forward_iterator<I> &&
0842         indirectly_swappable<I, I> &&
0843         indirectly_movable_storable<I, I>;
0844 
0845     /// \concept projected_indirect_strict_weak_order_
0846     /// \brief The \c projected_indirect_strict_weak_order_ concept
0847     template(typename C, typename I1, typename P1, typename I2, typename P2)(
0848     concept (projected_indirect_strict_weak_order_)(C, I1, P1, I2, P2),
0849         indirect_strict_weak_order<C, projected<I1, P1>, projected<I2, P2>>
0850     );
0851 
0852     template<typename I1, typename I2, typename Out, typename C = less,
0853         typename P1 = identity, typename P2 = identity>
0854     CPP_concept mergeable =
0855         input_iterator<I1> &&
0856         input_iterator<I2> &&
0857         weakly_incrementable<Out> &&
0858         indirectly_copyable<I1, Out> &&
0859         indirectly_copyable<I2, Out> &&
0860         CPP_concept_ref(ranges::projected_indirect_strict_weak_order_, C, I1, P1, I2, P2);
0861 
0862     /// \concept sortable
0863     /// \brief The \c sortable concept
0864     template<typename I, typename C = less, typename P = identity>
0865     CPP_concept sortable =
0866         permutable<I> &&
0867         CPP_concept_ref(ranges::projected_indirect_strict_weak_order_, C, I, P, I, P);
0868     // clang-format on
0869 
0870     struct sentinel_tag
0871     {};
0872     struct sized_sentinel_tag : sentinel_tag
0873     {};
0874 
0875     template<typename S, typename I>
0876     using sentinel_tag_of =               //
0877         std::enable_if_t<                 //
0878             sentinel_for<S, I>,           //
0879             meta::conditional_t<            //
0880                 sized_sentinel_for<S, I>, //
0881                 sized_sentinel_tag,       //
0882                 sentinel_tag>>;
0883 
0884     // Deprecated things:
0885     /// \cond
0886     template<typename I>
0887     using iterator_category RANGES_DEPRECATED(
0888         "iterator_category is deprecated. Use the iterator concepts instead") =
0889         detail::iterator_category<I>;
0890 
0891     template<typename I>
0892     using iterator_category_t RANGES_DEPRECATED(
0893         "iterator_category_t is deprecated. Use the iterator concepts instead") =
0894         meta::_t<detail::iterator_category<I>>;
0895 
0896     template<typename Fun, typename... Is>
0897     using indirect_invoke_result_t RANGES_DEPRECATED(
0898         "Please switch to indirect_result_t") = indirect_result_t<Fun, Is...>;
0899 
0900     template<typename Fun, typename... Is>
0901     struct RANGES_DEPRECATED("Please switch to indirect_result_t") indirect_invoke_result
0902       : meta::defer<indirect_result_t, Fun, Is...>
0903     {};
0904 
0905     template<typename Sig>
0906     struct indirect_result_of
0907     {};
0908 
0909     template<typename Fun, typename... Is>
0910     struct RANGES_DEPRECATED("Please switch to indirect_result_t")
0911         indirect_result_of<Fun(Is...)> : meta::defer<indirect_result_t, Fun, Is...>
0912     {};
0913 
0914     template<typename Sig>
0915     using indirect_result_of_t RANGES_DEPRECATED("Please switch to indirect_result_t") =
0916         meta::_t<indirect_result_of<Sig>>;
0917     /// \endcond
0918 
0919     namespace cpp20
0920     {
0921         using ranges::bidirectional_iterator;
0922         using ranges::contiguous_iterator;
0923         using ranges::forward_iterator;
0924         using ranges::incrementable;
0925         using ranges::indirect_relation;
0926         using ranges::indirect_result_t;
0927         using ranges::indirect_strict_weak_order;
0928         using ranges::indirect_unary_predicate;
0929         using ranges::indirectly_comparable;
0930         using ranges::indirectly_copyable;
0931         using ranges::indirectly_copyable_storable;
0932         using ranges::indirectly_movable;
0933         using ranges::indirectly_movable_storable;
0934         using ranges::indirectly_readable;
0935         using ranges::indirectly_regular_unary_invocable;
0936         using ranges::indirectly_swappable;
0937         using ranges::indirectly_unary_invocable;
0938         using ranges::indirectly_writable;
0939         using ranges::input_iterator;
0940         using ranges::input_or_output_iterator;
0941         using ranges::mergeable;
0942         using ranges::output_iterator;
0943         using ranges::permutable;
0944         using ranges::projected;
0945         using ranges::random_access_iterator;
0946         using ranges::sentinel_for;
0947         using ranges::sized_sentinel_for;
0948         using ranges::sortable;
0949         using ranges::weakly_incrementable;
0950     } // namespace cpp20
0951     /// @}
0952 } // namespace ranges
0953 
0954 #ifdef _GLIBCXX_DEBUG
0955 // HACKHACK: workaround underconstrained operator- for libstdc++ debug iterator wrapper
0956 // by intentionally creating an ambiguity when the wrapped types don't support the
0957 // necessary operation.
0958 namespace __gnu_debug
0959 {
0960     template(typename I1, typename I2, typename Seq)(
0961         requires (!::ranges::sized_sentinel_for<I1, I2>)) //
0962     void operator-(_Safe_iterator<I1, Seq> const &, _Safe_iterator<I2, Seq> const &) =
0963         delete;
0964 
0965     template(typename I1, typename Seq)(
0966         requires (!::ranges::sized_sentinel_for<I1, I1>)) //
0967     void operator-(_Safe_iterator<I1, Seq> const &, _Safe_iterator<I1, Seq> const &) =
0968         delete;
0969 } // namespace __gnu_debug
0970 #endif
0971 
0972 #if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 3900)
0973 // HACKHACK: workaround libc++ (https://llvm.org/bugs/show_bug.cgi?id=28421)
0974 // and libstdc++ (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71771)
0975 // underconstrained operator- for reverse_iterator by disabling sized_sentinel_for
0976 // when the base iterators do not model sized_sentinel_for.
0977 
0978 namespace ranges
0979 {
0980     template<typename S, typename I>
0981     /*inline*/ constexpr bool
0982         disable_sized_sentinel<std::reverse_iterator<S>, std::reverse_iterator<I>> =
0983             !static_cast<bool>(sized_sentinel_for<I, S>);
0984 } // namespace ranges
0985 
0986 #endif // defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 3900)
0987 
0988 #include <range/v3/detail/epilogue.hpp>
0989 
0990 #endif // RANGES_V3_ITERATOR_CONCEPTS_HPP