Skip to content

Commit b550275

Browse files
committed
[libc++] Simplify fill_n and for_each_n
1 parent f801b6f commit b550275

File tree

6 files changed

+61
-131
lines changed

6 files changed

+61
-131
lines changed

libcxx/include/__algorithm/fill.h

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <__iterator/iterator_traits.h>
1616
#include <__iterator/segmented_iterator.h>
1717
#include <__type_traits/enable_if.h>
18+
#include <__type_traits/is_same.h>
1819

1920
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2021
# pragma GCC system_header
@@ -27,33 +28,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2728
template <class _ForwardIterator, class _Sentinel, class _Tp>
2829
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
2930
__fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __value) {
31+
#ifndef _LIBCPP_CXX03_LANG
32+
if constexpr (is_same<_ForwardIterator, _Sentinel>::value && __is_segmented_iterator_v<_ForwardIterator>) {
33+
using __local_iterator_t = typename __segmented_iterator_traits<_ForwardIterator>::__local_iterator;
34+
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
35+
std::__fill(__lfirst, __llast, __value);
36+
});
37+
return __last;
38+
}
39+
#endif
3040
for (; __first != __last; ++__first)
3141
*__first = __value;
3242
return __first;
3343
}
3444

3545
template <class _RandomAccessIterator,
3646
class _Tp,
37-
__enable_if_t<__has_random_access_iterator_category<_RandomAccessIterator>::value &&
38-
!__is_segmented_iterator_v<_RandomAccessIterator>,
39-
int> = 0>
47+
__enable_if_t<__has_random_access_iterator_category<_RandomAccessIterator>::value, int> = 0>
4048
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
4149
__fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value) {
4250
return std::__fill_n(__first, __last - __first, __value);
4351
}
4452

45-
#ifndef _LIBCPP_CXX03_LANG
46-
template <class _SegmentedIterator, class _Tp, __enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0>
47-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
48-
_SegmentedIterator __fill(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value) {
49-
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
50-
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
51-
std::__fill(__lfirst, __llast, __value);
52-
});
53-
return __last;
54-
}
55-
#endif // !_LIBCPP_CXX03_LANG
56-
5753
template <class _ForwardIterator, class _Tp>
5854
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
5955
fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {

libcxx/include/__algorithm/fill_n.h

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
#include <__iterator/iterator_traits.h>
1717
#include <__iterator/segmented_iterator.h>
1818
#include <__memory/pointer_traits.h>
19-
#include <__type_traits/conjunction.h>
20-
#include <__type_traits/enable_if.h>
21-
#include <__type_traits/integral_constant.h>
22-
#include <__type_traits/negation.h>
2319
#include <__utility/convert_to_integral.h>
2420

2521
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -33,39 +29,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3329

3430
// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
3531

36-
template <class _OutputIterator,
37-
class _Size,
38-
class _Tp
39-
#ifndef _LIBCPP_CXX03_LANG
40-
,
41-
__enable_if_t<!_And<_BoolConstant<__is_segmented_iterator_v<_OutputIterator>>,
42-
__has_random_access_local_iterator<_OutputIterator>>::value,
43-
int> = 0
44-
#endif
45-
>
32+
template <class _OutputIterator, class _Size, class _Tp>
4633
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
4734
__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
35+
#ifndef _LIBCPP_CXX03_LANG
36+
if constexpr (__is_segmented_iterator_v<_OutputIterator>) {
37+
using __local_iterator = typename __segmented_iterator_traits<_OutputIterator>::__local_iterator;
38+
if constexpr (__has_random_access_iterator_category<__local_iterator>::value) {
39+
return std::__for_each_n_segment(__first, __n, [&](__local_iterator __lfirst, __local_iterator __llast) {
40+
std::__fill_n(__lfirst, __llast - __lfirst, __value);
41+
});
42+
}
43+
}
44+
#endif
4845
for (; __n > 0; ++__first, (void)--__n)
4946
*__first = __value;
5047
return __first;
5148
}
5249

