Skip to content
Draft
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
91 changes: 33 additions & 58 deletions libcxx/include/__algorithm/for_each_n.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@

#include <__algorithm/for_each.h>
#include <__algorithm/for_each_n_segment.h>
#include <__algorithm/min.h>
#include <__config>
#include <__cstddef/size_t.h>
#include <__functional/identity.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/segmented_iterator.h>
#include <__type_traits/disjunction.h>
#include <__type_traits/enable_if.h>
#include <__iterator/unreachable_sentinel.h>
#include <__type_traits/invoke.h>
#include <__type_traits/negation.h>
#include <__utility/convert_to_integral.h>
#include <__type_traits/is_same.h>
#include <__utility/exchange.h>
#include <__utility/move.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Expand All @@ -30,73 +31,47 @@
_LIBCPP_PUSH_MACROS
#include <__undef_macros>

#if _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _InputIterator,
class _Size,
class _Func,
class _Proj,
__enable_if_t<!__has_random_access_iterator_category<_InputIterator>::value &&
_Or<integral_constant<bool, !__is_segmented_iterator_v<_InputIterator> >,
_Not<__has_random_access_local_iterator<_InputIterator> > >::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
_IntegralSize __n = __orig_n;
while (__n > 0) {
std::__invoke(__f, std::__invoke(__proj, *__first));
++__first;
--__n;
template <class _Iter, class _Sent, class _Size, class _Func, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
__for_each_n(_Iter __first, _Sent __last, _Size& __n, _Func& __func, _Proj& __proj) {
if constexpr (__has_random_access_iterator_category<_Iter>::value) {
if constexpr (is_same_v<_Sent, __unreachable_sentinel_t>) {
return std::__for_each(__first, __first + std::exchange(__n, 0), __func, __proj);
} else {
auto __count = std::min<size_t>(__n, __last - __first);
__n -= __count;
return std::__for_each(__first, __first + __count, __func, __proj);
}
} else if constexpr (__is_segmented_iterator_v<_Iter>) {
return std::__for_each_n_segment(__first, __n, [&](auto __lfirst, auto __llast, _Size __max) {
std::__for_each_n(__lfirst, __llast, __max, __func, __proj);
return __max;
});
} else {
while (__n > 0 && __first != __last) {
std::__invoke(__func, std::__invoke(__proj, *__first));
++__first;
--__n;
}
return std::move(__first);
}
return std::move(__first);
}

template <class _RandIter,
class _Size,
class _Func,
class _Proj,
__enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandIter
__for_each_n(_RandIter __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
typename std::iterator_traits<_RandIter>::difference_type __n = __orig_n;
auto __last = __first + __n;
std::__for_each(__first, __last, __f, __proj);
return __last;
}

#ifndef _LIBCPP_CXX03_LANG
template <class _SegmentedIterator,
class _Size,
class _Func,
class _Proj,
__enable_if_t<!__has_random_access_iterator_category<_SegmentedIterator>::value &&
__is_segmented_iterator_v<_SegmentedIterator> &&
__has_random_access_iterator_category<
typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator
__for_each_n(_SegmentedIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
std::__for_each(__lfirst, __llast, __f, __proj);
});
}
#endif // !_LIBCPP_CXX03_LANG

#if _LIBCPP_STD_VER >= 17

template <class _InputIterator, class _Size, class _Func>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
for_each_n(_InputIterator __first, _Size __orig_n, _Func __f) {
__identity __proj;
return std::__for_each_n(__first, __orig_n, __f, __proj);
return std::__for_each_n(__first, __unreachable_sentinel, __orig_n, __f, __proj);
}

#endif // _LIBCPP_STD_VER >= 17

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_STD_VER >= 17

_LIBCPP_POP_MACROS

#endif // _LIBCPP___ALGORITHM_FOR_EACH_N_H
24 changes: 8 additions & 16 deletions libcxx/include/__algorithm/for_each_n_segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD

template <class _SegmentedIterator, class _Size, class _Functor>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
__for_each_n_segment(_SegmentedIterator __first, _Size __orig_n, _Functor __func) {
__for_each_n_segment(_SegmentedIterator __first, _Size __n, _Functor __func) {
static_assert(__is_segmented_iterator_v<_SegmentedIterator> &&
__has_random_access_iterator_category<
typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value,
"__for_each_n_segment only works with segmented iterators with random-access local iterators");
if (__orig_n <= 0)
if (__n <= 0)
return __first;

using _Traits = __segmented_iterator_traits<_SegmentedIterator>;
using __local_iter_t = typename _Traits::__local_iterator;
using __difference_t = typename std::iterator_traits<__local_iter_t>::difference_type;
__difference_t __n = __orig_n;
auto __seg = _Traits::__segment(__first);
auto __segment_iter = _Traits::__segment(__first);
auto __local_first = _Traits::__local(__first);
__local_iter_t __local_last;

__n = __func(_Traits::__local(__first), _Traits::__end(__segment_iter), __n);

while (__n > 0) {
__local_last = _Traits::__end(__seg);
auto __seg_size = __local_last - __local_first;
if (__n <= __seg_size) {
__local_last = __local_first + __n;
__func(__local_first, __local_last);
break;
}
__func(__local_first, __local_last);
__n -= __seg_size;
__local_first = _Traits::__begin(++__seg);
++__segment_iter;
__n = __func(_Traits::__begin(__segment_iter), _Traits::__end(__segment_iter), __n);
}

return _Traits::__compose(__seg, __local_last);
return _Traits::__compose(__segment_iter, __local_last);
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
5 changes: 2 additions & 3 deletions libcxx/include/__algorithm/ranges_for_each_n.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
#include <__functional/identity.h>
#include <__iterator/concepts.h>
#include <__iterator/incrementable_traits.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/projected.h>
#include <__ranges/concepts.h>
#include <__iterator/unreachable_sentinel.h>
#include <__utility/move.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Expand All @@ -40,7 +39,7 @@ struct __for_each_n {
template <input_iterator _Iter, class _Proj = identity, indirectly_unary_invocable<projected<_Iter, _Proj>> _Func>
_LIBCPP_HIDE_FROM_ABI constexpr for_each_n_result<_Iter, _Func>
operator()(_Iter __first, iter_difference_t<_Iter> __count, _Func __func, _Proj __proj = {}) const {
auto __last = std::__for_each_n(std::move(__first), __count, __func, __proj);
auto __last = std::__for_each_n(std::move(__first), __unreachable_sentinel, __count, __func, __proj);
return {std::move(__last), std::move(__func)};
}
};
Expand Down
5 changes: 0 additions & 5 deletions libcxx/include/__iterator/segmented_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,6 @@ inline const bool __has_specialization_v<_Tp, sizeof(_Tp) * 0> = true;
template <class _Iterator>
inline const bool __is_segmented_iterator_v = __has_specialization_v<__segmented_iterator_traits<_Iterator> >;

template <class _SegmentedIterator>
struct __has_random_access_local_iterator
: __has_random_access_iterator_category<
typename __segmented_iterator_traits< _SegmentedIterator >::__local_iterator > {};

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___SEGMENTED_ITERATOR_H
33 changes: 33 additions & 0 deletions libcxx/include/__iterator/unreachable_sentinel.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,46 @@

#include <__config>
#include <__iterator/concepts.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_same.h>
#include <__type_traits/remove_cvref.h>

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

_LIBCPP_BEGIN_NAMESPACE_STD

inline constexpr struct __unreachable_sentinel_t {} __unreachable_sentinel;

template <class _UnreachableSentinel,
class _Iter,
__enable_if_t<is_same<__remove_cvref_t<_UnreachableSentinel>, __unreachable_sentinel_t>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(_UnreachableSentinel&&, _Iter&&) {
return false;
}

template <class _UnreachableSentinel,
class _Iter,
__enable_if_t<is_same<__remove_cvref_t<_UnreachableSentinel>, __unreachable_sentinel_t>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(_Iter&&, _UnreachableSentinel&&) {
return false;
}

template <class _UnreachableSentinel,
class _Iter,
__enable_if_t<is_same<__remove_cvref_t<_UnreachableSentinel>, __unreachable_sentinel_t>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(_UnreachableSentinel&&, _Iter&&) {
return true;
}

template <class _UnreachableSentinel,
class _Iter,
__enable_if_t<is_same<__remove_cvref_t<_UnreachableSentinel>, __unreachable_sentinel_t>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(_Iter&&, _UnreachableSentinel&&) {
return true;
}

#if _LIBCPP_STD_VER >= 20

struct unreachable_sentinel_t {
Expand Down
Loading