File indexing completed on 2025-12-16 10:27:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_ALGORITHM_EQUAL_RANGE_HPP
0015 #define RANGES_V3_ALGORITHM_EQUAL_RANGE_HPP
0016
0017 #include <range/v3/range_fwd.hpp>
0018
0019 #include <range/v3/algorithm/aux_/equal_range_n.hpp>
0020 #include <range/v3/algorithm/aux_/lower_bound_n.hpp>
0021 #include <range/v3/algorithm/upper_bound.hpp>
0022 #include <range/v3/functional/comparisons.hpp>
0023 #include <range/v3/functional/identity.hpp>
0024 #include <range/v3/functional/invoke.hpp>
0025 #include <range/v3/iterator/operations.hpp>
0026 #include <range/v3/range/access.hpp>
0027 #include <range/v3/range/concepts.hpp>
0028 #include <range/v3/range/traits.hpp>
0029 #include <range/v3/utility/static_const.hpp>
0030 #include <range/v3/view/subrange.hpp>
0031
0032 #include <range/v3/detail/prologue.hpp>
0033
0034 namespace ranges
0035 {
0036
0037
0038 RANGES_FUNC_BEGIN(equal_range)
0039
0040
0041 template(typename I,
0042 typename S,
0043 typename V,
0044 typename C = less,
0045 typename P = identity)(
0046 requires forward_iterator<I> AND sentinel_for<S, I> AND
0047 indirect_strict_weak_order<C, V const *, projected<I, P>>)
0048 constexpr subrange<I> RANGES_FUNC(equal_range)(
0049 I first, S last, V const & val, C pred = C{}, P proj = P{})
0050 {
0051 if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S, I>))
0052 {
0053 auto const len = distance(first, last);
0054 return aux::equal_range_n(
0055 std::move(first), len, val, std::move(pred), std::move(proj));
0056 }
0057
0058
0059
0060
0061
0062 auto dist = iter_difference_t<I>{1};
0063 while(true)
0064 {
0065 auto mid = first;
0066 auto d = advance(mid, dist, last);
0067 if(d || mid == last)
0068 {
0069
0070 dist -= d;
0071 return aux::equal_range_n(
0072 std::move(first), dist, val, ranges::ref(pred), ranges::ref(proj));
0073 }
0074
0075 auto && v = *mid;
0076 auto && pv = invoke(proj, (decltype(v) &&)v);
0077 if(invoke(pred, val, pv))
0078 {
0079 return aux::equal_range_n(
0080 std::move(first), dist, val, ranges::ref(pred), ranges::ref(proj));
0081 }
0082 else if(!invoke(pred, pv, val))
0083 {
0084
0085
0086 return {
0087 aux::lower_bound_n(
0088 std::move(first), dist, val, ranges::ref(pred), ranges::ref(proj)),
0089 upper_bound(std::move(mid),
0090 std::move(last),
0091 val,
0092 ranges::ref(pred),
0093 ranges::ref(proj))};
0094 }
0095
0096 first = std::move(mid);
0097 ++first;
0098 dist *= 2;
0099 }
0100 }
0101
0102
0103 template(typename Rng, typename V, typename C = less, typename P = identity)(
0104 requires forward_range<Rng> AND
0105 indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>)
0106 constexpr borrowed_subrange_t<Rng>
0107 RANGES_FUNC(equal_range)(Rng && rng, V const & val, C pred = C{}, P proj = P{})
0108 {
0109 if(RANGES_CONSTEXPR_IF(sized_range<Rng>))
0110 {
0111 auto const len = distance(rng);
0112 return aux::equal_range_n(
0113 begin(rng), len, val, std::move(pred), std::move(proj));
0114 }
0115
0116 return (*this)(begin(rng), end(rng), val, std::move(pred), std::move(proj));
0117 }
0118
0119 RANGES_FUNC_END(equal_range)
0120
0121 namespace cpp20
0122 {
0123 using ranges::equal_range;
0124 }
0125
0126 }
0127
0128 #include <range/v3/detail/epilogue.hpp>
0129
0130 #endif