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 | // friend constexpr iterator operator-(iterator i, difference_type n) |
12 | // requires advanceable<W>; |
13 | // friend constexpr difference_type operator-(const iterator& x, const iterator& y) |
14 | // requires advanceable<W>; |
15 | |
16 | #include <cassert> |
17 | #include <cstdint> |
18 | #include <ranges> |
19 | #include <type_traits> |
20 | |
21 | #include "test_macros.h" |
22 | #include "../types.h" |
23 | |
24 | // If we're compiling for 32 bit or windows, int and long are the same size, so long long is the correct difference type. |
25 | #if INTPTR_MAX == INT32_MAX || defined(_WIN32) |
26 | using IntDiffT = long long; |
27 | #else |
28 | using IntDiffT = long; |
29 | #endif |
30 | |
31 | constexpr bool test() { |
32 | // <iterator> - difference_type |
33 | { |
34 | // When "_Start" is signed integer like. |
35 | { |
36 | std::ranges::iota_view<int> io(0); |
37 | auto iter1 = std::next(io.begin(), 10); |
38 | auto iter2 = std::next(io.begin(), 10); |
39 | assert(iter1 == iter2); |
40 | assert(iter1 - 5 != iter2); |
41 | assert(iter1 - 5 == std::ranges::prev(iter2, 5)); |
42 | |
43 | static_assert(!std::is_reference_v<decltype(iter2 - 5)>); |
44 | } |
45 | |
46 | // When "_Start" is not integer like. |
47 | { |
48 | std::ranges::iota_view io(SomeInt(0)); |
49 | auto iter1 = std::next(io.begin(), 10); |
50 | auto iter2 = std::next(io.begin(), 10); |
51 | assert(iter1 == iter2); |
52 | assert(iter1 - 5 != iter2); |
53 | assert(iter1 - 5 == std::ranges::prev(iter2, 5)); |
54 | |
55 | static_assert(!std::is_reference_v<decltype(iter2 - 5)>); |
56 | } |
57 | |
58 | // When "_Start" is unsigned integer like and n is greater than or equal to zero. |
59 | { |
60 | std::ranges::iota_view<unsigned> io(0); |
61 | auto iter1 = std::next(io.begin(), 10); |
62 | auto iter2 = std::next(io.begin(), 10); |
63 | assert(iter1 == iter2); |
64 | assert(iter1 - 5 != iter2); |
65 | assert(iter1 - 5 == std::ranges::prev(iter2, 5)); |
66 | |
67 | static_assert(!std::is_reference_v<decltype(iter2 - 5)>); |
68 | } |
69 | { |
70 | std::ranges::iota_view<unsigned> io(0); |
71 | auto iter1 = std::next(io.begin(), 10); |
72 | auto iter2 = std::next(io.begin(), 10); |
73 | assert(iter1 - 0 == iter2); |
74 | } |
75 | |
76 | // When "_Start" is unsigned integer like and n is less than zero. |
77 | { |
78 | std::ranges::iota_view<unsigned> io(0); |
79 | auto iter1 = std::next(io.begin(), 10); |
80 | auto iter2 = std::next(io.begin(), 10); |
81 | assert(iter1 - 5 != iter2); |
82 | assert(iter1 - 5 == std::ranges::prev(iter2, 5)); |
83 | |
84 | static_assert(!std::is_reference_v<decltype(iter2 - 5)>); |
85 | } |
86 | } |
87 | |
88 | // <iterator> - <iterator> |
89 | { |
90 | // When "_Start" is signed integer like. |
91 | { |
92 | std::ranges::iota_view<int> io(0); |
93 | auto iter1 = std::next(io.begin(), 10); |
94 | auto iter2 = std::next(io.begin(), 5); |
95 | assert(iter1 - iter2 == 5); |
96 | |
97 | LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>); |
98 | } |
99 | { |
100 | std::ranges::iota_view<int> io(0); |
101 | auto iter1 = std::next(io.begin(), 10); |
102 | auto iter2 = std::next(io.begin(), 10); |
103 | assert(iter1 - iter2 == 0); |
104 | |
105 | LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>); |
106 | } |
107 | { |
108 | std::ranges::iota_view<int> io(0); |
109 | auto iter1 = std::next(io.begin(), 5); |
110 | auto iter2 = std::next(io.begin(), 10); |
111 | assert(iter1 - iter2 == -5); |
112 | |
113 | LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>); |
114 | } |
115 | |
116 | // When "_Start" is unsigned integer like and y > x. |
117 | { |
118 | std::ranges::iota_view<unsigned> io(0); |
119 | auto iter1 = std::next(io.begin(), 5); |
120 | auto iter2 = std::next(io.begin(), 10); |
121 | assert(iter1 - iter2 == -5); |
122 | |
123 | LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>); |
124 | } |
125 | |
126 | // When "_Start" is unsigned integer like and x >= y. |
127 | { |
128 | std::ranges::iota_view<unsigned> io(0); |
129 | auto iter1 = std::next(io.begin(), 10); |
130 | auto iter2 = std::next(io.begin(), 5); |
131 | assert(iter1 - iter2 == 5); |
132 | |
133 | LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>); |
134 | } |
135 | { |
136 | std::ranges::iota_view<unsigned> io(0); |
137 | auto iter1 = std::next(io.begin(), 10); |
138 | auto iter2 = std::next(io.begin(), 10); |
139 | assert(iter1 - iter2 == 0); |
140 | |
141 | LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>); |
142 | } |
143 | |
144 | // When "_Start" is not integer like. |
145 | { |
146 | std::ranges::iota_view io(SomeInt(0)); |
147 | auto iter1 = std::next(io.begin(), 10); |
148 | auto iter2 = std::next(io.begin(), 5); |
149 | assert(iter1 - iter2 == 5); |
150 | |
151 | static_assert(std::same_as<decltype(iter1 - iter2), int>); |
152 | } |
153 | { |
154 | std::ranges::iota_view io(SomeInt(0)); |
155 | auto iter1 = std::next(io.begin(), 10); |
156 | auto iter2 = std::next(io.begin(), 10); |
157 | assert(iter1 - iter2 == 0); |
158 | |
159 | static_assert(std::same_as<decltype(iter1 - iter2), int>); |
160 | } |
161 | { |
162 | std::ranges::iota_view io(SomeInt(0)); |
163 | auto iter1 = std::next(io.begin(), 5); |
164 | auto iter2 = std::next(io.begin(), 10); |
165 | assert(iter1 - iter2 == -5); |
166 | |
167 | static_assert(std::same_as<decltype(iter1 - iter2), int>); |
168 | } |
169 | } |
170 | |
171 | return true; |
172 | } |
173 | |
174 | int main(int, char**) { |
175 | test(); |
176 | static_assert(test()); |
177 | |
178 | return 0; |
179 | } |
180 | |