53-
#ifndef _LIBCPP_CXX03_LANG
54-
template < class _OutputIterator,
55-
class _Size,
56-
class _Tp,
57-
__enable_if_t<_And<_BoolConstant<__is_segmented_iterator_v<_OutputIterator>>,
58-
__has_random_access_local_iterator<_OutputIterator>>::value,
59-
int> = 0>
60-
inline _LIBCPP_HIDE_FROM_ABI
61-
_LIBCPP_CONSTEXPR_SINCE_CXX14 _OutputIterator __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
62-
using __local_iterator_t = typename __segmented_iterator_traits<_OutputIterator>::__local_iterator;
63-
return std::__for_each_n_segment(__first, __n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
64-
std::__fill_n(__lfirst, __llast - __lfirst, __value);
65-
});
66-
}
67-
#endif // !_LIBCPP_CXX03_LANG
68-
6950
template <bool _FillVal, class _Cp>
7051
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
7152
__fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_difference_type_traits<_Cp>::size_type __n) {

libcxx/include/__algorithm/for_each.h

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
#include <__config>
1515
#include <__functional/identity.h>
1616
#include <__iterator/segmented_iterator.h>
17-
#include <__type_traits/enable_if.h>
1817
#include <__type_traits/invoke.h>
18+
#include <__type_traits/is_same.h>
1919

2020
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2121
# pragma GCC system_header
@@ -25,27 +25,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2525

2626
template <class _InputIterator, class _Sent, class _Func, class _Proj>
2727
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
28-
__for_each(_InputIterator __first, _Sent __last, _Func& __f, _Proj& __proj) {
28+
__for_each(_InputIterator __first, _Sent __last, _Func& __func, _Proj& __proj) {
29+
#ifndef _LIBCPP_CXX03_LANG
30+
if constexpr (is_same<_InputIterator, _Sent>::value && __is_segmented_iterator_v<_InputIterator>) {
31+
using __local_iterator_t = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
32+
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
33+
std::__for_each(__lfirst, __llast, __func, __proj);
34+
});
35+
return __last;
36+
}
37+
#endif
2938
for (; __first != __last; ++__first)
30-
std::__invoke(__f, std::__invoke(__proj, *__first));
39+
std::__invoke(__func, std::__invoke(__proj, *__first));
3140
return __first;
3241
}
3342

34-
#ifndef _LIBCPP_CXX03_LANG
35-
template <class _SegmentedIterator,
36-
class _Func,
37-
class _Proj,
38-
__enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0>
39-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator
40-
__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Func& __func, _Proj& __proj) {
41-
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
42-
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
43-
std::__for_each(__lfirst, __llast, __func, __proj);
44-
});
45-
return __last;
46-
}
47-
#endif // !_LIBCPP_CXX03_LANG
48-
4943
template <class _InputIterator, class _Func>
5044
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Func
5145
for_each(_InputIterator __first, _InputIterator __last, _Func __f) {

libcxx/include/__algorithm/for_each_n.h

Lines changed: 13 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616
#include <__functional/identity.h>
1717
#include <__iterator/iterator_traits.h>
1818
#include <__iterator/segmented_iterator.h>
19-
#include <__type_traits/disjunction.h>
20-
#include <__type_traits/enable_if.h>
2119
#include <__type_traits/invoke.h>
22-
#include <__type_traits/negation.h>
2320
#include <__utility/convert_to_integral.h>
2421
#include <__utility/move.h>
2522

@@ -32,18 +29,23 @@ _LIBCPP_PUSH_MACROS
3229

3330
_LIBCPP_BEGIN_NAMESPACE_STD
3431

35-
template <class _InputIterator,
36-
class _Size,
37-
class _Func,
38-
class _Proj,
39-
__enable_if_t<!__has_random_access_iterator_category<_InputIterator>::value &&
40-
_Or<integral_constant<bool, !__is_segmented_iterator_v<_InputIterator> >,
41-
_Not<__has_random_access_local_iterator<_InputIterator> > >::value,
42-
int> = 0>
32+
template <class _InputIterator, class _Size, class _Func, class _Proj>
4333
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
4434
__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
4535
typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
4636
_IntegralSize __n = __orig_n;
37+
38+
#ifndef _LIBCPP_CXX03_LANG
39+
if constexpr (__is_segmented_iterator_v<_InputIterator>) {
40+
using __local_iterator = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
41+
if constexpr (__has_random_access_iterator_category<__local_iterator>::value) {
42+
return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator __lfirst, __local_iterator __llast) {
43+
std::__for_each(__lfirst, __llast, __f, __proj);
44+
});
45+
}
46+
}
47+
#endif
48+
4749
while (__n > 0) {
4850
std::__invoke(__f, std::__invoke(__proj, *__first));
4951
++__first;
@@ -52,38 +54,6 @@ __for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj)
5254
return std::move(__first);
5355
}
5456

