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 <__iterator/distance.h>
18 #include <__iterator/iterator_traits.h>
19 #include <__string/constexpr_c_functions.h>
20 #include <__type_traits/desugars_to.h>
21 #include <__type_traits/enable_if.h>
22 #include <__type_traits/invoke.h>
23 #include <__type_traits/is_equality_comparable.h>
24 #include <__type_traits/is_volatile.h>
25 #include <__utility/move.h>
27 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
28 # pragma GCC system_header
32 #include <__undef_macros>
34 _LIBCPP_BEGIN_NAMESPACE_STD
36 template <class _InputIterator1
, class _InputIterator2
, class _BinaryPredicate
>
37 [[__nodiscard__
]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool __equal_iter_impl(
38 _InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _BinaryPredicate
& __pred
) {
39 for (; __first1
!= __last1
; ++__first1
, (void)++__first2
)
40 if (!__pred(*__first1
, *__first2
))
47 class _BinaryPredicate
,
48 __enable_if_t
<__desugars_to_v
<__equal_tag
, _BinaryPredicate
, _Tp
, _Up
> && !is_volatile
<_Tp
>::value
&&
49 !is_volatile
<_Up
>::value
&& __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
,
51 [[__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 [[__nodiscard__
]] 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 [[__nodiscard__
]] 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
71 template <class _Iter1
, class _Sent1
, class _Iter2
, class _Sent2
, class _Pred
, class _Proj1
, class _Proj2
>
72 [[__nodiscard__
]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool __equal_impl(
73 _Iter1 __first1
, _Sent1 __last1
, _Iter2 __first2
, _Sent2 __last2
, _Pred
& __comp
, _Proj1
& __proj1
, _Proj2
& __proj2
) {
74 while (__first1
!= __last1
&& __first2
!= __last2
) {
75 if (!std::__invoke(__comp
, std::__invoke(__proj1
, *__first1
), std::__invoke(__proj2
, *__first2
)))
80 return __first1
== __last1
&& __first2
== __last2
;
88 __enable_if_t
<__desugars_to_v
<__equal_tag
, _Pred
, _Tp
, _Up
> && __is_identity
<_Proj1
>::value
&&
89 __is_identity
<_Proj2
>::value
&& !is_volatile
<_Tp
>::value
&& !is_volatile
<_Up
>::value
&&
90 __libcpp_is_trivially_equality_comparable
<_Tp
, _Up
>::value
,
92 [[__nodiscard__
]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
93 __equal_impl(_Tp
* __first1
, _Tp
* __last1
, _Up
* __first2
, _Up
*, _Pred
&, _Proj1
&, _Proj2
&) {
94 return std::__constexpr_memcmp_equal(__first1
, __first2
, __element_count(__last1
- __first1
));
97 template <class _InputIterator1
, class _InputIterator2
, class _BinaryPredicate
>
98 [[__nodiscard__
]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
99 equal(_InputIterator1 __first1
,
100 _InputIterator1 __last1
,
101 _InputIterator2 __first2
,
102 _InputIterator2 __last2
,
103 _BinaryPredicate __pred
) {
104 if constexpr (__has_random_access_iterator_category
<_InputIterator1
>::value
&&
105 __has_random_access_iterator_category
<_InputIterator2
>::value
) {
106 if (std::distance(__first1
, __last1
) != std::distance(__first2
, __last2
))
110 return std::__equal_impl(
111 std::__unwrap_iter(__first1
),
112 std::__unwrap_iter(__last1
),
113 std::__unwrap_iter(__first2
),
114 std::__unwrap_iter(__last2
),
120 template <class _InputIterator1
, class _InputIterator2
>
121 [[__nodiscard__
]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
122 equal(_InputIterator1 __first1
, _InputIterator1 __last1
, _InputIterator2 __first2
, _InputIterator2 __last2
) {
123 return std::equal(__first1
, __last1
, __first2
, __last2
, __equal_to());
126 #endif // _LIBCPP_STD_VER >= 14
128 _LIBCPP_END_NAMESPACE_STD
132 #endif // _LIBCPP___ALGORITHM_EQUAL_H