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 struct R1
26 {
27   int i = 0;
28   int j = 0;
29 
rbeginR130   const int* rbegin() const { return &i; }
rbegin(const R1 && r)31   friend const int* rbegin(const R1&& r) { return &r.j; }
32 };
33 
34 struct R1V // view on an R1
35 {
36   R1& r;
37 
38   friend const long* rbegin(R1V&); // this is not defined
rbegin(const R1V & rv)39   friend const int* rbegin(const R1V& rv) noexcept { return rv.r.rbegin(); }
40 };
41 
42 // Allow ranges::end to work with R1V&&
43 template<> constexpr bool std::ranges::enable_borrowed_range<R1V> = true;
44 
45 void
test01()46 test01()
47 {
48   R1 r;
49   const R1& c = r;
50   VERIFY( std::ranges::crbegin(r) == std::ranges::rbegin(c) );
51   VERIFY( std::ranges::crbegin(c) == std::ranges::rbegin(c) );
52 
53   R1V v{r};
54   const R1V cv{r};
55   VERIFY( std::ranges::crbegin(std::move(v)) == std::ranges::rbegin(c) );
56   VERIFY( std::ranges::crbegin(std::move(cv)) == std::ranges::rbegin(c) );
57 }
58 
59 struct R2
60 {
61   int a[2] = { };
62   long l[2] = { };
63 
beginR264   const int* begin() const { return a; }
endR265   const int* end() const { return a + 2; }
66 
67   friend const long* begin(const R2&&); // not defined
68   friend const long* end(const R2&&); // not defined
69 };
70 
71 // N.B. this is a lie, rbegin on an R2 rvalue will return a dangling pointer.
72 template<> constexpr bool std::ranges::enable_borrowed_range<R2> = true;
73 
74 void
test02()75 test02()
76 {
77   R2 r;
78   const R2& c = r;
79   VERIFY( std::ranges::crbegin(r) == std::ranges::rbegin(c) );
80   VERIFY( std::ranges::crbegin(c) == std::ranges::rbegin(c) );
81 
82   VERIFY( std::ranges::crbegin(std::move(r)) == std::ranges::rbegin(c) );
83   VERIFY( std::ranges::crbegin(std::move(c)) == std::ranges::rbegin(c) );
84 }
85 
86 int
main()87 main()
88 {
89   test01();
90   test02();
91 }
92