Skip to content

Commit e5f93ea

Browse files
committed
[libc++] Simplify fill_n and for_each_n
1 parent a242a20 commit e5f93ea

File tree

6 files changed

+68
-132
lines changed

6 files changed

+68
-132
lines changed

libcxx/include/__algorithm/fill.h

Lines changed: 10 additions & 12 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,6 +28,15 @@ _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;
@@ -42,18 +52,6 @@ __fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& _
4252
return std::__fill_n(__first, __last - __first, __value);
4353
}
4454

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-
5755
template <class _ForwardIterator, class _Tp>
5856
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
5957
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: 20 additions & 47 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,57 +29,33 @@ _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;
47-
while (__n > 0) {
48-
std::__invoke(__f, std::__invoke(__proj, *__first));
49-
++__first;
50-
--__n;
51-
}
52-
return std::move(__first);
53-
}
54-
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-
}
6737

6838
#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-
});
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+
} else {
46+
return std::__for_each(__first, __first + __n, __f, __proj);
47+
}
48+
} else
49+
#endif
50+
{
51+
while (__n > 0) {
52+
std::__invoke(__f, std::__invoke(__proj, *__first));
53+
++__first;
54+
--__n;
55+
}
56+
return std::move(__first);
57+
}
8458
}
85-
#endif // !_LIBCPP_CXX03_LANG
8659

8760
#if _LIBCPP_STD_VER >= 17
8861

libcxx/include/__iterator/distance.h

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define _LIBCPP___ITERATOR_DISTANCE_H
1212

1313
#include <__algorithm/for_each_segment.h>
14+
#include <__concepts/same_as.h>
1415
#include <__config>
1516
#include <__iterator/concepts.h>
1617
#include <__iterator/incrementable_traits.h>
@@ -41,35 +42,29 @@ template <class _Iter>
4142
using __iter_distance_t _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type;
4243
#endif
4344

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-
5345
template <class _RandIter, __enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0>
5446
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_RandIter>
5547
__distance(_RandIter __first, _RandIter __last) {
5648
return __last - __first;
5749
}
5850

51+
template <class _InputIter, class _Sent>
52+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_InputIter>
53+
__distance(_InputIter __first, _Sent __last) {
54+
__iter_distance_t<_InputIter> __r(0);
5955
#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-
});
56+
if constexpr (same_as<_InputIter, _Sent> && __is_segmented_iterator_v<_InputIter>) {
57+
std::__for_each_segment(__first, __last, [&__r](auto __lfirst, auto __llast) {
58+
__r += std::__distance(__lfirst, __llast);
59+
});
60+
} else
61+
#endif
62+
{
63+
for (; __first != __last; ++__first)
64+
++__r;
65+
}
7066
return __r;
7167
}
72-
#endif // _LIBCPP_STD_VER >= 20
7368

7469
template <class _InputIter>
7570
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)