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 <__algorithm/comp.h>
14 #include <__algorithm/unwrap_iter.h>
16 #include <__functional/identity.h>
17 #include <__functional/invoke.h>
18 #include <__iterator/distance.h>
19 #include <__iterator/iterator_traits.h>
20 #include <__string/constexpr_c_functions.h>
21 #include <__type_traits/enable_if.h>
22 #include <__type_traits/integral_constant.h>
23 #include <__type_traits/is_constant_evaluated.h>
24 #include <__type_traits/is_equality_comparable.h>
25 #include <__type_traits/is_volatile.h>
26 #include <__type_traits/predicate_traits.h>
27 #include <__utility/move.h>
29 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30 # pragma GCC system_header
33 _LIBCPP_BEGIN_NAMESPACE_STD
35 template <class _InputIterator1
, class _InputIterator2
, class _BinaryPredicate
>
36 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool __equal_iter_impl(
37 _InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _BinaryPredicate
& __pred
) {
38 for (; __first1
!= __last1
; ++__first1
, (void)++__first2
)
39 if (!__pred(*__first1
, *__first2
))
47 class _BinaryPredicate
,
48 __enable_if_t
<__is_trivial_equality_predicate
<_BinaryPredicate
, _Tp
, _Up
>::value
&& !is_volatile
<_Tp
>::value
&&
49 !is_volatile
<_Up
>::value
&& __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
,
51 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
52 __equal_iter_impl(_Tp
* __first1
, _Tp
* __last1
, _Up
* __first2
, _BinaryPredicate
&) {
53 return std::__constexpr_memcmp_equal(__first1
, __first2
, __element_count(__last1
- __first1
));
56 template <class _InputIterator1
, class _InputIterator2
, class _BinaryPredicate
>
57 _LIBCPP_NODISCARD_EXT
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
58 equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _BinaryPredicate __pred
) {
59 return std::__equal_iter_impl(
60 std::__unwrap_iter(__first1
), std::__unwrap_iter(__last1
), std::__unwrap_iter(__first2
), __pred
);
63 template <class _InputIterator1
, class _InputIterator2
>
64 _LIBCPP_NODISCARD_EXT
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
65 equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
) {
66 return std::equal(__first1
, __last1
, __first2
, __equal_to());
69 #if _LIBCPP_STD_VER >= 14
70 template <class _BinaryPredicate
, class _InputIterator1
, class _InputIterator2
>
71 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
72 __equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _InputIterator2 __last2
,
73 _BinaryPredicate __pred
, input_iterator_tag
, input_iterator_tag
) {
74 for (; __first1
!= __last1
&& __first2
!= __last2
; ++__first1
, (void)++__first2
)
75 if (!__pred(*__first1
, *__first2
))
77 return __first1
== __last1
&& __first2
== __last2
;
80 template <class _Iter1
, class _Sent1
, class _Iter2
, class _Sent2
, class _Pred
, class _Proj1
, class _Proj2
>
81 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool __equal_impl(
82 _Iter1 __first1
, _Sent1 __last1
, _Iter2 __first2
, _Sent2 __last2
, _Pred
& __comp
, _Proj1
& __proj1
, _Proj2
& __proj2
) {
83 while (__first1
!= __last1
&& __first2
!= __last2
) {
84 if (!std::__invoke(__comp
, std::__invoke(__proj1
, *__first1
), std::__invoke(__proj2
, *__first2
)))
89 return __first1
== __last1
&& __first2
== __last2
;
97 __enable_if_t
<__is_trivial_equality_predicate
<_Pred
, _Tp
, _Up
>::value
&& __is_identity
<_Proj1
>::value
&&
98 __is_identity
<_Proj2
>::value
&& !is_volatile
<_Tp
>::value
&& !is_volatile
<_Up
>::value
&&
99 __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
,
101 _LIBCPP_NODISCARD
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool __equal_impl(
102 _Tp
* __first1
, _Tp
* __last1
, _Up
* __first2
, _Up
*, _Pred
&, _Proj1
&, _Proj2
&) {
103 return std::__constexpr_memcmp_equal(__first1
, __first2
, __element_count(__last1
- __first1
));
106 template <class _BinaryPredicate
, class _RandomAccessIterator1
, class _RandomAccessIterator2
>
107 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
108 __equal(_RandomAccessIterator1 __first1
, _RandomAccessIterator1 __last1
, _RandomAccessIterator2 __first2
,
109 _RandomAccessIterator2 __last2
, _BinaryPredicate __pred
, random_access_iterator_tag
,
110 random_access_iterator_tag
) {
111 if (_VSTD::distance(__first1
, __last1
) != _VSTD::distance(__first2
, __last2
))
114 return std::__equal_impl(
115 std::__unwrap_iter(__first1
),
116 std::__unwrap_iter(__last1
),
117 std::__unwrap_iter(__first2
),
118 std::__unwrap_iter(__last2
),
124 template <class _InputIterator1
, class _InputIterator2
, class _BinaryPredicate
>
125 _LIBCPP_NODISCARD_EXT
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
126 equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _InputIterator2 __last2
,
127 _BinaryPredicate __pred
) {
128 return _VSTD::__equal
<_BinaryPredicate
&>(
129 __first1
, __last1
, __first2
, __last2
, __pred
, typename iterator_traits
<_InputIterator1
>::iterator_category(),
130 typename iterator_traits
<_InputIterator2
>::iterator_category());
133 template <class _InputIterator1
, class _InputIterator2
>
134 _LIBCPP_NODISCARD_EXT
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
135 equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _InputIterator2 __last2
) {
142 typename iterator_traits
<_InputIterator1
>::iterator_category(),
143 typename iterator_traits
<_InputIterator2
>::iterator_category());
147 _LIBCPP_END_NAMESPACE_STD
149 #endif // _LIBCPP___ALGORITHM_EQUAL_H