294 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// template <input_iterator I1, sentinel_for<_I1> S1, input_iterator I2, sentinel_for<_I2> S2,12// class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity>13// requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2>14// constexpr mismatch_result<_I1, _I2>15// ranges::mismatch()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {})16 17// template <input_range R1, input_range R2,18// class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity>19// requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>20// constexpr mismatch_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>>21// ranges::mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {})22 23#include <algorithm>24#include <array>25#include <cassert>26#include <functional>27#include <ranges>28 29#include "test_iterators.h"30 31template <class Iter1, class Iter2>32constexpr void test_iterators(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2, int* expected1, int* expected2) {33 using Expected = std::ranges::mismatch_result<Iter1, Iter2>;34 std::same_as<Expected> auto ret = std::ranges::mismatch(std::move(begin1), sentinel_wrapper<Iter1>(std::move(end1)),35 std::move(begin2), sentinel_wrapper<Iter2>(std::move(end2)));36 assert(base(ret.in1) == expected1);37 assert(base(ret.in2) == expected2);38}39 40template <class Iter1, class Iter2>41constexpr void test_iters() {42 int a[] = {1, 2, 3, 4, 5};43 int b[] = {1, 2, 3, 5, 4};44 45 test_iterators(Iter1(a), Iter1(a + 5), Iter2(b), Iter2(b + 5), a + 3, b + 3);46}47 48constexpr bool test() {49 test_iters<cpp17_input_iterator<int*>, cpp17_input_iterator<int*>>();50 test_iters<cpp17_input_iterator<int*>, cpp20_input_iterator<int*>>();51 test_iters<cpp17_input_iterator<int*>, forward_iterator<int*>>();52 test_iters<cpp17_input_iterator<int*>, bidirectional_iterator<int*>>();53 test_iters<cpp17_input_iterator<int*>, random_access_iterator<int*>>();54 test_iters<cpp17_input_iterator<int*>, contiguous_iterator<int*>>();55 test_iters<cpp17_input_iterator<int*>, int*>();56 57 test_iters<cpp20_input_iterator<int*>, cpp17_input_iterator<int*>>();58 test_iters<cpp20_input_iterator<int*>, cpp20_input_iterator<int*>>();59 test_iters<cpp20_input_iterator<int*>, forward_iterator<int*>>();60 test_iters<cpp20_input_iterator<int*>, bidirectional_iterator<int*>>();61 test_iters<cpp20_input_iterator<int*>, random_access_iterator<int*>>();62 test_iters<cpp20_input_iterator<int*>, contiguous_iterator<int*>>();63 test_iters<cpp20_input_iterator<int*>, int*>();64 65 test_iters<forward_iterator<int*>, cpp17_input_iterator<int*>>();66 test_iters<forward_iterator<int*>, cpp20_input_iterator<int*>>();67 test_iters<forward_iterator<int*>, forward_iterator<int*>>();68 test_iters<forward_iterator<int*>, bidirectional_iterator<int*>>();69 test_iters<forward_iterator<int*>, random_access_iterator<int*>>();70 test_iters<forward_iterator<int*>, contiguous_iterator<int*>>();71 test_iters<forward_iterator<int*>, int*>();72 73 test_iters<bidirectional_iterator<int*>, cpp17_input_iterator<int*>>();74 test_iters<bidirectional_iterator<int*>, cpp20_input_iterator<int*>>();75 test_iters<bidirectional_iterator<int*>, forward_iterator<int*>>();76 test_iters<bidirectional_iterator<int*>, bidirectional_iterator<int*>>();77 test_iters<bidirectional_iterator<int*>, random_access_iterator<int*>>();78 test_iters<bidirectional_iterator<int*>, contiguous_iterator<int*>>();79 test_iters<bidirectional_iterator<int*>, int*>();80 81 test_iters<random_access_iterator<int*>, cpp17_input_iterator<int*>>();82 test_iters<random_access_iterator<int*>, cpp20_input_iterator<int*>>();83 test_iters<random_access_iterator<int*>, forward_iterator<int*>>();84 test_iters<random_access_iterator<int*>, bidirectional_iterator<int*>>();85 test_iters<random_access_iterator<int*>, random_access_iterator<int*>>();86 test_iters<random_access_iterator<int*>, contiguous_iterator<int*>>();87 test_iters<random_access_iterator<int*>, int*>();88 89 test_iters<contiguous_iterator<int*>, cpp17_input_iterator<int*>>();90 test_iters<contiguous_iterator<int*>, cpp20_input_iterator<int*>>();91 test_iters<contiguous_iterator<int*>, forward_iterator<int*>>();92 test_iters<contiguous_iterator<int*>, bidirectional_iterator<int*>>();93 test_iters<contiguous_iterator<int*>, random_access_iterator<int*>>();94 test_iters<contiguous_iterator<int*>, contiguous_iterator<int*>>();95 test_iters<contiguous_iterator<int*>, int*>();96 97 test_iters<int*, cpp17_input_iterator<int*>>();98 test_iters<int*, cpp20_input_iterator<int*>>();99 test_iters<int*, forward_iterator<int*>>();100 test_iters<int*, bidirectional_iterator<int*>>();101 test_iters<int*, random_access_iterator<int*>>();102 test_iters<int*, contiguous_iterator<int*>>();103 test_iters<int*, int*>();104 105 { // test with a range106 std::array<int, 5> a = {1, 2, 3, 4, 5};107 std::array<int, 5> b = {1, 2, 3, 5, 4};108 using Expected = std::ranges::mismatch_result<std::array<int, 5>::iterator, std::array<int, 5>::iterator>;109 std::same_as<Expected> auto ret = std::ranges::mismatch(a, b);110 assert(ret.in1 == a.begin() + 3);111 assert(ret.in2 == b.begin() + 3);112 }113 114 { // test with non-iterator sentinel115 int a[] = {1, 2, 3, 4, 5};116 int b[] = {1, 2, 3, 5, 4};117 118 using Iter = int*;119 using Sentinel = sentinel_wrapper<Iter>;120 using Expected = std::ranges::mismatch_result<Iter, Iter>;121 122 std::same_as<Expected> auto r = std::ranges::mismatch(Iter(a), Sentinel(a + 5), Iter(b), Sentinel(b + 5));123 assert(r.in1 == a + 3);124 assert(r.in2 == b + 3);125 }126 127 { // test with different array sizes128 {129 int a[] = {1, 2, 3};130 int b[] = {1, 2};131 test_iterators(a, a + 3, b, b + 2, a + 2, b + 2);132 using Expected = std::ranges::mismatch_result<int*, int*>;133 std::same_as<Expected> auto ret = std::ranges::mismatch(a, b);134 assert(ret.in1 == a + 2);135 assert(ret.in2 == b + 2);136 }137 {138 int a[] = {1, 2};139 int b[] = {1, 2, 3};140 test_iterators(a, a + 2, b, b + 3, a + 2, b + 2);141 using Expected = std::ranges::mismatch_result<int*, int*>;142 std::same_as<Expected> auto ret = std::ranges::mismatch(a, b);143 assert(ret.in1 == a + 2);144 assert(ret.in2 == b + 2);145 }146 }147 148 { // test with borrowed ranges149 int r1[] = {1, 2, 3, 4, 5};150 int r2[] = {1, 2, 3, 5, 4};151 152 using Expected = std::ranges::mismatch_result<int*, int*>;153 {154 std::same_as<Expected> auto ret = std::ranges::mismatch(r1, std::views::all(r2));155 assert(ret.in1 == r1 + 3);156 assert(ret.in2 == r2 + 3);157 }158 {159 std::same_as<Expected> auto ret = std::ranges::mismatch(std::views::all(r1), r2);160 assert(ret.in1 == r1 + 3);161 assert(ret.in2 == r2 + 3);162 }163 {164 std::same_as<Expected> auto ret = std::ranges::mismatch(std::views::all(r1), std::views::all(r2));165 assert(ret.in1 == r1 + 3);166 assert(ret.in2 == r2 + 3);167 }168 }169 170 { // test structured bindings171 int a[] = {1, 2, 3, 4};172 int b[] = {1, 2, 4, 8, 16};173 auto [ai, bi] = std::ranges::mismatch(a, b);174 assert(ai == a + 2);175 assert(bi == b + 2);176 auto [aj, bj] = std::ranges::mismatch(a, a+4, b, b+5);177 assert(aj == a + 2);178 assert(bj == b + 2);179 }180 181 { // test predicate182 {183 int a[] = {7, 6, 9, 3, 5, 1, 2, 4};184 int b[] = {6, 5, 8, 2, 5, 1, 2, 4};185 auto ret = std::ranges::mismatch(a, a + 8, b, b + 8, std::ranges::greater{});186 assert(ret.in1 == a + 4);187 assert(ret.in2 == b + 4);188 assert(*ret.in1 == 5);189 assert(*ret.in2 == 5);190 }191 192 {193 int a[] = {7, 6, 9, 3, 5, 1, 2, 4};194 int b[] = {6, 5, 8, 2, 5, 1, 2, 4};195 auto ret = std::ranges::mismatch(a, b, std::ranges::greater{});196 assert(ret.in1 == a + 4);197 assert(ret.in2 == b + 4);198 assert(*ret.in1 == 5);199 assert(*ret.in2 == 5);200 }201 }202 203 { // test projection204 {205 int a[] = {7, 6, 9, 3, 5, 1, 2, 4};206 int b[] = {6, 5, 8, 2, 5, 1, 2, 4};207 auto ret = std::ranges::mismatch(a, b,208 std::ranges::greater{},209 [](int i) { return i == 5 ? +100 : i; },210 [](int i) { return i == 5 ? -100 : i; });211 assert(ret.in1 == a + 5);212 assert(ret.in2 == b + 5);213 assert(*ret.in1 == 1);214 assert(*ret.in2 == 1);215 }216 {217 int a[] = {7, 6, 9, 3, 5, 1, 2, 4};218 auto ret = std::ranges::mismatch(a, a,219 std::less<double>{},220 [](int i) { return i * 1.01; },221 [c = 0](int i) mutable { return c++ < 5 ? i * 1.02 : i; });222 assert(ret.in1 == a + 5);223 assert(ret.in2 == a + 5);224 assert(*ret.in1 == 1);225 assert(*ret.in2 == 1);226 }227 {228 int a[] = {7, 6, 9, 3, 5, 1, 2, 4};229 int b[] = {6, 5, 8, 2, 5, 1, 2, 4};230 auto ret = std::ranges::mismatch(a, a + 8, b, b + 8,231 std::ranges::greater{},232 [](int i) { return i == 5 ? +100 : i; },233 [](int i) { return i == 5 ? -100 : i; });234 assert(ret.in1 == a + 5);235 assert(ret.in2 == b + 5);236 assert(*ret.in1 == 1);237 assert(*ret.in2 == 1);238 }239 {240 int a[] = {7, 6, 9, 3, 5, 1, 2, 4};241 auto ret = std::ranges::mismatch(a, a + 8, a, a + 8,242 std::less<double>{},243 [](int i) { return i * 1.01; },244 [c = 0](int i) mutable { return c++ < 5 ? i * 1.02 : i; });245 assert(ret.in1 == a + 5);246 assert(ret.in2 == a + 5);247 assert(*ret.in1 == 1);248 assert(*ret.in2 == 1);249 }250 }251 252 { // test predicate and projection call count253 {254 int pred_count = 0;255 int proj1_count = 0;256 int proj2_count = 0;257 int a[] = {7, 6, 9, 3, 5, 1, 2, 4};258 auto ret = std::ranges::mismatch(a, a,259 [&](int lhs, int rhs) { ++pred_count; return lhs == rhs; },260 [&](int i) { ++proj1_count; return i; },261 [&](int i) { ++proj2_count; return i; });262 assert(ret.in1 == a + 8);263 assert(ret.in2 == a + 8);264 assert(pred_count == 8);265 assert(proj1_count == 8);266 assert(proj2_count == 8);267 }268 {269 int pred_count = 0;270 int proj1_count = 0;271 int proj2_count = 0;272 int a[] = {7, 6, 9, 3, 5, 1, 2, 4};273 auto ret = std::ranges::mismatch(a, a + 8, a, a + 8,274 [&](int lhs, int rhs) { ++pred_count; return lhs == rhs; },275 [&](int i) { ++proj1_count; return i; },276 [&](int i) { ++proj2_count; return i; });277 assert(ret.in1 == a + 8);278 assert(ret.in2 == a + 8);279 assert(pred_count == 8);280 assert(proj1_count == 8);281 assert(proj2_count == 8);282 }283 }284 285 return true;286}287 288int main(int, char**) {289 test();290 static_assert(test());291 292 return 0;293}294