xref: /llvm-project/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp (revision b4ecfd3c4675ac45d48a97590d4489a1d29c3848)
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 bool     // constexpr after c++17
14 //   equal(Iter1 first1, Iter1 last1, Iter2 first2);
15 //
16 // Introduced in C++14:
17 // template<InputIterator Iter1, InputIterator Iter2>
18 //   constexpr bool     // constexpr after c++17
19 //   equal(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2);
20 
21 #include <algorithm>
22 #include <cassert>
23 #include <functional>
24 
25 #include "test_iterators.h"
26 #include "test_macros.h"
27 #include "type_algorithms.h"
28 
29 template <class UnderlyingType, class Iter1>
30 struct Test {
31   template <class Iter2>
32   TEST_CONSTEXPR_CXX20 void operator()() {
33     UnderlyingType a[]  = {0, 1, 2, 3, 4, 5};
34     const unsigned s    = sizeof(a) / sizeof(a[0]);
35     UnderlyingType b[s] = {0, 1, 2, 5, 4, 5};
36 
37     assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a)));
38     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b)));
39 
40 #if TEST_STD_VER >= 14
41     assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), std::equal_to<>()));
42     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), std::equal_to<>()));
43 
44     assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s)));
45     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s - 1)));
46     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), Iter2(b + s)));
47 
48     assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s), std::equal_to<>()));
49     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s - 1), std::equal_to<>()));
50     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), Iter2(b + s), std::equal_to<>()));
51 #endif
52   }
53 };
54 
55 struct TestNarrowingEqualTo {
56   template <class UnderlyingType>
57   TEST_CONSTEXPR_CXX20 void operator()() {
58     UnderlyingType a[] = {
59         UnderlyingType(0x1000),
60         UnderlyingType(0x1001),
61         UnderlyingType(0x1002),
62         UnderlyingType(0x1003),
63         UnderlyingType(0x1004)};
64     UnderlyingType b[] = {
65         UnderlyingType(0x1600),
66         UnderlyingType(0x1601),
67         UnderlyingType(0x1602),
68         UnderlyingType(0x1603),
69         UnderlyingType(0x1604)};
70 
71     assert(std::equal(a, a + 5, b, std::equal_to<char>()));
72 #if TEST_STD_VER >= 14
73     assert(std::equal(a, a + 5, b, b + 5, std::equal_to<char>()));
74 #endif
75   }
76 };
77 
78 template <class UnderlyingType, class TypeList>
79 struct TestIter2 {
80   template <class Iter1>
81   TEST_CONSTEXPR_CXX20 void operator()() {
82     meta::for_each(TypeList(), Test<UnderlyingType, Iter1>());
83   }
84 };
85 
86 struct AddressCompare {
87   int i = 0;
88   TEST_CONSTEXPR_CXX20 AddressCompare(int) {}
89 
90   operator char() { return static_cast<char>(i); }
91 
92   friend TEST_CONSTEXPR_CXX20 bool operator==(const AddressCompare& lhs, const AddressCompare& rhs) {
93     return &lhs == &rhs;
94   }
95 
96   friend TEST_CONSTEXPR_CXX20 bool operator!=(const AddressCompare& lhs, const AddressCompare& rhs) {
97     return &lhs != &rhs;
98   }
99 };
100 
101 TEST_CONSTEXPR_CXX20 bool test() {
102   meta::for_each(meta::cpp17_input_iterator_list<int*>(), TestIter2<int, meta::cpp17_input_iterator_list<int*> >());
103   meta::for_each(meta::cpp17_input_iterator_list<char*>(), TestIter2<char, meta::cpp17_input_iterator_list<char*> >());
104   meta::for_each(meta::cpp17_input_iterator_list<AddressCompare*>(),
105                  TestIter2<AddressCompare, meta::cpp17_input_iterator_list<AddressCompare*> >());
106 
107   meta::for_each(meta::integral_types(), TestNarrowingEqualTo());
108 
109   return true;
110 }
111 
112 struct Base {};
113 struct Derived : virtual Base {};
114 
115 int main(int, char**) {
116   test();
117 #if TEST_STD_VER >= 20
118   static_assert(test());
119 #endif
120 
121   meta::for_each(meta::as_pointers<meta::cv_qualified_versions<int> >(),
122                  TestIter2<int, meta::as_pointers<meta::cv_qualified_versions<int> > >());
123   meta::for_each(meta::as_pointers<meta::cv_qualified_versions<char> >(),
124                  TestIter2<char, meta::as_pointers<meta::cv_qualified_versions<char> > >());
125 
126   {
127     Derived d;
128     Derived* a[] = {&d, nullptr};
129     Base* b[]    = {&d, nullptr};
130 
131     assert(std::equal(a, a + 2, b));
132 #if TEST_STD_VER >= 14
133     assert(std::equal(a, a + 2, b, b + 2));
134 #endif
135   }
136 
137   return 0;
138 }
139