//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // template // requires HasEqualTo // constexpr bool // constexpr after c++17 // equal(Iter1 first1, Iter1 last1, Iter2 first2); // // Introduced in C++14: // template // constexpr bool // constexpr after c++17 // equal(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2); // We test the cartesian product, so we sometimes compare differently signed types // ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-sign-compare // MSVC warning C4242: 'argument': conversion from 'int' to 'const _Ty', possible loss of data // MSVC warning C4244: 'argument': conversion from 'wchar_t' to 'const _Ty', possible loss of data // MSVC warning C4389: '==': signed/unsigned mismatch // ADDITIONAL_COMPILE_FLAGS(cl-style-warnings): /wd4242 /wd4244 /wd4389 #include #include #include #include "test_iterators.h" #include "test_macros.h" #include "type_algorithms.h" template struct Test { template TEST_CONSTEXPR_CXX20 void operator()() { UnderlyingType a[] = {0, 1, 2, 3, 4, 5}; const unsigned s = sizeof(a) / sizeof(a[0]); UnderlyingType b[s] = {0, 1, 2, 5, 4, 5}; assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a))); assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b))); #if TEST_STD_VER >= 14 assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), std::equal_to<>())); assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), std::equal_to<>())); assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s))); assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s - 1))); assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), Iter2(b + s))); assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s), std::equal_to<>())); assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s - 1), std::equal_to<>())); assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), Iter2(b + s), std::equal_to<>())); #endif } }; struct TestNarrowingEqualTo { template TEST_CONSTEXPR_CXX20 void operator()() { TEST_DIAGNOSTIC_PUSH // MSVC warning C4310: cast truncates constant value TEST_MSVC_DIAGNOSTIC_IGNORED(4310) UnderlyingType a[] = { UnderlyingType(0x1000), UnderlyingType(0x1001), UnderlyingType(0x1002), UnderlyingType(0x1003), UnderlyingType(0x1004)}; UnderlyingType b[] = { UnderlyingType(0x1600), UnderlyingType(0x1601), UnderlyingType(0x1602), UnderlyingType(0x1603), UnderlyingType(0x1604)}; TEST_DIAGNOSTIC_POP assert(std::equal(a, a + 5, b, std::equal_to())); #if TEST_STD_VER >= 14 assert(std::equal(a, a + 5, b, b + 5, std::equal_to())); #endif } }; template struct TestIter2 { template TEST_CONSTEXPR_CXX20 void operator()() { types::for_each(TypeList(), Test()); } }; struct AddressCompare { int i = 0; TEST_CONSTEXPR_CXX20 AddressCompare(int) {} operator char() { return static_cast(i); } friend TEST_CONSTEXPR_CXX20 bool operator==(const AddressCompare& lhs, const AddressCompare& rhs) { return &lhs == &rhs; } friend TEST_CONSTEXPR_CXX20 bool operator!=(const AddressCompare& lhs, const AddressCompare& rhs) { return &lhs != &rhs; } }; #if TEST_STD_VER >= 20 class trivially_equality_comparable { public: constexpr trivially_equality_comparable(int i) : i_(i) {} bool operator==(const trivially_equality_comparable&) const = default; private: int i_; }; #endif TEST_CONSTEXPR_CXX20 bool test() { types::for_each(types::cpp17_input_iterator_list(), TestIter2 >()); types::for_each( types::cpp17_input_iterator_list(), TestIter2 >()); types::for_each(types::cpp17_input_iterator_list(), TestIter2 >()); types::for_each(types::integral_types(), TestNarrowingEqualTo()); #if TEST_STD_VER >= 20 types::for_each( types::cpp17_input_iterator_list{}, TestIter2>{}); #endif return true; } struct Base {}; struct Derived : virtual Base {}; struct TestTypes { template struct Test { template void operator()() { T a[] = {1, 2, 3, 4, 5, 6}; U b[] = {1, 2, 3, 4, 5, 6}; assert(std::equal(a, a + 6, b)); } }; template void operator()() { types::for_each(types::integer_types(), Test()); } }; int main(int, char**) { test(); #if TEST_STD_VER >= 20 static_assert(test()); #endif types::for_each(types::integer_types(), TestTypes()); types::for_each(types::as_pointers >(), TestIter2 > >()); types::for_each(types::as_pointers >(), TestIter2 > >()); { Derived d; Derived* a[] = {&d, nullptr}; Base* b[] = {&d, nullptr}; assert(std::equal(a, a + 2, b)); #if TEST_STD_VER >= 14 assert(std::equal(a, a + 2, b, b + 2)); #endif } return 0; }