Skip to content

Commit 4b8c86f

Browse files
committed
fixup! WIP: [libc++][ranges] Implement ranges::stride_view.
Begin splitting iterator tests into different files. Signed-off-by: Will Hawkins <[email protected]>
1 parent d319d4c commit 4b8c86f

File tree

1 file changed

+210
-0
lines changed

1 file changed

+210
-0
lines changed
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
11+
// constexpr __iterator& operator++()
12+
// constexpr void operator++(int)
13+
// constexpr __iterator operator++(int)
14+
15+
#include <iterator>
16+
#include <vector>
17+
18+
#include "../types.h"
19+
#include "test_iterators.h"
20+
21+
template <class T>
22+
concept CanPostIncrementVoid = std::is_same_v<void, decltype(std::declval<T>()++)> && requires(T& t) { t++; };
23+
template <class T>
24+
concept CanPostIncrementIterator = std::is_same_v<T, decltype(std::declval<T>()++)> && requires(T& t) { t = t++; };
25+
template <class T>
26+
concept CanPreIncrementIterator = std::is_same_v<T&, decltype(++(std::declval<T>()))> && requires(T& t) { t = ++t; };
27+
28+
// A stride view with a base that is a non forward range returns void from operator++
29+
using InputView = BasicTestView<cpp17_input_iterator<int*>, sized_sentinel<cpp17_input_iterator<int*>>>;
30+
using StrideViewOverInputViewIterator = std::ranges::iterator_t<std::ranges::stride_view<InputView>>;
31+
static_assert(CanPostIncrementVoid<StrideViewOverInputViewIterator>);
32+
static_assert(!CanPostIncrementIterator<StrideViewOverInputViewIterator>);
33+
static_assert(CanPreIncrementIterator<StrideViewOverInputViewIterator>);
34+
35+
// A stride view with a base that is a forward range returns void from operator++
36+
using ForwardView = BasicTestView<forward_iterator<int*>, sized_sentinel<forward_iterator<int*>>>;
37+
using StrideViewOverForwardViewIterator = std::ranges::iterator_t<std::ranges::stride_view<ForwardView>>;
38+
static_assert(!CanPostIncrementVoid<StrideViewOverForwardViewIterator>);
39+
static_assert(CanPostIncrementIterator<StrideViewOverForwardViewIterator>);
40+
static_assert(CanPreIncrementIterator<StrideViewOverForwardViewIterator>);
41+
42+
template <typename Iter>
43+
requires std::sized_sentinel_for<Iter, Iter> && (!std::forward_iterator<Iter>)
44+
constexpr bool test_non_forward_operator_increment(Iter zero_begin, Iter three_begin, Iter end) {
45+
using Base = BasicTestView<Iter, Iter>;
46+
using StrideViewIterator = std::ranges::iterator_t<std::ranges::stride_view<Base>>;
47+
static_assert(std::weakly_incrementable<StrideViewIterator>);
48+
static_assert(!std::ranges::forward_range<Base>);
49+
50+
auto base_view_offset_zero = Base(zero_begin, end);
51+
auto base_view_offset_three = Base(three_begin, end);
52+
auto stride_view_over_base_zero_offset = std::ranges::stride_view(base_view_offset_zero, 3);
53+
auto stride_view_over_base_three_offset = std::ranges::stride_view(base_view_offset_three, 3);
54+
55+
auto sv_zero_offset_begin = stride_view_over_base_zero_offset.begin();
56+
auto sv_three_offset_begin = stride_view_over_base_three_offset.begin();
57+
58+
auto sv_zero_offset_third_index = sv_zero_offset_begin; // With a stride of 3, so ++ moves 3 indexes.
59+
++sv_zero_offset_third_index;
60+
assert(*sv_three_offset_begin == *sv_zero_offset_third_index);
61+
62+
sv_zero_offset_third_index = sv_zero_offset_begin;
63+
sv_zero_offset_third_index++;
64+
assert(*sv_three_offset_begin == *sv_zero_offset_third_index);
65+
66+
// See if both get to the end (with pre-increment).
67+
auto sv_zero_offset_incremented_to_end = sv_zero_offset_begin;
68+
++sv_zero_offset_incremented_to_end; // 3
69+
++sv_zero_offset_incremented_to_end; // 6
70+
++sv_zero_offset_incremented_to_end; // 9
71+
++sv_zero_offset_incremented_to_end; // End
72+
73+
auto sv_three_offset_incremented_to_end = sv_three_offset_begin; // With a stride of 3, so ++ moves 3 indexes.
74+
++sv_three_offset_incremented_to_end; // 6
75+
++sv_three_offset_incremented_to_end; // 9
76+
++sv_three_offset_incremented_to_end; // End
77+
78+
assert(sv_three_offset_incremented_to_end == sv_zero_offset_incremented_to_end);
79+
assert(sv_three_offset_incremented_to_end == stride_view_over_base_three_offset.end());
80+
assert(sv_zero_offset_incremented_to_end == stride_view_over_base_zero_offset.end());
81+
82+
// See if both get to the end (with post-increment).
83+
sv_zero_offset_incremented_to_end = sv_zero_offset_begin;
84+
sv_zero_offset_incremented_to_end++; // 3
85+
sv_zero_offset_incremented_to_end++; // 6
86+
sv_zero_offset_incremented_to_end++; // 9
87+
sv_zero_offset_incremented_to_end++; // End
88+
89+
sv_three_offset_incremented_to_end = sv_three_offset_begin; // With a stride of 3, so ++ moves 3 indexes.
90+
sv_three_offset_incremented_to_end++; // 6
91+
sv_three_offset_incremented_to_end++; // 9
92+
sv_three_offset_incremented_to_end++; // End
93+
94+
assert(sv_three_offset_incremented_to_end == sv_zero_offset_incremented_to_end);
95+
assert(sv_three_offset_incremented_to_end == stride_view_over_base_three_offset.end());
96+
assert(sv_zero_offset_incremented_to_end == stride_view_over_base_zero_offset.end());
97+
98+
return true;
99+
}
100+
101+
template <std::forward_iterator Iter>
102+
constexpr bool test_forward_operator_increment(Iter begin, Iter end) {
103+
using Base = BasicTestView<Iter, Iter>;
104+
105+
using StrideViewIterator = std::ranges::iterator_t<std::ranges::stride_view<Base>>;
106+
static_assert(std::ranges::forward_range<Base>);
107+
static_assert(std::weakly_incrementable<StrideViewIterator>);
108+
109+
auto base_view_offset_zero = Base(begin, end);
110+
auto stride_view_over_base_zero_offset = std::ranges::stride_view(base_view_offset_zero, 3);
111+
auto sv_zero_offset_begin = stride_view_over_base_zero_offset.begin();
112+
113+
// Create a ground truth for comparison.
114+
auto sv_zero_offset_third_index_key = stride_view_over_base_zero_offset.begin();
115+
sv_zero_offset_third_index_key++;
116+
117+
auto sv_zero_offset_third_index = ++sv_zero_offset_begin;
118+
assert(*sv_zero_offset_third_index == *sv_zero_offset_begin);
119+
assert(*sv_zero_offset_third_index == *sv_zero_offset_third_index_key);
120+
121+
sv_zero_offset_begin = stride_view_over_base_zero_offset.begin();
122+
sv_zero_offset_third_index = sv_zero_offset_begin;
123+
sv_zero_offset_third_index++;
124+
assert(*sv_zero_offset_third_index == *sv_zero_offset_third_index_key);
125+
126+
sv_zero_offset_begin = stride_view_over_base_zero_offset.begin();
127+
auto sv_zero_offset_incremented_to_end = sv_zero_offset_begin;
128+
++sv_zero_offset_incremented_to_end; // 3
129+
++sv_zero_offset_incremented_to_end; // 6
130+
++sv_zero_offset_incremented_to_end; // 9
131+
++sv_zero_offset_incremented_to_end; // End
132+
133+
auto sv_zero_offset_incremented_to_end_reset = sv_zero_offset_begin; // With a stride of 3, so ++ moves 3 indexes.
134+
sv_zero_offset_incremented_to_end_reset = ++sv_zero_offset_incremented_to_end_reset; // 3
135+
sv_zero_offset_incremented_to_end_reset = ++sv_zero_offset_incremented_to_end_reset; // 6
136+
sv_zero_offset_incremented_to_end_reset = ++sv_zero_offset_incremented_to_end_reset; // 9
137+
sv_zero_offset_incremented_to_end_reset = ++sv_zero_offset_incremented_to_end_reset; // End
138+
139+
assert(sv_zero_offset_incremented_to_end == sv_zero_offset_incremented_to_end_reset);
140+
assert(sv_zero_offset_incremented_to_end == stride_view_over_base_zero_offset.end());
141+
142+
sv_zero_offset_incremented_to_end = sv_zero_offset_begin;
143+
sv_zero_offset_incremented_to_end++; // 3
144+
sv_zero_offset_incremented_to_end++; // 6
145+
sv_zero_offset_incremented_to_end++; // 9
146+
sv_zero_offset_incremented_to_end++; // End
147+
assert(sv_zero_offset_incremented_to_end == stride_view_over_base_zero_offset.end());
148+
149+
return true;
150+
}
151+
152+
constexpr bool test_properly_handling_missing() {
153+
// Check whether __missing_ gets handled properly.
154+
using Base = BasicTestView<int*, int*>;
155+
int arr[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
156+
auto base = Base(arr, arr + 10);
157+
auto strider = std::ranges::stride_view<Base>(base, 7);
158+
159+
auto strider_iter = strider.end();
160+
161+
strider_iter--;
162+
assert(*strider_iter == 8);
163+
164+
// Now that we are back among the valid, we should
165+
// have a normal stride length back (i.e., __missing_
166+
// should be equal to 0).
167+
strider_iter--;
168+
assert(*strider_iter == 1);
169+
170+
strider_iter++;
171+
assert(*strider_iter == 8);
172+
173+
// By striding past the end, we are going to generate
174+
// another __missing_ != 0 value.
175+
strider_iter++;
176+
assert(strider_iter == strider.end());
177+
178+
// Make sure that all sentinel operations work!
179+
assert(strider.end() == std::default_sentinel);
180+
assert(std::default_sentinel == strider.end());
181+
182+
assert(strider_iter - std::default_sentinel == 0);
183+
assert(std::default_sentinel - strider.end() == 0);
184+
assert(std::default_sentinel - strider_iter == 0);
185+
186+
// Let's make sure that the newly regenerated __missing__ gets used.
187+
strider_iter += -2;
188+
assert(*strider_iter == 1);
189+
190+
return true;
191+
}
192+
193+
int main(int, char**) {
194+
{
195+
constexpr int arr[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
196+
std::vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
197+
test_forward_operator_increment(arr, arr + 11);
198+
test_forward_operator_increment(vec.begin(), vec.end());
199+
}
200+
201+
{
202+
int arr[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
203+
test_non_forward_operator_increment(
204+
SizedInputIterator(arr), SizedInputIterator(arr + 3), SizedInputIterator(arr + 10));
205+
}
206+
207+
test_properly_handling_missing();
208+
static_assert(test_properly_handling_missing());
209+
return 0;
210+
}

0 commit comments

Comments
 (0)