Skip to content

Commit eab7be5

Browse files
authored
[libc++] Forward more algorithms to the classic algorithms (#114674)
This partially addresses #105687.
1 parent 56077e5 commit eab7be5

14 files changed

+101
-97
lines changed

libcxx/include/__algorithm/adjacent_find.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include <__algorithm/comp.h>
1414
#include <__algorithm/iterator_operations.h>
1515
#include <__config>
16+
#include <__functional/identity.h>
1617
#include <__iterator/iterator_traits.h>
18+
#include <__type_traits/invoke.h>
1719
#include <__utility/move.h>
1820

1921
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -25,14 +27,15 @@ _LIBCPP_PUSH_MACROS
2527

2628
_LIBCPP_BEGIN_NAMESPACE_STD
2729

28-
template <class _Iter, class _Sent, class _BinaryPredicate>
30+
template <class _Iter, class _Sent, class _Pred, class _Proj>
2931
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
30-
__adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
32+
__adjacent_find(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
3133
if (__first == __last)
3234
return __first;
35+
3336
_Iter __i = __first;
3437
while (++__i != __last) {
35-
if (__pred(*__first, *__i))
38+
if (std::__invoke(__pred, std::__invoke(__proj, *__first), std::__invoke(__proj, *__i)))
3639
return __first;
3740
__first = __i;
3841
}
@@ -42,7 +45,8 @@ __adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
4245
template <class _ForwardIterator, class _BinaryPredicate>
4346
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
4447
adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) {
45-
return std::__adjacent_find(std::move(__first), std::move(__last), __pred);
48+
__identity __proj;
49+
return std::__adjacent_find(std::move(__first), std::move(__last), __pred, __proj);
4650
}
4751

4852
template <class _ForwardIterator>

libcxx/include/__algorithm/all_of.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,30 @@
1111
#define _LIBCPP___ALGORITHM_ALL_OF_H
1212

1313
#include <__config>
14+
#include <__functional/identity.h>
15+
#include <__type_traits/invoke.h>
1416

1517
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1618
# pragma GCC system_header
1719
#endif
1820

1921
_LIBCPP_BEGIN_NAMESPACE_STD
2022

23+
template <class _Iter, class _Sent, class _Proj, class _Pred>
24+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
25+
__all_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
26+
for (; __first != __last; ++__first) {
27+
if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
28+
return false;
29+
}
30+
return true;
31+
}
32+
2133
template <class _InputIterator, class _Predicate>
2234
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
2335
all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
24-
for (; __first != __last; ++__first)
25-
if (!__pred(*__first))
26-
return false;
27-
return true;
36+
__identity __proj;
37+
return std::__all_of(__first, __last, __pred, __proj);
2838
}
2939

3040
_LIBCPP_END_NAMESPACE_STD

libcxx/include/__algorithm/any_of.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,30 @@
1111
#define _LIBCPP___ALGORITHM_ANY_OF_H
1212

1313
#include <__config>
14+
#include <__functional/identity.h>
15+
#include <__type_traits/invoke.h>
1416

1517
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1618
# pragma GCC system_header
1719
#endif
1820

1921
_LIBCPP_BEGIN_NAMESPACE_STD
2022

23+
template <class _Iter, class _Sent, class _Proj, class _Pred>
24+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
25+
__any_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
26+
for (; __first != __last; ++__first) {
27+
if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
28+
return true;
29+
}
30+
return false;
31+
}
32+
2133
template <class _InputIterator, class _Predicate>
2234
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
2335
any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
24-
for (; __first != __last; ++__first)
25-
if (__pred(*__first))
26-
return true;
27-
return false;
36+
__identity __proj;
37+
return std::__any_of(__first, __last, __pred, __proj);
2838
}
2939

3040
_LIBCPP_END_NAMESPACE_STD

libcxx/include/__algorithm/copy_if.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,41 @@
1010
#define _LIBCPP___ALGORITHM_COPY_IF_H
1111

1212
#include <__config>
13+
#include <__functional/identity.h>
14+
#include <__type_traits/invoke.h>
15+
#include <__utility/move.h>
16+
#include <__utility/pair.h>
1317

1418
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1519
# pragma GCC system_header
1620
#endif
1721

22+
_LIBCPP_PUSH_MACROS
23+
#include <__undef_macros>
24+
1825
_LIBCPP_BEGIN_NAMESPACE_STD
1926

