Skip to content

Commit 962695a

Browse files
committed
[libcxx] Optimize std::generate for segmented iterators
1 parent 7eee672 commit 962695a

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

libcxx/include/__algorithm/generate.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,44 @@
99
#ifndef _LIBCPP___ALGORITHM_GENERATE_H
1010
#define _LIBCPP___ALGORITHM_GENERATE_H
1111

12+
#include <__algorithm/for_each_segment.h>
1213
#include <__config>
14+
#include <__iterator/segmented_iterator.h>
15+
#include <__type_traits/enable_if.h>
1316

1417
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1518
# pragma GCC system_header
1619
#endif
1720

1821
_LIBCPP_BEGIN_NAMESPACE_STD
1922

20-
template <class _ForwardIterator, class _Generator>
23+
template <class _ForwardIterator, class _Sent, class _Generator>
2124
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
22-
generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
25+
__generate(_ForwardIterator __first, _Sent __last, _Generator __gen) {
2326
for (; __first != __last; ++__first)
2427
*__first = __gen();
2528
}
2629

30+
#ifndef _LIBCPP_CXX03_LANG
31+
template <class _SegmentedIterator,
32+
class _Generator,
33+
__enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0>
34+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
35+
_SegmentedIterator __generate(_SegmentedIterator __first, _SegmentedIterator __last, _Generator& __gen) {
36+
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
37+
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
38+
std::__generate(__lfirst, __llast, __gen);
39+
});
40+
return __last;
41+
}
42+
#endif // !_LIBCPP_CXX03_LANG
43+
44+
template <class _ForwardIterator, class _Generator>
45+
inline _LIBCPP_HIDE_FROM_ABI
46+
_LIBCPP_CONSTEXPR_SINCE_CXX20 void generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
47+
std::__generate(__first, __last, __gen);
48+
}
49+
2750
_LIBCPP_END_NAMESPACE_STD
2851

2952
#endif // _LIBCPP___ALGORITHM_GENERATE_H

libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <algorithm>
1818
#include <cassert>
19+
#include <deque>
1920

2021
#include "test_macros.h"
2122
#include "test_iterators.h"
@@ -51,12 +52,22 @@ test()
5152
assert(ia[3] == 1);
5253
}
5354

55+
void deque_test() {
56+
int sizes[] = {0, 1, 2, 1023, 1024, 1025, 2047, 2048, 2049};
57+
for (const int size : sizes) {
58+
std::deque<int> d(size);
59+
std::generate(d.begin(), d.end(), gen_test());
60+
assert(std::all_of(d.begin(), d.end(), [](int x) { return x == 1; }));
61+
}
62+
}
63+
5464
int main(int, char**)
5565
{
5666
test<forward_iterator<int*> >();
5767
test<bidirectional_iterator<int*> >();
5868
test<random_access_iterator<int*> >();
5969
test<int*>();
70+
deque_test();
6071

6172
#if TEST_STD_VER > 17
6273
static_assert(test_constexpr());

0 commit comments

Comments
 (0)