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 constexpr const int* rbegin() const { return &i; } rendR131 constexpr const int* rend() const { return &i + 1; } rbegin(const R1 && r)32 friend constexpr const int* rbegin(const R1&& r) { return &r.j; } rend(const R1 && r)33 friend constexpr const int* rend(const R1&& r) { return &r.j + 1; } 34 }; 35 36 // N.B. this is a lie, rend on an R1 rvalue will return a dangling pointer. 37 template<> constexpr bool std::ranges::enable_borrowed_range<R1> = true; 38 39 void test01()40test01() 41 { 42 R1 r; 43 const R1& c = r; 44 VERIFY( std::ranges::crend(r) == std::ranges::rend(c) ); 45 VERIFY( std::ranges::crend(c) == std::ranges::rend(c) ); 46 VERIFY( std::ranges::crend(std::move(r)) == std::ranges::rend(c) ); 47 VERIFY( std::ranges::crend(std::move(c)) == std::ranges::rend(c) ); 48 } 49 50 struct R2 51 { 52 int a[2] = { }; 53 long l[2] = { }; 54 beginR255 const int* begin() const { return a; } endR256 const int* end() const { return a + 2; } 57 begin(const R2 && r)58 friend const long* begin(const R2&& r) { return r.l; } end(const R2 && r)59 friend const long* end(const R2&& r) { return r.l + 2; } 60 }; 61 62 // N.B. this is a lie, rend on an R2 rvalue will return a dangling pointer. 63 template<> constexpr bool std::ranges::enable_borrowed_range<R2> = true; 64 65 void test02()66test02() 67 { 68 R2 r; 69 const R2& c = r; 70 VERIFY( std::ranges::crend(r) == std::ranges::rend(c) ); 71 VERIFY( std::ranges::crend(c) == std::ranges::rend(c) ); 72 VERIFY( std::ranges::crend(std::move(r)) == std::ranges::rend(std::move(c)) ); 73 VERIFY( std::ranges::crend(std::move(c)) == std::ranges::rend(std::move(c)) ); 74 } 75 76 struct R3 77 { 78 int i = 0; 79 rbeginR380 const int* rbegin() const noexcept { return &i + 1; } rendR381 const long* rend() const noexcept { return nullptr; } // not a sentinel for rbegin() 82 rbegin(const R3 &)83 friend const long* rbegin(const R3&) noexcept { return nullptr; } rend(const R3 & r)84 friend const int* rend(const R3& r) { return &r.i; } 85 }; 86 87 // N.B. this is a lie, rend on an R3 rvalue will return a dangling pointer. 88 template<> constexpr bool std::ranges::enable_borrowed_range<R3> = true; 89 90 void test03()91test03() 92 { 93 R3 r; 94 const R3& c = r; 95 VERIFY( std::ranges::crend(r) == std::ranges::rend(c) ); 96 static_assert( !noexcept(std::ranges::crend(r)) ); 97 VERIFY( std::ranges::crend(c) == std::ranges::rend(c) ); 98 static_assert( !noexcept(std::ranges::crend(c)) ); 99 } 100 101 void test04()102test04() 103 { 104 int a[2] = { }; 105 const auto& c = a; 106 VERIFY( std::ranges::crend(a) == std::ranges::rend(c) ); 107 VERIFY( std::ranges::crend(c) == std::ranges::rend(c) ); 108 } 109 110 int main()111main() 112 { 113 test01(); 114 test02(); 115 test03(); 116 test04(); 117 } 118