Skip to content

Commit 14ce923

Browse files
committed
Address ldionne's comments
1 parent 446da63 commit 14ce923

File tree

4 files changed

+32
-16
lines changed

4 files changed

+32
-16
lines changed

libcxx/include/__algorithm/for_each.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#ifndef _LIBCPP___ALGORITHM_FOR_EACH_H
1111
#define _LIBCPP___ALGORITHM_FOR_EACH_H
12+
1213
#include <__algorithm/for_each_segment.h>
1314
#include <__config>
1415
#include <__iterator/segmented_iterator.h>

libcxx/include/__algorithm/for_each_n.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
#include <__config>
1616
#include <__iterator/iterator_traits.h>
1717
#include <__iterator/segmented_iterator.h>
18+
#include <__type_traits/disjunction.h>
1819
#include <__type_traits/enable_if.h>
20+
#include <__type_traits/negation.h>
1921
#include <__utility/convert_to_integral.h>
2022
#include <__utility/move.h>
2123

@@ -32,11 +34,8 @@ template <class _InputIterator,
3234
class _Size,
3335
class _Func,
3436
__enable_if_t<!__has_random_access_iterator_category<_InputIterator>::value &&
35-
(!__is_segmented_iterator<_InputIterator>::value
36-
// || !__has_random_access_iterator_category<
37-
// typename __segmented_iterator_traits<_InputIterator>::__local_iterator>::value
38-
), // TODO: __segmented_iterator_traits<_InputIterator> results in template instantiation
39-
// during SFINAE, which is a hard error to be fixed. Once fixed, we should uncomment.
37+
_Or< _Not<__is_segmented_iterator<_InputIterator> >,
38+
_Not<__has_random_access_local_iterator<_InputIterator> > >::value,
4039
int> = 0>
4140
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
4241
__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f) {

libcxx/include/__iterator/segmented_iterator.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
#include <__config>
4444
#include <__cstddef/size_t.h>
45+
#include <__iterator/iterator_traits.h>
4546
#include <__type_traits/integral_constant.h>
4647

4748
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -74,6 +75,11 @@ struct __has_specialization<_Tp, sizeof(_Tp) * 0> : true_type {};
7475
template <class _Iterator>
7576
using __is_segmented_iterator _LIBCPP_NODEBUG = __has_specialization<__segmented_iterator_traits<_Iterator> >;
7677

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+
7783
_LIBCPP_END_NAMESPACE_STD
7884

7985
#endif // _LIBCPP___SEGMENTED_ITERATOR_H

libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/for_each_n.pass.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <deque>
1919
#include <functional>
2020
#include <iterator>
21+
#include <list>
2122
#include <ranges>
2223
#include <vector>
2324

@@ -46,15 +47,24 @@ struct deque_test {
4647
};
4748

4849
/*TEST_CONSTEXPR_CXX26*/
49-
void test_segmented_deque_iterator() { // TODO: Mark as TEST_CONSTEXPR_CXX26 once std::deque is constexpr
50-
// check that segmented deque iterators work properly
51-
int sizes[] = {0, 1, 2, 1023, 1024, 1025, 2047, 2048, 2049};
52-
for (const int size : sizes) {
53-
std::deque<int> d(size);
54-
int index = 0;
55-
56-
std::for_each_n(d.begin(), d.size(), deque_test(d, index));
50+
void test_deque_and_join_view_iterators() { // TODO: Mark as TEST_CONSTEXPR_CXX26 once std::deque is constexpr
51+
{ // Verify that segmented deque iterators work properly
52+
int sizes[] = {0, 1, 2, 1023, 1024, 1025, 2047, 2048, 2049};
53+
for (const int size : sizes) {
54+
std::deque<int> d(size);
55+
int index = 0;
56+
57+
std::for_each_n(d.begin(), d.size(), deque_test(d, index));
58+
}
59+
}
60+
#if TEST_STD_VER >= 20
61+
{ // Verify that join_view of lists work properly. Note that join_view of (non-random access) lists does
62+
// not produce segmented iterators.
63+
std::list<std::list<int>> lst = {{}, {0}, {1, 2}, {}, {3, 4, 5}, {6, 7, 8, 9}, {10}, {11, 12, 13}};
64+
auto v = lst | std::views::join;
65+
std::for_each_n(v.begin(), std::ranges::distance(v), [i = 0](int& a) mutable { assert(a == i++); });
5766
}
67+
#endif
5868
}
5969

6070
TEST_CONSTEXPR_CXX20 bool test() {
@@ -108,11 +118,11 @@ TEST_CONSTEXPR_CXX20 bool test() {
108118
}
109119

110120
if (!TEST_IS_CONSTANT_EVALUATED) // TODO: Use TEST_STD_AT_LEAST_26_OR_RUNTIME_EVALUATED when std::deque is made constexpr
111-
test_segmented_deque_iterator();
121+
test_deque_and_join_view_iterators();
112122

113123
#if TEST_STD_VER >= 20
114-
{
115-
std::vector<std::vector<int>> vec = {{0}, {1, 2}, {3, 4, 5}, {6, 7, 8, 9}, {10}, {11, 12, 13}};
124+
{ // join_views of (random-access) vectors yield segmented iterators
125+
std::vector<std::vector<int>> vec = {{}, {0}, {1, 2}, {}, {3, 4, 5}, {6, 7, 8, 9}, {10}, {11, 12, 13}};
116126
auto v = vec | std::views::join;
117127
std::for_each_n(v.begin(), std::ranges::distance(v), [i = 0](int& a) mutable { assert(a == i++); });
118128
}

0 commit comments

Comments
 (0)