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()46test01() 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()75test02() 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()87main() 88 { 89 test01(); 90 test02(); 91 } 92