xref: /llvm-project/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp (revision b25d36c3abae945788b881defc7eff4fdb46e3a2)
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 // We test the cartesian product, so we somethimes compare differently signed types
22 // ADDITIONAL_COMPILE_FLAGS: -Wno-sign-compare
23 
24 #include <algorithm>
25 #include <cassert>
26 #include <functional>
27 
28 #include "test_iterators.h"
29 #include "test_macros.h"
30 #include "type_algorithms.h"
31 
32 template <class UnderlyingType, class Iter1>
33 struct Test {
34   template <class Iter2>
35   TEST_CONSTEXPR_CXX20 void operator()() {
36     UnderlyingType a[]  = {0, 1, 2, 3, 4, 5};
37     const unsigned s    = sizeof(a) / sizeof(a[0]);
38     UnderlyingType b[s] = {0, 1, 2, 5, 4, 5};
39 
40     assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a)));
41     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b)));
42 
43 #if TEST_STD_VER >= 14
44     assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), std::equal_to<>()));
45     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), std::equal_to<>()));
46 
47     assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s)));
48     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s - 1)));
49     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), Iter2(b + s)));
50 
51     assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s), std::equal_to<>()));
52     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s - 1), std::equal_to<>()));
53     assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), Iter2(b + s), std::equal_to<>()));
54 #endif
55   }
56 };
57 
58 struct TestNarrowingEqualTo {
59   template <class UnderlyingType>
60   TEST_CONSTEXPR_CXX20 void operator()() {
61     UnderlyingType a[] = {
62         UnderlyingType(0x1000),
63         UnderlyingType(0x1001),
64         UnderlyingType(0x1002),
65         UnderlyingType(0x1003),
66         UnderlyingType(0x1004)};
67     UnderlyingType b[] = {
68         UnderlyingType(0x1600),
69         UnderlyingType(0x1601),
70         UnderlyingType(0x1602),
71         UnderlyingType(0x1603),
72         UnderlyingType(0x1604)};
73 
74     assert(std::equal(a, a + 5, b, std::equal_to<char>()));
75 #if TEST_STD_VER >= 14
76     assert(std::equal(a, a + 5, b, b + 5, std::equal_to<char>()));
77 #endif
78   }
79 };
80 
81 template <class UnderlyingType, class TypeList>
82 struct TestIter2 {
83   template <class Iter1>
84   TEST_CONSTEXPR_CXX20 void operator()() {
85     types::for_each(TypeList(), Test<UnderlyingType, Iter1>());
86   }
87 };
88 
89 struct AddressCompare {
90   int i = 0;
91   TEST_CONSTEXPR_CXX20 AddressCompare(int) {}
92 
93   operator char() { return static_cast<char>(i); }
94 
95   friend TEST_CONSTEXPR_CXX20 bool operator==(const AddressCompare& lhs, const AddressCompare& rhs) {
96     return &lhs == &rhs;
97   }
98 
99   friend TEST_CONSTEXPR_CXX20 bool operator!=(const AddressCompare& lhs, const AddressCompare& rhs) {
100     return &lhs != &rhs;
101   }
102 };
103 
104 #if TEST_STD_VER >= 20
105 class trivially_equality_comparable {
106 public:
107   constexpr trivially_equality_comparable(int i) : i_(i) {}
108   bool operator==(const trivially_equality_comparable&) const = default;
109 
110 private:
111   int i_;
112 };
113 
114 #endif
115 
116 TEST_CONSTEXPR_CXX20 bool test() {
117   types::for_each(types::cpp17_input_iterator_list<int*>(), TestIter2<int, types::cpp17_input_iterator_list<int*> >());
118   types::for_each(
119       types::cpp17_input_iterator_list<char*>(), TestIter2<char, types::cpp17_input_iterator_list<char*> >());
120   types::for_each(types::cpp17_input_iterator_list<AddressCompare*>(),
121                   TestIter2<AddressCompare, types::cpp17_input_iterator_list<AddressCompare*> >());
122 
123   types::for_each(types::integral_types(), TestNarrowingEqualTo());
124 
125 #if TEST_STD_VER >= 20
126   types::for_each(
127       types::cpp17_input_iterator_list<trivially_equality_comparable*>{},
128       TestIter2<trivially_equality_comparable, types::cpp17_input_iterator_list<trivially_equality_comparable*>>{});
129 #endif
130 
131   return true;
132 }
133 
134 struct Base {};
135 struct Derived : virtual Base {};
136 
137 struct TestTypes {
138   template <class T>
139   struct Test {
140     template <class U>
141     void operator()() {
142       T a[] = {1, 2, 3, 4, 5, 6};
143       U b[] = {1, 2, 3, 4, 5, 6};
144       assert(std::equal(a, a + 6, b));
145     }
146   };
147 
148   template <class T>
149   void operator()() {
150     types::for_each(types::integer_types(), Test<T>());
151   }
152 };
153 
154 int main(int, char**) {
155   test();
156 #if TEST_STD_VER >= 20
157   static_assert(test());
158 #endif
159 
160   types::for_each(types::integer_types(), TestTypes());
161   types::for_each(types::as_pointers<types::cv_qualified_versions<int> >(),
162                   TestIter2<int, types::as_pointers<types::cv_qualified_versions<int> > >());
163   types::for_each(types::as_pointers<types::cv_qualified_versions<char> >(),
164                   TestIter2<char, types::as_pointers<types::cv_qualified_versions<char> > >());
165 
166   {
167     Derived d;
168     Derived* a[] = {&d, nullptr};
169     Base* b[]    = {&d, nullptr};
170 
171     assert(std::equal(a, a + 2, b));
172 #if TEST_STD_VER >= 14
173     assert(std::equal(a, a + 2, b, b + 2));
174 #endif
175   }
176 
177   return 0;
178 }
179