55-
template <class _RandIter,
56-
class _Size,
57-
class _Func,
58-
class _Proj,
59-
__enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0>
60-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandIter
61-
__for_each_n(_RandIter __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
62-
typename std::iterator_traits<_RandIter>::difference_type __n = __orig_n;
63-
auto __last = __first + __n;
64-
std::__for_each(__first, __last, __f, __proj);
65-
return __last;
66-
}
67-
68-
#ifndef _LIBCPP_CXX03_LANG
69-
template <class _SegmentedIterator,
70-
class _Size,
71-
class _Func,
72-
class _Proj,
73-
__enable_if_t<!__has_random_access_iterator_category<_SegmentedIterator>::value &&
74-
__is_segmented_iterator_v<_SegmentedIterator> &&
75-
__has_random_access_iterator_category<
76-
typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value,
77-
int> = 0>
78-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator
79-
__for_each_n(_SegmentedIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
80-
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
81-
return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
82-
std::__for_each(__lfirst, __llast, __f, __proj);
83-
});
84-
}
85-
#endif // !_LIBCPP_CXX03_LANG
86-
8757
#if _LIBCPP_STD_VER >= 17
8858

8959
template <class _InputIterator, class _Size, class _Func>

libcxx/include/__iterator/distance.h

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,35 +41,29 @@ template <class _Iter>
4141
using __iter_distance_t _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type;
4242
#endif
4343

44-
template <class _InputIter, class _Sent>
45-
inline _LIBCPP_HIDE_FROM_ABI
46-
_LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_InputIter> __distance(_InputIter __first, _Sent __last) {
47-
__iter_distance_t<_InputIter> __r(0);
48-
for (; __first != __last; ++__first)
49-
++__r;
50-
return __r;
51-
}
52-
5344
template <class _RandIter, __enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0>
5445
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_RandIter>
5546
__distance(_RandIter __first, _RandIter __last) {
5647
return __last - __first;
5748
}
5849

50+
template <class _InputIter, class _Sent>
51+
inline _LIBCPP_HIDE_FROM_ABI
52+
_LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_InputIter> __distance(_InputIter __first, _Sent __last) {
53+
__iter_distance_t<_InputIter> __r(0);
5954
#if _LIBCPP_STD_VER >= 20
60-
template <class _SegmentedIter,
61-
__enable_if_t<!__has_random_access_iterator_category<_SegmentedIter>::value &&
62-
__is_segmented_iterator_v<_SegmentedIter>,
63-
int> = 0>
64-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_SegmentedIter>
65-
__distance(_SegmentedIter __first, _SegmentedIter __last) {
66-
__iter_distance_t<_SegmentedIter> __r(0);
67-
std::__for_each_segment(__first, __last, [&__r](auto __lfirst, auto __llast) {
68-
__r += std::__distance(__lfirst, __llast);
69-
});
55+
if constexpr (same_as<_InputIter, _Sent> && __is_segmented_iterator_v<_InputIter>) {
56+
std::__for_each_segment(__first, __last, [&__r](auto __lfirst, auto __llast) {
57+
__r += std::__distance(__lfirst, __llast);
58+
});
59+
} else
60+
#endif
61+
{
62+
for (; __first != __last; ++__first)
63+
++__r;
64+
}
7065
return __r;
7166
}
72-
#endif // _LIBCPP_STD_VER >= 20
7367

7468
template <class _InputIter>
7569
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InputIter>::difference_type

libcxx/include/__iterator/segmented_iterator.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,6 @@ inline const bool __has_specialization_v<_Tp, sizeof(_Tp) * 0> = true;
7575
template <class _Iterator>
7676
inline const bool __is_segmented_iterator_v = __has_specialization_v<__segmented_iterator_traits<_Iterator> >;
7777

78-
template <class _SegmentedIterator>
79-
struct __has_random_access_local_iterator
80-
: __has_random_access_iterator_category<
81-
typename __segmented_iterator_traits< _SegmentedIterator >::__local_iterator > {};
82-
8378
_LIBCPP_END_NAMESPACE_STD
8479

8580
#endif // _LIBCPP___SEGMENTED_ITERATOR_H

0 commit comments

Comments
 (0)