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