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