20-
template <class _InputIterator, class _OutputIterator, class _Predicate>
21-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
22-
copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred) {
27+
template <class _InIter, class _Sent, class _OutIter, class _Proj, class _Pred>
28+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
29+
__copy_if(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) {
2330
for (; __first != __last; ++__first) {
24-
if (__pred(*__first)) {
31+
if (std::__invoke(__pred, std::__invoke(__proj, *__first))) {
2532
*__result = *__first;
2633
++__result;
2734
}
2835
}
29-
return __result;
36+
return std::make_pair(std::move(__first), std::move(__result));
37+
}
38+
39+
template <class _InputIterator, class _OutputIterator, class _Predicate>
40+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
41+
copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred) {
42+
__identity __proj;
43+
return std::__copy_if(__first, __last, __result, __pred, __proj).second;
3044
}
3145

3246
_LIBCPP_END_NAMESPACE_STD
3347

48+
_LIBCPP_POP_MACROS
49+
3450
#endif // _LIBCPP___ALGORITHM_COPY_IF_H

libcxx/include/__algorithm/count_if.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,35 @@
1010
#ifndef _LIBCPP___ALGORITHM_COUNT_IF_H
1111
#define _LIBCPP___ALGORITHM_COUNT_IF_H
1212

13+
#include <__algorithm/iterator_operations.h>
1314
#include <__config>
15+
#include <__functional/identity.h>
1416
#include <__iterator/iterator_traits.h>
17+
#include <__type_traits/invoke.h>
1518

1619
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1720
# pragma GCC system_header
1821
#endif
1922

2023
_LIBCPP_BEGIN_NAMESPACE_STD
2124

25+
template <class _AlgPolicy, class _Iter, class _Sent, class _Proj, class _Pred>
26+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __policy_iter_diff_t<_AlgPolicy, _Iter>
27+
__count_if(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
28+
__policy_iter_diff_t<_AlgPolicy, _Iter> __counter(0);
29+
for (; __first != __last; ++__first) {
30+
if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
31+
++__counter;
32+
}
33+
return __counter;
34+
}
35+
2236
template <class _InputIterator, class _Predicate>
2337
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
2438
typename iterator_traits<_InputIterator>::difference_type
2539
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
26-
typename iterator_traits<_InputIterator>::difference_type __r(0);
27-
for (; __first != __last; ++__first)
28-
if (__pred(*__first))
29-
++__r;
30-
return __r;
40+
__identity __proj;
41+
return std::__count_if<_ClassicAlgPolicy>(__first, __last, __pred, __proj);
3142
}
3243

3344
_LIBCPP_END_NAMESPACE_STD

libcxx/include/__algorithm/iterator_operations.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ struct _IterOps<_ClassicAlgPolicy> {
216216
}
217217
};
218218

219+
template <class _AlgPolicy, class _Iter>
220+
using __policy_iter_diff_t = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>;
221+
219222
_LIBCPP_END_NAMESPACE_STD
220223

221224
_LIBCPP_POP_MACROS

libcxx/include/__algorithm/ranges_adjacent_find.h

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
#ifndef _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H
1010
#define _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H
1111

12+
#include <__algorithm/adjacent_find.h>
1213
#include <__config>
1314
#include <__functional/identity.h>
14-
#include <__functional/invoke.h>
1515
#include <__functional/ranges_operations.h>
1616
#include <__iterator/concepts.h>
1717
#include <__iterator/projected.h>
@@ -33,28 +33,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3333

3434
namespace ranges {
3535
struct __adjacent_find {
36-
template <class _Iter, class _Sent, class _Proj, class _Pred>
37-
_LIBCPP_HIDE_FROM_ABI constexpr static _Iter
38-
__adjacent_find_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
39-
if (__first == __last)
40-
return __first;
41-
42-
auto __i = __first;
43-
while (++__i != __last) {
44-
if (std::invoke(__pred, std::invoke(__proj, *__first), std::invoke(__proj, *__i)))
45-
return __first;
46-
__first = __i;
47-
}
48-
return __i;
49-
}
50-
5136
template <forward_iterator _Iter,
5237
sentinel_for<_Iter> _Sent,
5338
class _Proj = identity,
5439
indirect_binary_predicate<projected<_Iter, _Proj>, projected<_Iter, _Proj>> _Pred = ranges::equal_to>
5540
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter
5641
operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const {
57-
return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj);
42+
return std::__adjacent_find(std::move(__first), std::move(__last), __pred, __proj);
5843
}
5944

6045
template <forward_range _Range,
@@ -63,7 +48,7 @@ struct __adjacent_find {
6348
_Pred = ranges::equal_to>
6449
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range>
6550
operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const {
66-
return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
51+
return std::__adjacent_find(ranges::begin(__range), ranges::end(__range), __pred, __proj);
6752
}
6853
};
6954

libcxx/include/__algorithm/ranges_all_of.h

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef _LIBCPP___ALGORITHM_RANGES_ALL_OF_H
1010
#define _LIBCPP___ALGORITHM_RANGES_ALL_OF_H
1111

12+
#include <__algorithm/all_of.h>
1213
#include <__config>
1314
#include <__functional/identity.h>
1415
#include <__functional/invoke.h>
@@ -31,30 +32,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3132

3233
namespace ranges {
3334
struct __all_of {
34-
template <class _Iter, class _Sent, class _Proj, class _Pred>
35-
_LIBCPP_HIDE_FROM_ABI constexpr static bool __all_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
36-
for (; __first != __last; ++__first) {
37-
if (!std::invoke(__pred, std::invoke(__proj, *__first)))
38-
return false;
39-
}
40-
return true;
41-
}
42-
4335
template <input_iterator _Iter,
4436
sentinel_for<_Iter> _Sent,
4537
class _Proj = identity,
4638
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
4739
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool
4840
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
49-
return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj);
41+
return std::__all_of(std::move(__first), std::move(__last), __pred, __proj);
5042
}
5143

