Skip to content

[libc++] Forward more algorithms to the classic algorithms #114674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions libcxx/include/__algorithm/adjacent_find.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include <__algorithm/comp.h>
#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__functional/identity.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/invoke.h>
#include <__utility/move.h>

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

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Iter, class _Sent, class _BinaryPredicate>
template <class _Iter, class _Sent, class _Pred, class _Proj>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
__adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
__adjacent_find(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
if (__first == __last)
return __first;

_Iter __i = __first;
while (++__i != __last) {
if (__pred(*__first, *__i))
if (std::__invoke(__pred, std::__invoke(__proj, *__first), std::__invoke(__proj, *__i)))
return __first;
__first = __i;
}
Expand All @@ -42,7 +45,8 @@ __adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
template <class _ForwardIterator, class _BinaryPredicate>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) {
return std::__adjacent_find(std::move(__first), std::move(__last), __pred);
__identity __proj;
return std::__adjacent_find(std::move(__first), std::move(__last), __pred, __proj);
}

template <class _ForwardIterator>
Expand Down
18 changes: 14 additions & 4 deletions libcxx/include/__algorithm/all_of.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,30 @@
#define _LIBCPP___ALGORITHM_ALL_OF_H

#include <__config>
#include <__functional/identity.h>
#include <__type_traits/invoke.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
__all_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
for (; __first != __last; ++__first) {
if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
return false;
}
return true;
}

template <class _InputIterator, class _Predicate>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first)
if (!__pred(*__first))
return false;
return true;
__identity __proj;
return std::__all_of(__first, __last, __pred, __proj);
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
18 changes: 14 additions & 4 deletions libcxx/include/__algorithm/any_of.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,30 @@
#define _LIBCPP___ALGORITHM_ANY_OF_H

#include <__config>
#include <__functional/identity.h>
#include <__type_traits/invoke.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
__any_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
for (; __first != __last; ++__first) {
if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
return true;
}
return false;
}

template <class _InputIterator, class _Predicate>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first)
if (__pred(*__first))
return true;
return false;
__identity __proj;
return std::__any_of(__first, __last, __pred, __proj);
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
26 changes: 21 additions & 5 deletions libcxx/include/__algorithm/copy_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,41 @@
#define _LIBCPP___ALGORITHM_COPY_IF_H

#include <__config>
#include <__functional/identity.h>
#include <__type_traits/invoke.h>
#include <__utility/move.h>
#include <__utility/pair.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _InputIterator, class _OutputIterator, class _Predicate>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred) {
template <class _InIter, class _Sent, class _OutIter, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
__copy_if(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) {
for (; __first != __last; ++__first) {
if (__pred(*__first)) {
if (std::__invoke(__pred, std::__invoke(__proj, *__first))) {
*__result = *__first;
++__result;
}
}
return __result;
return std::make_pair(std::move(__first), std::move(__result));
}

template <class _InputIterator, class _OutputIterator, class _Predicate>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred) {
__identity __proj;
return std::__copy_if(__first, __last, __result, __pred, __proj).second;
}

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___ALGORITHM_COPY_IF_H
21 changes: 16 additions & 5 deletions libcxx/include/__algorithm/count_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,35 @@
#ifndef _LIBCPP___ALGORITHM_COUNT_IF_H
#define _LIBCPP___ALGORITHM_COUNT_IF_H

#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__functional/identity.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/invoke.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _AlgPolicy, class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __policy_iter_diff_t<_AlgPolicy, _Iter>
__count_if(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
__policy_iter_diff_t<_AlgPolicy, _Iter> __counter(0);
for (; __first != __last; ++__first) {
if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
++__counter;
}
return __counter;
}

template <class _InputIterator, class _Predicate>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
typename iterator_traits<_InputIterator>::difference_type
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
typename iterator_traits<_InputIterator>::difference_type __r(0);
for (; __first != __last; ++__first)
if (__pred(*__first))
++__r;
return __r;
__identity __proj;
return std::__count_if<_ClassicAlgPolicy>(__first, __last, __pred, __proj);
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
3 changes: 3 additions & 0 deletions libcxx/include/__algorithm/iterator_operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ struct _IterOps<_ClassicAlgPolicy> {
}
};

template <class _AlgPolicy, class _Iter>
using __policy_iter_diff_t = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>;
Comment on lines +219 to +220
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would find it clearer to instead do this at the beginning of algorithms that need it:

using _Difference = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>;

And then to use _Difference throughout. __policy_iter_diff_t introduces yet another short-name that I'd rather not have to remember. Not a blocking comment since this is somewhat subjective.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that you also have to mention typename _IterOps<_AlgPolicy>::template __difference_type<_Iter> in the declaration, which is really not easy to read IMO. FWIW I think we may want to rethink the iterator_operations.h, since it's become a quite ugly catch-all of different operations.


