2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___ALGORITHM_EQUAL_H
11 #define _LIBCPP___ALGORITHM_EQUAL_H
13 #include <__cxx03/__algorithm/comp.h>
14 #include <__cxx03/__algorithm/unwrap_iter.h>
15 #include <__cxx03/__config>
16 #include <__cxx03/__functional/identity.h>
17 #include <__cxx03/__functional/invoke.h>
18 #include <__cxx03/__iterator/distance.h>
19 #include <__cxx03/__iterator/iterator_traits.h>
20 #include <__cxx03/__string/constexpr_c_functions.h>
21 #include <__cxx03/__type_traits/desugars_to.h>
22 #include <__cxx03/__type_traits/enable_if.h>
23 #include <__cxx03/__type_traits/is_constant_evaluated.h>
24 #include <__cxx03/__type_traits/is_equality_comparable.h>
25 #include <__cxx03/__type_traits/is_volatile.h>
26 #include <__cxx03/__utility/move.h>
28 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
29 # pragma GCC system_header
33 #include <__cxx03/__undef_macros>
35 _LIBCPP_BEGIN_NAMESPACE_STD
37 template <class _InputIterator1
, class _InputIterator2
, class _BinaryPredicate
>
38 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool __equal_iter_impl(
39 _InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _BinaryPredicate
& __pred
) {
40 for (; __first1
!= __last1
; ++__first1
, (void)++__first2
)
41 if (!__pred(*__first1
, *__first2
))
48 class _BinaryPredicate
,
49 __enable_if_t
<__desugars_to_v
<__equal_tag
, _BinaryPredicate
, _Tp
, _Up
> && !is_volatile
<_Tp
>::value
&&
50 !is_volatile
<_Up
>::value
&& __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
,
52 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
53 __equal_iter_impl(_Tp
* __first1
, _Tp
* __last1
, _Up
* __first2
, _BinaryPredicate
&) {
54 return std::__constexpr_memcmp_equal(__first1
, __first2
, __element_count(__last1
- __first1
));
57 template <class _InputIterator1
, class _InputIterator2
, class _BinaryPredicate
>
58 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
59 equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _BinaryPredicate __pred
) {
60 return std::__equal_iter_impl(
61 std::__unwrap_iter(__first1
), std::__unwrap_iter(__last1
), std::__unwrap_iter(__first2
), __pred
);
64 template <class _InputIterator1
, class _InputIterator2
>
65 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
66 equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
) {
67 return std::equal(__first1
, __last1
, __first2
, __equal_to());
70 #if _LIBCPP_STD_VER >= 14
72 template <class _Iter1
, class _Sent1
, class _Iter2
, class _Sent2
, class _Pred
, class _Proj1
, class _Proj2
>
73 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool __equal_impl(
74 _Iter1 __first1
, _Sent1 __last1
, _Iter2 __first2
, _Sent2 __last2
, _Pred
& __comp
, _Proj1
& __proj1
, _Proj2
& __proj2
) {
75 while (__first1
!= __last1
&& __first2
!= __last2
) {
76 if (!std::__invoke(__comp
, std::__invoke(__proj1
, *__first1
), std::__invoke(__proj2
, *__first2
)))
81 return __first1
== __last1
&& __first2
== __last2
;
89 __enable_if_t
<__desugars_to_v
<__equal_tag
, _Pred
, _Tp
, _Up
> && __is_identity
<_Proj1
>::value
&&
90 __is_identity
<_Proj2
>::value
&& !is_volatile
<_Tp
>::value
&& !is_volatile
<_Up
>::value
&&
91 __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
,
93 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
94 __equal_impl(_Tp
* __first1
, _Tp
* __last1
, _Up
* __first2
, _Up
*, _Pred
&, _Proj1
&, _Proj2
&) {
95 return std::__constexpr_memcmp_equal(__first1
, __first2
, __element_count(__last1
- __first1
));
98 template <class _InputIterator1
, class _InputIterator2
, class _BinaryPredicate
>
99 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
100 equal(_InputIterator1 __first1
,
101 _InputIterator1 __last1
,
102 _InputIterator2 __first2
,
103 _InputIterator2 __last2
,
104 _BinaryPredicate __pred
) {
105 if constexpr (__has_random_access_iterator_category
<_InputIterator1
>::value
&&
106 __has_random_access_iterator_category
<_InputIterator2
>::value
) {
107 if (std::distance(__first1
, __last1
) != std::distance(__first2
, __last2
))
111 return std::__equal_impl(
112 std::__unwrap_iter(__first1
),
113 std::__unwrap_iter(__last1
),
114 std::__unwrap_iter(__first2
),
115 std::__unwrap_iter(__last2
),
121 template <class _InputIterator1
, class _InputIterator2
>
122 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
123 equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _InputIterator2 __last2
) {
124 return std::equal(__first1
, __last1
, __first2
, __last2
, __equal_to());
127 #endif // _LIBCPP_STD_VER >= 14
129 _LIBCPP_END_NAMESPACE_STD
133 #endif // _LIBCPP___ALGORITHM_EQUAL_H