xref: /llvm-project/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp (revision 746cf7e38cc4c62c8deafbbac945ff6d96f2cd20)
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     types::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 #if TEST_STD_VER >= 20
102 class trivially_equality_comparable {
103 public:
104   constexpr trivially_equality_comparable(int i) : i_(i) {}
105   bool operator==(const trivially_equality_comparable&) const = default;
106 
107 private:
108   int i_;
109 };
110 
111 #endif
112 
113 TEST_CONSTEXPR_CXX20 bool test() {
114   types::for_each(types::cpp17_input_iterator_list<int*>(), TestIter2<int, types::cpp17_input_iterator_list<int*> >());
115   types::for_each(
116       types::cpp17_input_iterator_list<char*>(), TestIter2<char, types::cpp17_input_iterator_list<char*> >());
117   types::for_each(types::cpp17_input_iterator_list<AddressCompare*>(),
118                   TestIter2<AddressCompare, types::cpp17_input_iterator_list<AddressCompare*> >());
119 
120   types::for_each(types::integral_types(), TestNarrowingEqualTo());
121 
122 #if TEST_STD_VER >= 20
123   types::for_each(
124       types::cpp17_input_iterator_list<trivially_equality_comparable*>{},
125       TestIter2<trivially_equality_comparable, types::cpp17_input_iterator_list<trivially_equality_comparable*>>{});
126 #endif
127 
128   return true;
129 }
130 
131 struct Base {};
132 struct Derived : virtual Base {};
133 
134 int main(int, char**) {
135   test();
136 #if TEST_STD_VER >= 20
137   static_assert(test());
138 #endif
139 
140   types::for_each(types::as_pointers<types::cv_qualified_versions<int> >(),
141                   TestIter2<int, types::as_pointers<types::cv_qualified_versions<int> > >());
142   types::for_each(types::as_pointers<types::cv_qualified_versions<char> >(),
143                   TestIter2<char, types::as_pointers<types::cv_qualified_versions<char> > >());
144 
145   {
146     Derived d;
147     Derived* a[] = {&d, nullptr};
148     Base* b[]    = {&d, nullptr};
149 
150     assert(std::equal(a, a + 2, b));
151 #if TEST_STD_VER >= 14
152     assert(std::equal(a, a + 2, b, b + 2));
153 #endif
154   }
155 
156   return 0;
157 }
158