]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/std/ranges/access/end.cc
libstdc++: Reduce header dependencies on <array> and <utility>
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / std / ranges / access / end.cc
1 // Copyright (C) 2019-2021 Free Software Foundation, Inc.
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
18 // { dg-options "-std=gnu++2a" }
19 // { dg-do run { target c++2a } }
20
21 #include <ranges>
22 #include <utility> // as_const
23 #include <testsuite_hooks.h>
24 #include <testsuite_iterators.h>
25
26 static_assert(__gnu_test::is_customization_point_object(std::ranges::end));
27
28 using std::same_as;
29
30 void
31 test01()
32 {
33 int a[2] = {};
34
35 // t + extent_v<T> if E is of array type T.
36
37 static_assert(same_as<decltype(std::ranges::end(a)), decltype(a + 2)>);
38 static_assert(noexcept(std::ranges::end(a)));
39 VERIFY( std::ranges::end(a) == (a + 2) );
40 }
41
42 void
43 test02()
44 {
45 using __gnu_test::test_range;
46 using __gnu_test::random_access_iterator_wrapper;
47 using __gnu_test::input_iterator_wrapper;
48 using __gnu_test::output_iterator_wrapper;
49
50 int a[] = { 0, 1 };
51
52 // Otherwise, decay-copy(t.end()) if it is a valid expression
53 // and its type S models sentinel_for<decltype(ranges::begin(E))>.
54
55 test_range<int, random_access_iterator_wrapper> r(a);
56 static_assert(same_as<decltype(std::ranges::end(r)), decltype(r.end())>);
57 VERIFY( std::ranges::end(r) == std::ranges::next(r.begin(), 2) );
58
59 test_range<int, input_iterator_wrapper> i(a);
60 static_assert(same_as<decltype(std::ranges::end(i)), decltype(i.end())>);
61 VERIFY( std::ranges::end(i) == std::ranges::next(i.begin(), 2) );
62
63 test_range<int, output_iterator_wrapper> o(a);
64 static_assert(same_as<decltype(std::ranges::end(o)), decltype(o.end())>);
65 VERIFY( std::ranges::end(o) == std::ranges::next(o.begin(), 2) );
66 }
67
68 struct R
69 {
70 int a[4] = { 0, 1, 2, 3 };
71
72 const int* begin() const;
73 friend int* begin(R&&) noexcept;
74 friend const int* begin(const R&&) noexcept;
75
76 // Should be ignored because it doesn't return a sentinel for int*
77 const long* end() const;
78
79 friend int* end(R& r) { return r.a + 0; }
80 friend int* end(R&& r) { return r.a + 1; }
81 friend const int* end(const R& r) noexcept { return r.a + 2; }
82 friend const int* end(const R&& r) noexcept { return r.a + 3; }
83 };
84
85 struct RV // view on an R
86 {
87 R& r;
88
89 const int* begin() const;
90
91 friend int* end(RV& v) noexcept { return end(v.r); }
92 friend const int* end(const RV& v) { return end(std::as_const(v.r)); }
93 };
94
95 // Allow ranges::begin to work with RV&&
96 template<> constexpr bool std::ranges::enable_borrowed_range<RV> = true;
97
98 void
99 test03()
100 {
101 R r;
102 const R& c = r;
103
104 // Otherwise, decay-copy(end(t)) if it is a valid expression
105 // and its type S models sentinel_for<decltype(ranges::begin(E))>.
106
107 static_assert(same_as<decltype(std::ranges::end(r)), decltype(end(r))>);
108 static_assert(!noexcept(std::ranges::end(r)));
109 VERIFY( std::ranges::end(r) == end(r) );
110
111 static_assert(same_as<decltype(std::ranges::end(c)), decltype(end(c))>);
112 static_assert(noexcept(std::ranges::end(c)));
113 VERIFY( std::ranges::end(c) == end(c) );
114
115 RV v{r};
116 static_assert(same_as<decltype(std::ranges::end(std::move(v))),
117 decltype(end(r))>);
118 static_assert(noexcept(std::ranges::end(std::move(v))));
119 VERIFY( std::ranges::end(std::move(v)) == end(r) );
120
121 const RV cv{r};
122 static_assert(same_as<decltype(std::ranges::end(std::move(cv))),
123 decltype(end(c))>);
124 static_assert(!noexcept(std::ranges::end(std::move(cv))));
125 VERIFY( std::ranges::end(std::move(cv)) == end(c) );
126 }
127
128 struct RR
129 {
130 short s = 0;
131 long l = 0;
132 int a[4] = { 0, 1, 2, 3 };
133
134 const void* begin() const; // return type not an iterator
135
136 friend const short* begin(RR&) noexcept;
137 short* end() noexcept { return &s; }
138
139 friend const long* begin(const RR&) noexcept;
140 const long* end() const { return &l; }
141
142 friend const int* begin(RR&&) noexcept;
143 friend int* end(RR&) { throw 1; } // not valid for rvalues
144 friend int* end(RR&& r) { return r.a + 1; }
145
146 friend const int* begin(const RR&&) noexcept;
147 friend const int* end(const RR&) { throw 1; } // not valid for rvalues
148 friend const int* end(const RR&& r) noexcept { return r.a + 3; }
149 };
150
151 // N.B. this is a lie, end on an RR rvalue will return a dangling pointer.
152 template<> constexpr bool std::ranges::enable_borrowed_range<RR> = true;
153
154 void
155 test04()
156 {
157 RR r;
158 const RR& c = r;
159 VERIFY( std::ranges::end(r) == &r.s );
160 static_assert(noexcept(std::ranges::end(r)));
161
162 VERIFY( std::ranges::end(std::move(r)) == &r.s );
163 static_assert(noexcept(std::ranges::end(std::move(r))));
164
165 VERIFY( std::ranges::end(c) == &r.l );
166 static_assert(!noexcept(std::ranges::end(c)));
167
168 VERIFY( std::ranges::end(std::move(c)) == &r.l );
169 static_assert(!noexcept(std::ranges::end(std::move(c))));
170 }
171
172 int
173 main()
174 {
175 test01();
176 test02();
177 test03();
178 test04();
179 }