5244
template <input_range _Range,
5345
class _Proj = identity,
5446
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
5547
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool
5648
operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
57-
return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
49+
return std::__all_of(ranges::begin(__range), ranges::end(__range), __pred, __proj);
5850
}
5951
};
6052

libcxx/include/__algorithm/ranges_any_of.h

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
#ifndef _LIBCPP___ALGORITHM_RANGES_ANY_OF_H
1010
#define _LIBCPP___ALGORITHM_RANGES_ANY_OF_H
1111

12+
#include <__algorithm/any_of.h>
1213
#include <__config>
1314
#include <__functional/identity.h>
14-
#include <__functional/invoke.h>
1515
#include <__iterator/concepts.h>
1616
#include <__iterator/projected.h>
1717
#include <__ranges/access.h>
@@ -31,30 +31,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3131

3232
namespace ranges {
3333
struct __any_of {
34-
template <class _Iter, class _Sent, class _Proj, class _Pred>
35-
_LIBCPP_HIDE_FROM_ABI constexpr static bool __any_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
36-
for (; __first != __last; ++__first) {
37-
if (std::invoke(__pred, std::invoke(__proj, *__first)))
38-
return true;
39-
}
40-
return false;
41-
}
42-
4334
template <input_iterator _Iter,
4435
sentinel_for<_Iter> _Sent,
4536
class _Proj = identity,
4637
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
4738
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool
4839
operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const {
49-
return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj);
40+
return std::__any_of(std::move(__first), std::move(__last), __pred, __proj);
5041
}
5142

5243
template <input_range _Range,
5344
class _Proj = identity,
5445
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
5546
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool
5647
operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
57-
return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
48+
return std::__any_of(ranges::begin(__range), ranges::end(__range), __pred, __proj);
5849
}
5950
};
6051

libcxx/include/__algorithm/ranges_copy_if.h

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_IF_H
1010
#define _LIBCPP___ALGORITHM_RANGES_COPY_IF_H
1111

12+
#include <__algorithm/copy_if.h>
1213
#include <__algorithm/in_out_result.h>
1314
#include <__config>
1415
#include <__functional/identity.h>
@@ -37,18 +38,6 @@ template <class _Ip, class _Op>
3738
using copy_if_result = in_out_result<_Ip, _Op>;
3839

3940
struct __copy_if {
40-
template <class _InIter, class _Sent, class _OutIter, class _Proj, class _Pred>
41-
_LIBCPP_HIDE_FROM_ABI static constexpr copy_if_result<_InIter, _OutIter>
42-
__copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) {
43-
for (; __first != __last; ++__first) {
44-
if (std::invoke(__pred, std::invoke(__proj, *__first))) {
45-
*__result = *__first;
46-
++__result;
47-
}
48-
}
49-
return {std::move(__first), std::move(__result)};
50-
}
51-
5241
template <input_iterator _Iter,
5342
sentinel_for<_Iter> _Sent,
5443
weakly_incrementable _OutIter,
@@ -57,7 +46,8 @@ struct __copy_if {
5746
requires indirectly_copyable<_Iter, _OutIter>
5847
_LIBCPP_HIDE_FROM_ABI constexpr copy_if_result<_Iter, _OutIter>
5948
operator()(_Iter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const {
60-
return __copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj);
49+
auto __res = std::__copy_if(std::move(__first), std::move(__last), std::move(__result), __pred, __proj);
50+
return {std::move(__res.first), std::move(__res.second)};
6151
}
6252

6353
template <input_range _Range,
@@ -67,7 +57,8 @@ struct __copy_if {
6757
requires indirectly_copyable<iterator_t<_Range>, _OutIter>
6858
_LIBCPP_HIDE_FROM_ABI constexpr copy_if_result<borrowed_iterator_t<_Range>, _OutIter>
6959
operator()(_Range&& __r, _OutIter __result, _Pred __pred, _Proj __proj = {}) const {
70-
return __copy_if_impl(ranges::begin(__r), ranges::end(__r), std::move(__result), __pred, __proj);
60+
auto __res = std::__copy_if(ranges::begin(__r), ranges::end(__r), std::move(__result), __pred, __proj);
61+
return {std::move(__res.first), std::move(__res.second)};
7162
}
7263
};
7364

libcxx/include/__algorithm/ranges_copy_n.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace ranges {
3737
template <class _Ip, class _Op>
3838
using copy_n_result = in_out_result<_Ip, _Op>;
3939

40+
// TODO: Merge this with copy_n
4041
struct __copy_n {
4142
template <class _InIter, class _DiffType, class _OutIter>
4243
_LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter>

0 commit comments

Comments
 (0)