_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS
Expand Down
21 changes: 3 additions & 18 deletions libcxx/include/__algorithm/ranges_adjacent_find.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H
#define _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H

#include <__algorithm/adjacent_find.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/projected.h>
Expand All @@ -33,28 +33,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD

namespace ranges {
struct __adjacent_find {
template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI constexpr static _Iter
__adjacent_find_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
if (__first == __last)
return __first;

auto __i = __first;
while (++__i != __last) {
if (std::invoke(__pred, std::invoke(__proj, *__first), std::invoke(__proj, *__i)))
return __first;
__first = __i;
}
return __i;
}

template <forward_iterator _Iter,
sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_binary_predicate<projected<_Iter, _Proj>, projected<_Iter, _Proj>> _Pred = ranges::equal_to>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter
operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const {
return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj);
return std::__adjacent_find(std::move(__first), std::move(__last), __pred, __proj);
}

template <forward_range _Range,
Expand All @@ -63,7 +48,7 @@ struct __adjacent_find {
_Pred = ranges::equal_to>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const {
return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
return std::__adjacent_find(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
};

Expand Down
14 changes: 3 additions & 11 deletions libcxx/include/__algorithm/ranges_all_of.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_ALL_OF_H
#define _LIBCPP___ALGORITHM_RANGES_ALL_OF_H

#include <__algorithm/all_of.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
Expand All @@ -31,30 +32,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD

namespace ranges {
struct __all_of {
template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI constexpr static bool __all_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
for (; __first != __last; ++__first) {
if (!std::invoke(__pred, std::invoke(__proj, *__first)))
return false;
}
return true;
}

template <input_iterator _Iter,
sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj);
return std::__all_of(std::move(__first), std::move(__last), __pred, __proj);
}

template <input_range _Range,
class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool
operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
return std::__all_of(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
};

Expand Down
15 changes: 3 additions & 12 deletions libcxx/include/__algorithm/ranges_any_of.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_ANY_OF_H
#define _LIBCPP___ALGORITHM_RANGES_ANY_OF_H

#include <__algorithm/any_of.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__iterator/concepts.h>
#include <__iterator/projected.h>
#include <__ranges/access.h>
Expand All @@ -31,30 +31,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD

namespace ranges {
struct __any_of {
template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI constexpr static bool __any_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
for (; __first != __last; ++__first) {
if (std::invoke(__pred, std::invoke(__proj, *__first)))
return true;
}
return false;
}

template <input_iterator _Iter,
sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool
operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const {
return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj);
return std::__any_of(std::move(__first), std::move(__last), __pred, __proj);
}

template <input_range _Range,
class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool
operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
return std::__any_of(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
};

Expand Down
19 changes: 5 additions & 14 deletions libcxx/include/__algorithm/ranges_copy_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_IF_H
#define _LIBCPP___ALGORITHM_RANGES_COPY_IF_H

#include <__algorithm/copy_if.h>
#include <__algorithm/in_out_result.h>
#include <__config>
#include <__functional/identity.h>
Expand Down Expand Up @@ -37,18 +38,6 @@ template <class _Ip, class _Op>
using copy_if_result = in_out_result<_Ip, _Op>;

struct __copy_if {
template <class _InIter, class _Sent, class _OutIter, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI static constexpr copy_if_result<_InIter, _OutIter>
__copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) {
for (; __first != __last; ++__first) {
if (std::invoke(__pred, std::invoke(__proj, *__first))) {
*__result = *__first;
++__result;
}
}
return {std::move(__first), std::move(__result)};
}

template <input_iterator _Iter,
sentinel_for<_Iter> _Sent,
weakly_incrementable _OutIter,
Expand All @@ -57,7 +46,8 @@ struct __copy_if {
requires indirectly_copyable<_Iter, _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr copy_if_result<_Iter, _OutIter>
operator()(_Iter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const {
return __copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj);
auto __res = std::__copy_if(std::move(__first), std::move(__last), std::move(__result), __pred, __proj);
return {std::move(__res.first), std::move(__res.second)};
}

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

Expand Down
1 change: 1 addition & 0 deletions libcxx/include/__algorithm/ranges_copy_n.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace ranges {
template <class _Ip, class _Op>
using copy_n_result = in_out_result<_Ip, _Op>;

// TODO: Merge this with copy_n
struct __copy_n {
template <class _InIter, class _DiffType, class _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter>
Expand Down
Loading
Loading