1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// <algorithm>
10
11// template<InputIterator Iter1, InputIterator Iter2>
12// requires HasEqualTo<Iter1::value_type, Iter2::value_type>
13// constexpr pair<Iter1, Iter2> // constexpr after c++17
14// mismatch(Iter1 first1, Iter1 last1, Iter2 first2);
15//
16// template<InputIterator Iter1, InputIterator Iter2Pred>
17// constexpr pair<Iter1, Iter2> // constexpr after c++17
18// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2); // C++14
19//
20// template<InputIterator Iter1, InputIterator Iter2,
21// Predicate<auto, Iter1::value_type, Iter2::value_type> Pred>
22// requires CopyConstructible<Pred>
23// constexpr pair<Iter1, Iter2> // constexpr after c++17
24// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Pred pred);
25//
26// template<InputIterator Iter1, InputIterator Iter2, Predicate Pred>
27// constexpr pair<Iter1, Iter2> // constexpr after c++17
28// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred); // C++14
29
30// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=50000000
31// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=100000000
32
33#include <algorithm>
34#include <array>
35#include <cassert>
36#include <vector>
37
38#include "test_macros.h"
39#include "test_iterators.h"
40#include "type_algorithms.h"
41
42template <class Iter, class Container1, class Container2>
43TEST_CONSTEXPR_CXX20 void check(Container1 lhs, Container2 rhs, size_t offset) {
44 if (lhs.size() == rhs.size()) {
45 assert(std::mismatch(Iter(lhs.data()), Iter(lhs.data() + lhs.size()), Iter(rhs.data())) ==
46 std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset)));
47
48 assert(std::mismatch(Iter(lhs.data()),
49 Iter(lhs.data() + lhs.size()),
50 Iter(rhs.data()),
51 std::equal_to<typename Container1::value_type>()) ==
52 std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset)));
53 }
54
55#if TEST_STD_VER >= 14
56 assert(
57 std::mismatch(Iter(lhs.data()), Iter(lhs.data() + lhs.size()), Iter(rhs.data()), Iter(rhs.data() + rhs.size())) ==
58 std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset)));
59
60 assert(std::mismatch(Iter(lhs.data()),
61 Iter(lhs.data() + lhs.size()),
62 Iter(rhs.data()),
63 Iter(rhs.data() + rhs.size()),
64 std::equal_to<typename Container1::value_type>()) ==
65 std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset)));
66#endif
67}
68
69struct NonTrivial {
70 int i_;
71
72 TEST_CONSTEXPR_CXX20 NonTrivial(int i) : i_(i) {}
73 TEST_CONSTEXPR_CXX20 NonTrivial(NonTrivial&& other) : i_(other.i_) { other.i_ = 0; }
74
75 TEST_CONSTEXPR_CXX20 friend bool operator==(const NonTrivial& lhs, const NonTrivial& rhs) { return lhs.i_ == rhs.i_; }
76};
77
78struct ModTwoComp {
79 TEST_CONSTEXPR_CXX20 bool operator()(int lhs, int rhs) { return lhs % 2 == rhs % 2; }
80};
81
82template <class Iter>
83TEST_CONSTEXPR_CXX20 bool test() {
84 { // empty ranges
85 std::array<int, 0> lhs = {};
86 std::array<int, 0> rhs = {};
87 check<Iter>(lhs, rhs, 0);
88 }
89
90 { // same range without mismatch
91 std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3};
92 std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3};
93 check<Iter>(lhs, rhs, 8);
94 }
95
96 { // same range with mismatch
97 std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
98 std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3};
99 check<Iter>(lhs, rhs, 3);
100 }
101
102 { // second range is smaller
103 std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
104 std::array<int, 2> rhs = {0, 1};
105 check<Iter>(lhs, rhs, 2);
106 }
107
108 { // first range is smaller
109 std::array<int, 2> lhs = {0, 1};
110 std::array<int, 8> rhs = {0, 1, 2, 2, 0, 1, 2, 3};
111 check<Iter>(lhs, rhs, 2);
112 }
113
114 { // use a custom comparator
115 std::array<int, 4> lhs = {0, 2, 3, 4};
116 std::array<int, 4> rhs = {0, 0, 4, 4};
117 assert(std::mismatch(lhs.data(), lhs.data() + lhs.size(), rhs.data(), ModTwoComp()) ==
118 std::make_pair(lhs.data() + 2, rhs.data() + 2));
119#if TEST_STD_VER >= 14
120 assert(std::mismatch(lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size(), ModTwoComp()) ==
121 std::make_pair(lhs.data() + 2, rhs.data() + 2));
122#endif
123 }
124
125 return true;
126}
127
128struct Test {
129 template <class Iter>
130 TEST_CONSTEXPR_CXX20 void operator()() {
131 test<Iter>();
132 }
133};
134
135TEST_CONSTEXPR_CXX20 bool test() {
136 types::for_each(types::cpp17_input_iterator_list<int*>(), Test());
137
138 { // use a non-integer type to also test the general case - all elements match
139 std::array<NonTrivial, 8> lhs = {1, 2, 3, 4, 5, 6, 7, 8};
140 std::array<NonTrivial, 8> rhs = {1, 2, 3, 4, 5, 6, 7, 8};
141 check<NonTrivial*>(std::move(lhs), std::move(rhs), 8);
142 }
143
144 { // use a non-integer type to also test the general case - not all elements match
145 std::array<NonTrivial, 8> lhs = {1, 2, 3, 4, 7, 6, 7, 8};
146 std::array<NonTrivial, 8> rhs = {1, 2, 3, 4, 5, 6, 7, 8};
147 check<NonTrivial*>(std::move(lhs), std::move(rhs), 4);
148 }
149
150 return true;
151}
152
153int main(int, char**) {
154 test();
155#if TEST_STD_VER >= 20
156 static_assert(test());
157#endif
158
159 { // check with a lot of elements to test the vectorization optimization
160 {
161 std::vector<char> lhs(256);
162 std::vector<char> rhs(256);
163 for (size_t i = 0; i != lhs.size(); ++i) {
164 lhs[i] = 1;
165 check<char*>(lhs, rhs, i);
166 lhs[i] = 0;
167 rhs[i] = 1;
168 check<char*>(lhs, rhs, i);
169 rhs[i] = 0;
170 }
171 }
172
173 {
174 std::vector<int> lhs(256);
175 std::vector<int> rhs(256);
176 for (size_t i = 0; i != lhs.size(); ++i) {
177 lhs[i] = 1;
178 check<int*>(lhs, rhs, i);
179 lhs[i] = 0;
180 rhs[i] = 1;
181 check<int*>(lhs, rhs, i);
182 rhs[i] = 0;
183 }
184 }
185 }
186
187 { // check the tail of the vectorized loop
188 for (size_t vec_size = 1; vec_size != 256; ++vec_size) {
189 {
190 std::vector<char> lhs(vec_size);
191 std::vector<char> rhs(vec_size);
192
193 check<char*>(lhs, rhs, lhs.size());
194 lhs.back() = 1;
195 check<char*>(lhs, rhs, lhs.size() - 1);
196 lhs.back() = 0;
197 rhs.back() = 1;
198 check<char*>(lhs, rhs, lhs.size() - 1);
199 rhs.back() = 0;
200 }
201 {
202 std::vector<int> lhs(vec_size);
203 std::vector<int> rhs(vec_size);
204
205 check<int*>(lhs, rhs, lhs.size());
206 lhs.back() = 1;
207 check<int*>(lhs, rhs, lhs.size() - 1);
208 lhs.back() = 0;
209 rhs.back() = 1;
210 check<int*>(lhs, rhs, lhs.size() - 1);
211 rhs.back() = 0;
212 }
213 }
214 }
215 return 0;
216}
217

source code of libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp