1 /// \file 2 // Range v3 library 3 // 4 // Copyright Eric Niebler 2014-present 5 // 6 // Use, modification and distribution is subject to the 7 // Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt) 10 // 11 // Project home: https://github.com/ericniebler/range-v3 12 // 13 #ifndef RANGES_V3_ALGORITHM_MISMATCH_HPP 14 #define RANGES_V3_ALGORITHM_MISMATCH_HPP 15 16 #include <utility> 17 18 #include <meta/meta.hpp> 19 20 #include <range/v3/range_fwd.hpp> 21 22 #include <range/v3/algorithm/result_types.hpp> 23 #include <range/v3/functional/comparisons.hpp> 24 #include <range/v3/functional/identity.hpp> 25 #include <range/v3/functional/invoke.hpp> 26 #include <range/v3/iterator/concepts.hpp> 27 #include <range/v3/iterator/traits.hpp> 28 #include <range/v3/range/access.hpp> 29 #include <range/v3/range/concepts.hpp> 30 #include <range/v3/range/dangling.hpp> 31 #include <range/v3/range/traits.hpp> 32 #include <range/v3/utility/static_const.hpp> 33 34 #include <range/v3/detail/prologue.hpp> 35 36 namespace ranges 37 { 38 /// \addtogroup group-algorithms 39 /// @{ 40 template<typename I1, typename I2> 41 using mismatch_result = detail::in1_in2_result<I1, I2>; 42 RANGES_FUNC_BEGIN(mismatch)43 RANGES_FUNC_BEGIN(mismatch) 44 45 /// \brief function template \c mismatch 46 template(typename I1, 47 typename S1, 48 typename I2, 49 typename C = equal_to, 50 typename P1 = identity, 51 typename P2 = identity)( 52 /// \pre 53 requires input_iterator<I1> AND sentinel_for<S1, I1> AND 54 input_iterator<I2> AND 55 indirect_relation<C, projected<I1, P1>, projected<I2, P2>>) 56 RANGES_DEPRECATED( 57 "Use the variant of ranges::mismatch that takes an upper bound for " 58 "both sequences") 59 mismatch_result<I1, I2> RANGES_FUNC(mismatch)(I1 begin1, 60 S1 end1, 61 I2 begin2, 62 C pred = C{}, 63 P1 proj1 = P1{}, 64 P2 proj2 = P2{}) // 65 { 66 for(; begin1 != end1; ++begin1, ++begin2) 67 if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) 68 break; 69 return {begin1, begin2}; 70 } 71 72 /// \overload 73 template(typename I1, 74 typename S1, 75 typename I2, 76 typename S2, 77 typename C = equal_to, 78 typename P1 = identity, 79 typename P2 = identity)( 80 /// \pre 81 requires input_iterator<I1> AND sentinel_for<S1, I1> AND 82 input_iterator<I2> AND sentinel_for<S2, I2> AND 83 indirect_relation<C, projected<I1, P1>, projected<I2, P2>>) RANGES_FUNC(mismatch)84 mismatch_result<I1, I2> RANGES_FUNC(mismatch)(I1 begin1, 85 S1 end1, 86 I2 begin2, 87 S2 end2, 88 C pred = C{}, 89 P1 proj1 = P1{}, 90 P2 proj2 = P2{}) // 91 { 92 for(; begin1 != end1 && begin2 != end2; ++begin1, ++begin2) 93 if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) 94 break; 95 return {begin1, begin2}; 96 } 97 98 /// \overload 99 template(typename Rng1, 100 typename I2Ref, 101 typename C = equal_to, 102 typename P1 = identity, 103 typename P2 = identity)( //s 104 requires input_range<Rng1> AND input_iterator<uncvref_t<I2Ref>> AND 105 indirect_relation<C, 106 projected<iterator_t<Rng1>, P1>, 107 projected<uncvref_t<I2Ref>, P2>>) 108 RANGES_DEPRECATED( 109 "Use the variant of ranges::mismatch that takes an upper bound for " 110 "both sequences") 111 mismatch_result<borrowed_iterator_t<Rng1>, uncvref_t<I2Ref>> RANGES_FUNC(mismatch)112 RANGES_FUNC(mismatch)(Rng1 && rng1, 113 I2Ref && begin2, 114 C pred = C{}, // see below [*] 115 P1 proj1 = P1{}, 116 P2 proj2 = P2{}) // 117 { 118 RANGES_DIAGNOSTIC_PUSH 119 RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS 120 return (*this)(begin(rng1), 121 end(rng1), 122 static_cast<uncvref_t<I2Ref> &&>(begin2), 123 std::move(pred), 124 std::move(proj1), 125 std::move(proj2)); 126 RANGES_DIAGNOSTIC_POP 127 } 128 129 /// \overload 130 template(typename Rng1, 131 typename Rng2, 132 typename C = equal_to, 133 typename P1 = identity, 134 typename P2 = identity)( 135 /// \pre 136 requires input_range<Rng1> AND input_range<Rng2> AND 137 indirect_relation<C, 138 projected<iterator_t<Rng1>, P1>, 139 projected<iterator_t<Rng2>, P2>>) 140 mismatch_result<borrowed_iterator_t<Rng1>, borrowed_iterator_t<Rng2>> // RANGES_FUNC(mismatch)141 RANGES_FUNC(mismatch)(Rng1 && rng1, 142 Rng2 && rng2, 143 C pred = C{}, 144 P1 proj1 = P1{}, 145 P2 proj2 = P2{}) // 146 { 147 return (*this)(begin(rng1), 148 end(rng1), 149 begin(rng2), 150 end(rng2), 151 std::move(pred), 152 std::move(proj1), 153 std::move(proj2)); 154 } 155 156 RANGES_FUNC_END(mismatch) 157 158 namespace cpp20 159 { 160 using ranges::mismatch; 161 using ranges::mismatch_result; 162 } // namespace cpp20 163 164 // [*] In this case, the 'begin2' iterator is taken by universal reference. Why? So 165 // that we can properly distinguish this case: 166 // int x[] = {1,2,3,4}; 167 // int y[] = {1,2,3,4}; 168 // mismatch(x, y); 169 // Had 'begin2' been taken by value as is customary, this call could match as either 170 // two ranges, or a range and an iterator, where the iterator is the array, decayed 171 // to a pointer. Yuk! 172 173 /// @} 174 } // namespace ranges 175 176 #include <range/v3/detail/epilogue.hpp> 177 178 #endif 179