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