1 // Copyright (C) 2019-2021 Free Software Foundation, Inc.
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)
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.
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/>.
18 // { dg-options "-std=gnu++2a" }
19 // { dg-do run { target c++2a } }
22 #include <testsuite_hooks.h>
23 #include <testsuite_iterators.h>
32 // t + extent_v<T> if E is of array type T.
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) );
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
;
49 // Otherwise, decay-copy(t.end()) if it is a valid expression
50 // and its type S models sentinel_for<decltype(ranges::begin(E))>.
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) );
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) );
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) );
67 int a
[4] = { 0, 1, 2, 3 };
69 const int* begin() const;
70 friend int* begin(R
&&) noexcept
;
71 friend const int* begin(const R
&&) noexcept
;
73 // Should be ignored because it doesn't return a sentinel for int*
74 const long* end() const;
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; }
82 struct RV
// view on an R
86 const int* begin() const;
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
)); }
92 // Allow ranges::begin to work with RV&&
93 template<> constexpr bool std::ranges::enable_borrowed_range
<RV
> = true;
101 // Otherwise, decay-copy(end(t)) if it is a valid expression
102 // and its type S models sentinel_for<decltype(ranges::begin(E))>.
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
) );
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
) );
113 static_assert(same_as
<decltype(std::ranges::end(std::move(v
))),
115 static_assert(noexcept(std::ranges::end(std::move(v
))));
116 VERIFY( std::ranges::end(std::move(v
)) == end(r
) );
119 static_assert(same_as
<decltype(std::ranges::end(std::move(cv
))),
121 static_assert(!noexcept(std::ranges::end(std::move(cv
))));
122 VERIFY( std::ranges::end(std::move(cv
)) == end(c
) );
129 int a
[4] = { 0, 1, 2, 3 };
131 const void* begin() const; // return type not an iterator
133 friend const short* begin(RR
&) noexcept
;
134 short* end() noexcept
{ return &s
; }
136 friend const long* begin(const RR
&) noexcept
;
137 const long* end() const { return &l
; }
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; }
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; }
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;
156 VERIFY( std::ranges::end(r
) == &r
.s
);
157 static_assert(noexcept(std::ranges::end(r
)));
159 VERIFY( std::ranges::end(std::move(r
)) == &r
.s
);
160 static_assert(noexcept(std::ranges::end(std::move(r
))));
162 VERIFY( std::ranges::end(c
) == &r
.l
);
163 static_assert(!noexcept(std::ranges::end(c
)));
165 VERIFY( std::ranges::end(std::move(c
)) == &r
.l
);
166 static_assert(!noexcept(std::ranges::end(std::move(c
))));