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> |
39 | 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> |
64 | 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> |
94 | TEST_CONSTEXPR_CXX20 void operator()() { |
95 | types::for_each(TypeList(), Test<UnderlyingType, Iter1>()); |
96 | } |
97 | }; |
98 | |
99 | struct AddressCompare { |
100 | int i = 0; |
101 | TEST_CONSTEXPR_CXX20 AddressCompare(int) {} |
102 | |
103 | operator char() { return static_cast<char>(i); } |
104 | |
105 | friend TEST_CONSTEXPR_CXX20 bool operator==(const AddressCompare& lhs, const AddressCompare& rhs) { |
106 | return &lhs == &rhs; |
107 | } |
108 | |
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: |
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 | |
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> |
151 | 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> |
159 | void operator()() { |
160 | types::for_each(types::integer_types(), Test<T>()); |
161 | } |
162 | }; |
163 | |
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 | |