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
10 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11
12 // ranges::advance(it, sent)
13
14 #include <iterator>
15
16 #include <cassert>
17 #include <cstddef>
18
19 #include "../types.h"
20 #include "test_iterators.h"
21 #include "test_macros.h"
22
23 template <bool Count, class It>
check_assignable(int * first,int * last,int * expected)24 constexpr void check_assignable(int* first, int* last, int* expected) {
25 {
26 It it(first);
27 auto sent = assignable_sentinel(It(last));
28 std::ranges::advance(it, sent);
29 ASSERT_SAME_TYPE(decltype(std::ranges::advance(it, sent)), void);
30 assert(base(it) == expected);
31 }
32
33 // Count operations
34 if constexpr (Count) {
35 auto it = stride_counting_iterator(It(first));
36 auto sent = assignable_sentinel(stride_counting_iterator(It(last)));
37 std::ranges::advance(it, sent);
38 assert(base(base(it)) == expected);
39 assert(it.stride_count() == 0); // because we got here by assigning from last, not by incrementing
40 }
41 }
42
43 template <bool Count, class It>
check_sized_sentinel(int * first,int * last,int * expected)44 constexpr void check_sized_sentinel(int* first, int* last, int* expected) {
45 auto size = (last - first);
46
47 {
48 It it(first);
49 auto sent = distance_apriori_sentinel(size);
50 std::ranges::advance(it, sent);
51 ASSERT_SAME_TYPE(decltype(std::ranges::advance(it, sent)), void);
52 assert(base(it) == expected);
53 }
54
55 // Count operations
56 if constexpr (Count) {
57 auto it = stride_counting_iterator(It(first));
58 auto sent = distance_apriori_sentinel(size);
59 std::ranges::advance(it, sent);
60 if constexpr (std::random_access_iterator<It>) {
61 assert(it.stride_count() == 1);
62 } else {
63 assert(it.stride_count() == size);
64 }
65 }
66 }
67
68 template <bool Count, class It>
check_sentinel(int * first,int * last,int * expected)69 constexpr void check_sentinel(int* first, int* last, int* expected) {
70 auto size = (last - first);
71
72 {
73 It it(first);
74 auto sent = sentinel_wrapper(It(last));
75 std::ranges::advance(it, sent);
76 ASSERT_SAME_TYPE(decltype(std::ranges::advance(it, sent)), void);
77 assert(base(it) == expected);
78 }
79
80 // Count operations
81 if constexpr (Count) {
82 auto it = stride_counting_iterator(It(first));
83 auto sent = sentinel_wrapper(stride_counting_iterator(It(last)));
84 std::ranges::advance(it, sent);
85 assert(it.stride_count() == size);
86 }
87 }
88
test()89 constexpr bool test() {
90 int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
91
92 for (int n = 0; n != 10; ++n) {
93 check_assignable<false, cpp17_input_iterator<int*>>( range, range+n, range+n);
94 check_assignable<false, cpp20_input_iterator<int*>>( range, range+n, range+n);
95 check_assignable<true, forward_iterator<int*>>( range, range+n, range+n);
96 check_assignable<true, bidirectional_iterator<int*>>(range, range+n, range+n);
97 check_assignable<true, random_access_iterator<int*>>(range, range+n, range+n);
98 check_assignable<true, contiguous_iterator<int*>>( range, range+n, range+n);
99 check_assignable<true, int*>( range, range+n, range+n);
100
101 check_sized_sentinel<false, cpp17_input_iterator<int*>>( range, range+n, range+n);
102 check_sized_sentinel<false, cpp20_input_iterator<int*>>( range, range+n, range+n);
103 check_sized_sentinel<true, forward_iterator<int*>>( range, range+n, range+n);
104 check_sized_sentinel<true, bidirectional_iterator<int*>>(range, range+n, range+n);
105 check_sized_sentinel<true, random_access_iterator<int*>>(range, range+n, range+n);
106 check_sized_sentinel<true, contiguous_iterator<int*>>( range, range+n, range+n);
107 check_sized_sentinel<true, int*>( range, range+n, range+n);
108
109 check_sentinel<false, cpp17_input_iterator<int*>>( range, range+n, range+n);
110 check_sentinel<false, cpp20_input_iterator<int*>>( range, range+n, range+n);
111 check_sentinel<true, forward_iterator<int*>>( range, range+n, range+n);
112 check_sentinel<true, bidirectional_iterator<int*>>(range, range+n, range+n);
113 check_sentinel<true, random_access_iterator<int*>>(range, range+n, range+n);
114 check_sentinel<true, contiguous_iterator<int*>>( range, range+n, range+n);
115 check_sentinel<true, int*>( range, range+n, range+n);
116 }
117
118 return true;
119 }
120
main(int,char **)121 int main(int, char**) {
122 assert(test());
123 static_assert(test());
124 return 0;
125 }
126