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
11// template<class I, sentinel_for<I> S>
12// requires (!sized_sentinel_for<S, I>)
13// constexpr iter_difference_t<I> ranges::distance(I first, S last);
14//
15// template<class I, sized_sentinel_for<decay_t<I>> S>
16// constexpr iter_difference_t<I> ranges::distance(I&& first, S last); // TODO: update when LWG3664 is resolved
17
18#include <iterator>
19#include <cassert>
20
21#include "test_iterators.h"
22#include "test_macros.h"
23
24template<class It, class Sent>
25constexpr void test_unsized() {
26 static_assert(std::sentinel_for<Sent, It> && !std::sized_sentinel_for<Sent, It>);
27 int a[3] = {1,2,3};
28 {
29 It first = It(a);
30 auto last = Sent(It(a));
31 assert(std::ranges::distance(first, last) == 0);
32 assert(std::ranges::distance(It(a), last) == 0);
33 assert(std::ranges::distance(first, Sent(It(a))) == 0);
34 assert(std::ranges::distance(It(a), Sent(It(a))) == 0);
35 ASSERT_SAME_TYPE(decltype(std::ranges::distance(It(a), Sent(It(a)))), std::iter_difference_t<It>);
36 }
37 {
38 auto check = [&a]<class ItQual, class SentQual> {
39 It first = It(a);
40 Sent last = Sent(It(a + 3));
41 assert(std::ranges::distance(static_cast<ItQual>(first), static_cast<SentQual>(last)) == 3);
42 };
43
44 // Test all const/ref-qualifications of both operands.
45 check.template operator()<It&, Sent&>();
46 check.template operator()<It&, Sent&&>();
47 check.template operator()<It&, const Sent&>();
48 check.template operator()<It&, const Sent&&>();
49 check.template operator()<It&&, Sent&>();
50 check.template operator()<It&&, Sent&&>();
51 check.template operator()<It&&, const Sent&>();
52 check.template operator()<It&&, const Sent&&>();
53 check.template operator()<const It&, Sent&>();
54 check.template operator()<const It&, Sent&&>();
55 check.template operator()<const It&, const Sent&>();
56 check.template operator()<const It&, const Sent&&>();
57 check.template operator()<const It&&, Sent&>();
58 check.template operator()<const It&&, Sent&&>();
59 check.template operator()<const It&&, const Sent&>();
60 check.template operator()<const It&&, const Sent&&>();
61 }
62}
63
64template<class It, class Sent>
65constexpr void test_sized() {
66 static_assert(std::sized_sentinel_for<Sent, It>);
67 int a[] = {1,2,3};
68 {
69 auto check = [&a]<class ItQual, class SentQual> {
70 It first = It(a + 3);
71 Sent last = Sent(It(a));
72 assert(std::ranges::distance(static_cast<ItQual>(first), static_cast<SentQual>(last)) == -3);
73 };
74
75 // Test all const/ref-qualifications of both operands.
76 check.template operator()<It&, Sent&>();
77 check.template operator()<It&, Sent&&>();
78 check.template operator()<It&, const Sent&>();
79 check.template operator()<It&, const Sent&&>();
80 check.template operator()<It&&, Sent&>();
81 check.template operator()<It&&, Sent&&>();
82 check.template operator()<It&&, const Sent&>();
83 check.template operator()<It&&, const Sent&&>();
84 check.template operator()<const It&, Sent&>();
85 check.template operator()<const It&, Sent&&>();
86 check.template operator()<const It&, const Sent&>();
87 check.template operator()<const It&, const Sent&&>();
88 check.template operator()<const It&&, Sent&>();
89 check.template operator()<const It&&, Sent&&>();
90 check.template operator()<const It&&, const Sent&>();
91 check.template operator()<const It&&, const Sent&&>();
92 }
93 {
94 It first = It(a);
95 auto last = Sent(It(a));
96 assert(std::ranges::distance(first, last) == 0);
97 assert(std::ranges::distance(It(a), last) == 0);
98 assert(std::ranges::distance(first, Sent(It(a))) == 0);
99 assert(std::ranges::distance(It(a), Sent(It(a))) == 0);
100 ASSERT_SAME_TYPE(decltype(std::ranges::distance(It(a), Sent(It(a)))), std::iter_difference_t<It>);
101 }
102 {
103 It first = It(a);
104 auto last = Sent(It(a + 3));
105 assert(std::ranges::distance(first, last) == 3);
106 assert(std::ranges::distance(It(a), last) == 3);
107 assert(std::ranges::distance(first, Sent(It(a + 3))) == 3);
108 assert(std::ranges::distance(It(a), Sent(It(a + 3))) == 3);
109 }
110}
111
112struct StrideCounter {
113 int *it_;
114 int *inc_;
115 using value_type = int;
116 using difference_type = int;
117 explicit StrideCounter();
118 constexpr explicit StrideCounter(int *it, int *inc) : it_(it), inc_(inc) {}
119 constexpr auto& operator++() { ++it_; *inc_ += 1; return *this; }
120 StrideCounter operator++(int);
121 int& operator*() const;
122 bool operator==(StrideCounter) const;
123};
124static_assert(std::forward_iterator<StrideCounter>);
125static_assert(!std::sized_sentinel_for<StrideCounter, StrideCounter>);
126
127struct SizedStrideCounter {
128 int *it_;
129 int *minus_;
130 using value_type = int;
131 explicit SizedStrideCounter();
132 constexpr explicit SizedStrideCounter(int *it, int *minus) : it_(it), minus_(minus) {}
133 SizedStrideCounter& operator++();
134 SizedStrideCounter operator++(int);
135 int& operator*() const;
136 bool operator==(SizedStrideCounter) const;
137 constexpr int operator-(SizedStrideCounter rhs) const {
138 *minus_ += 1;
139 return static_cast<int>(it_ - rhs.it_);
140 }
141};
142static_assert(std::forward_iterator<SizedStrideCounter>);
143static_assert(std::sized_sentinel_for<SizedStrideCounter, SizedStrideCounter>);
144
145constexpr void test_stride_counting() {
146 {
147 int a[] = {1, 2, 3};
148 int inc = 0;
149 StrideCounter first(a, &inc);
150 StrideCounter last(a+3, nullptr);
151 std::same_as<int> auto result = std::ranges::distance(first, last);
152 assert(result == 3);
153 assert(inc == 3);
154 }
155 {
156 int a[] = {1, 2, 3};
157 int minus = 0;
158 SizedStrideCounter first(a, &minus);
159 SizedStrideCounter last(a+3, nullptr);
160 std::same_as<int> auto result = std::ranges::distance(first, last);
161 assert(result == 3);
162 assert(minus == 1);
163 }
164}
165
166constexpr bool test() {
167 {
168 int a[] = {1, 2, 3};
169 assert(std::ranges::distance(a, a + 3) == 3);
170 assert(std::ranges::distance(a, a) == 0);
171 assert(std::ranges::distance(a + 3, a) == -3);
172 }
173
174 test_unsized<cpp17_input_iterator<int*>, sentinel_wrapper<cpp17_input_iterator<int*>>>();
175 test_unsized<cpp17_output_iterator<int*>, sentinel_wrapper<cpp17_output_iterator<int*>>>();
176 test_unsized<forward_iterator<int*>, sentinel_wrapper<forward_iterator<int*>>>();
177 test_unsized<bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>();
178 test_unsized<random_access_iterator<int*>, sentinel_wrapper<random_access_iterator<int*>>>();
179 test_unsized<contiguous_iterator<int*>, sentinel_wrapper<contiguous_iterator<int*>>>();
180 test_unsized<int*, sentinel_wrapper<int*>>();
181 test_unsized<const int*, sentinel_wrapper<const int*>>();
182 test_unsized<forward_iterator<int*>, forward_iterator<int*>>();
183 test_unsized<bidirectional_iterator<int*>, bidirectional_iterator<int*>>();
184
185 test_sized<cpp17_input_iterator<int*>, sized_sentinel<cpp17_input_iterator<int*>>>();
186 test_sized<cpp20_input_iterator<int*>, sized_sentinel<cpp20_input_iterator<int*>>>();
187 test_sized<cpp17_output_iterator<int*>, sized_sentinel<cpp17_output_iterator<int*>>>();
188 test_sized<forward_iterator<int*>, sized_sentinel<forward_iterator<int*>>>();
189 test_sized<bidirectional_iterator<int*>, sized_sentinel<bidirectional_iterator<int*>>>();
190 test_sized<random_access_iterator<int*>, sized_sentinel<random_access_iterator<int*>>>();
191 test_sized<contiguous_iterator<int*>, sized_sentinel<contiguous_iterator<int*>>>();
192 test_sized<int*, sized_sentinel<int*>>();
193 test_sized<const int*, sized_sentinel<const int*>>();
194 test_sized<int*, int*>();
195 test_sized<int*, const int*>();
196 test_sized<random_access_iterator<int*>, random_access_iterator<int*>>();
197 test_sized<contiguous_iterator<int*>, contiguous_iterator<int*>>();
198
199 {
200 using It = cpp20_input_iterator<int*>; // non-copyable, thus not a sentinel for itself
201 static_assert(!std::is_copy_constructible_v<It>);
202 static_assert(!std::sentinel_for<It, It>);
203 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, It&>);
204 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, It&&>);
205 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&&, It&>);
206 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&&, It&&>);
207 }
208 {
209 using It = cpp20_input_iterator<int*>; // non-copyable
210 using Sent = sentinel_wrapper<It>; // not a sized sentinel
211 static_assert(std::sentinel_for<Sent, It> && !std::sized_sentinel_for<Sent, It>);
212 int a[] = {1,2,3};
213 Sent last = Sent(It(a + 3));
214 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, Sent&>);
215 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, Sent&&>);
216 assert(std::ranges::distance(It(a), last) == 3);
217 assert(std::ranges::distance(It(a), Sent(It(a + 3))) == 3);
218 }
219 {
220 using It = cpp17_input_iterator<int*>; // not a sentinel for itself
221 static_assert(!std::sentinel_for<It, It>);
222 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, It&>);
223 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, It&&>);
224 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&&, It&>);
225 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&&, It&&>);
226 }
227
228 // Calling it on a non-iterator or non-sentinel isn't allowed.
229 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), int, int>);
230 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), int*, int>);
231 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), int, int*>);
232 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), int*, char*>);
233
234 return true;
235}
236
237int main(int, char**) {
238 test();
239 static_assert(test());
240
241 return 0;
242}
243

source code of libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp