]>
Commit | Line | Data |
---|---|---|
a945c346 | 1 | // Copyright (C) 2019-2024 Free Software Foundation, Inc. |
6d0dff49 JW |
2 | // |
3 | // This file is part of the GNU ISO C++ Library. This library is free | |
4 | // software; you can redistribute it and/or modify it under the | |
5 | // terms of the GNU General Public License as published by the | |
6 | // Free Software Foundation; either version 3, or (at your option) | |
7 | // any later version. | |
8 | ||
9 | // This library is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | ||
14 | // You should have received a copy of the GNU General Public License along | |
15 | // with this library; see the file COPYING3. If not see | |
16 | // <http://www.gnu.org/licenses/>. | |
17 | ||
d4ac20b0 | 18 | // { dg-do run { target c++20 } } |
6d0dff49 | 19 | |
328b52d6 | 20 | #include <ranges> |
261d5a4a | 21 | #include <utility> // as_const |
6d0dff49 JW |
22 | #include <testsuite_hooks.h> |
23 | #include <testsuite_iterators.h> | |
24 | ||
b9e35ee6 JW |
25 | static_assert(__gnu_test::is_customization_point_object(std::ranges::end)); |
26 | ||
6d0dff49 JW |
27 | using std::same_as; |
28 | ||
29 | void | |
30 | test01() | |
31 | { | |
32 | int a[2] = {}; | |
33 | ||
5cd2e126 JW |
34 | // t + extent_v<T> if E is of array type T. |
35 | ||
6d0dff49 JW |
36 | static_assert(same_as<decltype(std::ranges::end(a)), decltype(a + 2)>); |
37 | static_assert(noexcept(std::ranges::end(a))); | |
38 | VERIFY( std::ranges::end(a) == (a + 2) ); | |
39 | } | |
40 | ||
41 | void | |
42 | test02() | |
43 | { | |
44 | using __gnu_test::test_range; | |
45 | using __gnu_test::random_access_iterator_wrapper; | |
46 | using __gnu_test::input_iterator_wrapper; | |
47 | using __gnu_test::output_iterator_wrapper; | |
48 | ||
49 | int a[] = { 0, 1 }; | |
50 | ||
5cd2e126 JW |
51 | // Otherwise, decay-copy(t.end()) if it is a valid expression |
52 | // and its type S models sentinel_for<decltype(ranges::begin(E))>. | |
53 | ||
6d0dff49 JW |
54 | test_range<int, random_access_iterator_wrapper> r(a); |
55 | static_assert(same_as<decltype(std::ranges::end(r)), decltype(r.end())>); | |
5cd2e126 | 56 | VERIFY( std::ranges::end(r) == std::ranges::next(r.begin(), 2) ); |
6d0dff49 JW |
57 | |
58 | test_range<int, input_iterator_wrapper> i(a); | |
59 | static_assert(same_as<decltype(std::ranges::end(i)), decltype(i.end())>); | |
5cd2e126 | 60 | VERIFY( std::ranges::end(i) == std::ranges::next(i.begin(), 2) ); |
6d0dff49 JW |
61 | |
62 | test_range<int, output_iterator_wrapper> o(a); | |
63 | static_assert(same_as<decltype(std::ranges::end(o)), decltype(o.end())>); | |
64 | VERIFY( std::ranges::end(o) == std::ranges::next(o.begin(), 2) ); | |
65 | } | |
66 | ||
67 | struct R | |
68 | { | |
69 | int a[4] = { 0, 1, 2, 3 }; | |
70 | ||
b3ffa117 JW |
71 | const int* begin() const; |
72 | friend int* begin(R&&) noexcept; | |
73 | friend const int* begin(const R&&) noexcept; | |
6d0dff49 JW |
74 | |
75 | // Should be ignored because it doesn't return a sentinel for int* | |
b3ffa117 | 76 | const long* end() const; |
6d0dff49 JW |
77 | |
78 | friend int* end(R& r) { return r.a + 0; } | |
79 | friend int* end(R&& r) { return r.a + 1; } | |
80 | friend const int* end(const R& r) noexcept { return r.a + 2; } | |
81 | friend const int* end(const R&& r) noexcept { return r.a + 3; } | |
82 | }; | |
83 | ||
b5b2e387 JW |
84 | struct RV // view on an R |
85 | { | |
86 | R& r; | |
87 | ||
88 | const int* begin() const; | |
89 | ||
90 | friend int* end(RV& v) noexcept { return end(v.r); } | |
91 | friend const int* end(const RV& v) { return end(std::as_const(v.r)); } | |
92 | }; | |
93 | ||
94 | // Allow ranges::begin to work with RV&& | |
15411a64 | 95 | template<> constexpr bool std::ranges::enable_borrowed_range<RV> = true; |
b5b2e387 | 96 | |
6d0dff49 JW |
97 | void |
98 | test03() | |
99 | { | |
100 | R r; | |
101 | const R& c = r; | |
102 | ||
5cd2e126 JW |
103 | // Otherwise, decay-copy(end(t)) if it is a valid expression |
104 | // and its type S models sentinel_for<decltype(ranges::begin(E))>. | |
105 | ||
6d0dff49 JW |
106 | static_assert(same_as<decltype(std::ranges::end(r)), decltype(end(r))>); |
107 | static_assert(!noexcept(std::ranges::end(r))); | |
108 | VERIFY( std::ranges::end(r) == end(r) ); | |
109 | ||
6d0dff49 JW |
110 | static_assert(same_as<decltype(std::ranges::end(c)), decltype(end(c))>); |
111 | static_assert(noexcept(std::ranges::end(c))); | |
112 | VERIFY( std::ranges::end(c) == end(c) ); | |
113 | ||
b5b2e387 JW |
114 | RV v{r}; |
115 | static_assert(same_as<decltype(std::ranges::end(std::move(v))), | |
116 | decltype(end(r))>); | |
117 | static_assert(noexcept(std::ranges::end(std::move(v)))); | |
118 | VERIFY( std::ranges::end(std::move(v)) == end(r) ); | |
119 | ||
120 | const RV cv{r}; | |
121 | static_assert(same_as<decltype(std::ranges::end(std::move(cv))), | |
122 | decltype(end(c))>); | |
123 | static_assert(!noexcept(std::ranges::end(std::move(cv)))); | |
124 | VERIFY( std::ranges::end(std::move(cv)) == end(c) ); | |
6d0dff49 JW |
125 | } |
126 | ||
127 | struct RR | |
128 | { | |
129 | short s = 0; | |
130 | long l = 0; | |
131 | int a[4] = { 0, 1, 2, 3 }; | |
132 | ||
b3ffa117 | 133 | const void* begin() const; // return type not an iterator |
6d0dff49 | 134 | |
b3ffa117 | 135 | friend const short* begin(RR&) noexcept; |
6d0dff49 | 136 | short* end() noexcept { return &s; } |
b3ffa117 JW |
137 | |
138 | friend const long* begin(const RR&) noexcept; | |
6d0dff49 JW |
139 | const long* end() const { return &l; } |
140 | ||
b3ffa117 JW |
141 | friend const int* begin(RR&&) noexcept; |
142 | friend int* end(RR&) { throw 1; } // not valid for rvalues | |
6d0dff49 | 143 | friend int* end(RR&& r) { return r.a + 1; } |
b3ffa117 JW |
144 | |
145 | friend const int* begin(const RR&&) noexcept; | |
146 | friend const int* end(const RR&) { throw 1; } // not valid for rvalues | |
6d0dff49 JW |
147 | friend const int* end(const RR&& r) noexcept { return r.a + 3; } |
148 | }; | |
149 | ||
b5b2e387 | 150 | // N.B. this is a lie, end on an RR rvalue will return a dangling pointer. |
15411a64 | 151 | template<> constexpr bool std::ranges::enable_borrowed_range<RR> = true; |
b5b2e387 | 152 | |
6d0dff49 JW |
153 | void |
154 | test04() | |
155 | { | |
156 | RR r; | |
157 | const RR& c = r; | |
158 | VERIFY( std::ranges::end(r) == &r.s ); | |
159 | static_assert(noexcept(std::ranges::end(r))); | |
160 | ||
b5b2e387 JW |
161 | VERIFY( std::ranges::end(std::move(r)) == &r.s ); |
162 | static_assert(noexcept(std::ranges::end(std::move(r)))); | |
6d0dff49 JW |
163 | |
164 | VERIFY( std::ranges::end(c) == &r.l ); | |
165 | static_assert(!noexcept(std::ranges::end(c))); | |
166 | ||
b5b2e387 JW |
167 | VERIFY( std::ranges::end(std::move(c)) == &r.l ); |
168 | static_assert(!noexcept(std::ranges::end(std::move(c)))); | |
6d0dff49 JW |
169 | } |
170 | ||
171 | int | |
172 | main() | |
173 | { | |
174 | test01(); | |
175 | test02(); | |
176 | test03(); | |
177 | test04(); | |
178 | } |