1e78f53d1SNikolas Klauser // -*- C++ -*- 2e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 3e78f53d1SNikolas Klauser // 4e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 6e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7e78f53d1SNikolas Klauser // 8e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 9e78f53d1SNikolas Klauser 10*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___ALGORITHM_EQUAL_H 11*ce777190SNikolas Klauser #define _LIBCPP___CXX03___ALGORITHM_EQUAL_H 12e78f53d1SNikolas Klauser 1373fbae83SNikolas Klauser #include <__cxx03/__algorithm/comp.h> 1473fbae83SNikolas Klauser #include <__cxx03/__algorithm/unwrap_iter.h> 1573fbae83SNikolas Klauser #include <__cxx03/__config> 1673fbae83SNikolas Klauser #include <__cxx03/__functional/identity.h> 1773fbae83SNikolas Klauser #include <__cxx03/__functional/invoke.h> 1873fbae83SNikolas Klauser #include <__cxx03/__iterator/distance.h> 1973fbae83SNikolas Klauser #include <__cxx03/__iterator/iterator_traits.h> 2073fbae83SNikolas Klauser #include <__cxx03/__string/constexpr_c_functions.h> 2173fbae83SNikolas Klauser #include <__cxx03/__type_traits/desugars_to.h> 2273fbae83SNikolas Klauser #include <__cxx03/__type_traits/enable_if.h> 2373fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_constant_evaluated.h> 2473fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_equality_comparable.h> 2573fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_volatile.h> 2673fbae83SNikolas Klauser #include <__cxx03/__utility/move.h> 27e78f53d1SNikolas Klauser 28e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 29e78f53d1SNikolas Klauser # pragma GCC system_header 30e78f53d1SNikolas Klauser #endif 31e78f53d1SNikolas Klauser 32e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS 3373fbae83SNikolas Klauser #include <__cxx03/__undef_macros> 34e78f53d1SNikolas Klauser 35e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 36e78f53d1SNikolas Klauser 37e78f53d1SNikolas Klauser template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> 38e78f53d1SNikolas Klauser _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl( 39e78f53d1SNikolas Klauser _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) { 40e78f53d1SNikolas Klauser for (; __first1 != __last1; ++__first1, (void)++__first2) 41e78f53d1SNikolas Klauser if (!__pred(*__first1, *__first2)) 42e78f53d1SNikolas Klauser return false; 43e78f53d1SNikolas Klauser return true; 44e78f53d1SNikolas Klauser } 45e78f53d1SNikolas Klauser 46e78f53d1SNikolas Klauser template <class _Tp, 47e78f53d1SNikolas Klauser class _Up, 48e78f53d1SNikolas Klauser class _BinaryPredicate, 49e78f53d1SNikolas Klauser __enable_if_t<__desugars_to_v<__equal_tag, _BinaryPredicate, _Tp, _Up> && !is_volatile<_Tp>::value && 50e78f53d1SNikolas Klauser !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, 51e78f53d1SNikolas Klauser int> = 0> 52e78f53d1SNikolas Klauser _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool 53e78f53d1SNikolas Klauser __equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) { 54e78f53d1SNikolas Klauser return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); 55e78f53d1SNikolas Klauser } 56e78f53d1SNikolas Klauser 57e78f53d1SNikolas Klauser template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> 58e78f53d1SNikolas Klauser _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool 59e78f53d1SNikolas Klauser equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { 60e78f53d1SNikolas Klauser return std::__equal_iter_impl( 61e78f53d1SNikolas Klauser std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred); 62e78f53d1SNikolas Klauser } 63e78f53d1SNikolas Klauser 64e78f53d1SNikolas Klauser template <class _InputIterator1, class _InputIterator2> 65e78f53d1SNikolas Klauser _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool 66e78f53d1SNikolas Klauser equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { 67e78f53d1SNikolas Klauser return std::equal(__first1, __last1, __first2, __equal_to()); 68e78f53d1SNikolas Klauser } 69e78f53d1SNikolas Klauser 70e78f53d1SNikolas Klauser #if _LIBCPP_STD_VER >= 14 71e78f53d1SNikolas Klauser 72e78f53d1SNikolas Klauser template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> 73e78f53d1SNikolas Klauser _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( 74e78f53d1SNikolas Klauser _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __comp, _Proj1& __proj1, _Proj2& __proj2) { 75e78f53d1SNikolas Klauser while (__first1 != __last1 && __first2 != __last2) { 76e78f53d1SNikolas Klauser if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) 77e78f53d1SNikolas Klauser return false; 78e78f53d1SNikolas Klauser ++__first1; 79e78f53d1SNikolas Klauser ++__first2; 80e78f53d1SNikolas Klauser } 81e78f53d1SNikolas Klauser return __first1 == __last1 && __first2 == __last2; 82e78f53d1SNikolas Klauser } 83e78f53d1SNikolas Klauser 84e78f53d1SNikolas Klauser template <class _Tp, 85e78f53d1SNikolas Klauser class _Up, 86e78f53d1SNikolas Klauser class _Pred, 87e78f53d1SNikolas Klauser class _Proj1, 88e78f53d1SNikolas Klauser class _Proj2, 89e78f53d1SNikolas Klauser __enable_if_t<__desugars_to_v<__equal_tag, _Pred, _Tp, _Up> && __is_identity<_Proj1>::value && 90e78f53d1SNikolas Klauser __is_identity<_Proj2>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value && 91e78f53d1SNikolas Klauser __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, 92e78f53d1SNikolas Klauser int> = 0> 93e78f53d1SNikolas Klauser _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool 94e78f53d1SNikolas Klauser __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) { 95e78f53d1SNikolas Klauser return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); 96e78f53d1SNikolas Klauser } 97e78f53d1SNikolas Klauser 98e78f53d1SNikolas Klauser template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> 99e78f53d1SNikolas Klauser _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool 100e78f53d1SNikolas Klauser equal(_InputIterator1 __first1, 101e78f53d1SNikolas Klauser _InputIterator1 __last1, 102e78f53d1SNikolas Klauser _InputIterator2 __first2, 103e78f53d1SNikolas Klauser _InputIterator2 __last2, 104e78f53d1SNikolas Klauser _BinaryPredicate __pred) { 105e78f53d1SNikolas Klauser if constexpr (__has_random_access_iterator_category<_InputIterator1>::value && 106e78f53d1SNikolas Klauser __has_random_access_iterator_category<_InputIterator2>::value) { 107e78f53d1SNikolas Klauser if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) 108e78f53d1SNikolas Klauser return false; 109e78f53d1SNikolas Klauser } 110e78f53d1SNikolas Klauser __identity __proj; 111e78f53d1SNikolas Klauser return std::__equal_impl( 112e78f53d1SNikolas Klauser std::__unwrap_iter(__first1), 113e78f53d1SNikolas Klauser std::__unwrap_iter(__last1), 114e78f53d1SNikolas Klauser std::__unwrap_iter(__first2), 115e78f53d1SNikolas Klauser std::__unwrap_iter(__last2), 116e78f53d1SNikolas Klauser __pred, 117e78f53d1SNikolas Klauser __proj, 118e78f53d1SNikolas Klauser __proj); 119e78f53d1SNikolas Klauser } 120e78f53d1SNikolas Klauser 121e78f53d1SNikolas Klauser template <class _InputIterator1, class _InputIterator2> 122e78f53d1SNikolas Klauser _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool 123e78f53d1SNikolas Klauser equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { 124e78f53d1SNikolas Klauser return std::equal(__first1, __last1, __first2, __last2, __equal_to()); 125e78f53d1SNikolas Klauser } 126e78f53d1SNikolas Klauser 127e78f53d1SNikolas Klauser #endif // _LIBCPP_STD_VER >= 14 128e78f53d1SNikolas Klauser 129e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 130e78f53d1SNikolas Klauser 131e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS 132e78f53d1SNikolas Klauser 133*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___ALGORITHM_EQUAL_H 134