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 <utility> // as_const
23 #include <testsuite_hooks.h>
24 #include <testsuite_iterators.h>
26 static_assert(__gnu_test::is_customization_point_object(std::ranges::end
));
35 // t + extent_v<T> if E is of array type T.
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) );
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
;
52 // Otherwise, decay-copy(t.end()) if it is a valid expression
53 // and its type S models sentinel_for<decltype(ranges::begin(E))>.
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) );
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) );
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) );
70 int a
[4] = { 0, 1, 2, 3 };
72 const int* begin() const;
73 friend int* begin(R
&&) noexcept
;
74 friend const int* begin(const R
&&) noexcept
;
76 // Should be ignored because it doesn't return a sentinel for int*
77 const long* end() const;
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; }
85 struct RV
// view on an R
89 const int* begin() const;
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
)); }
95 // Allow ranges::begin to work with RV&&
96 template<> constexpr bool std::ranges::enable_borrowed_range
<RV
> = true;
104 // Otherwise, decay-copy(end(t)) if it is a valid expression
105 // and its type S models sentinel_for<decltype(ranges::begin(E))>.
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
) );
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
) );
116 static_assert(same_as
<decltype(std::ranges::end(std::move(v
))),
118 static_assert(noexcept(std::ranges::end(std::move(v
))));
119 VERIFY( std::ranges::end(std::move(v
)) == end(r
) );
122 static_assert(same_as
<decltype(std::ranges::end(std::move(cv
))),
124 static_assert(!noexcept(std::ranges::end(std::move(cv
))));
125 VERIFY( std::ranges::end(std::move(cv
)) == end(c
) );
132 int a
[4] = { 0, 1, 2, 3 };
134 const void* begin() const; // return type not an iterator
136 friend const short* begin(RR
&) noexcept
;
137 short* end() noexcept
{ return &s
; }
139 friend const long* begin(const RR
&) noexcept
;
140 const long* end() const { return &l
; }
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; }
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; }
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;
159 VERIFY( std::ranges::end(r
) == &r
.s
);
160 static_assert(noexcept(std::ranges::end(r
)));
162 VERIFY( std::ranges::end(std::move(r
)) == &r
.s
);
163 static_assert(noexcept(std::ranges::end(std::move(r
))));
165 VERIFY( std::ranges::end(c
) == &r
.l
);
166 static_assert(!noexcept(std::ranges::end(c
)));
168 VERIFY( std::ranges::end(std::move(c
)) == &r
.l
);
169 static_assert(!noexcept(std::ranges::end(std::move(c
))));