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 template<typename T> 26 concept has_data 27 = requires (T&& t) { std::ranges::data(std::forward<T>(t)); }; 28 29 void test01()30test01() 31 { 32 struct R 33 { 34 int i = 0; 35 int j = 0; 36 int* data() { return &j; } 37 const R* data() const noexcept { return nullptr; } 38 }; 39 static_assert( has_data<R&> ); 40 static_assert( has_data<const R&> ); 41 R r; 42 const R& c = r; 43 VERIFY( std::ranges::data(r) == &r.j ); 44 static_assert( !noexcept(std::ranges::data(r)) ); 45 VERIFY( std::ranges::data(c) == (R*)nullptr ); 46 static_assert( noexcept(std::ranges::data(c)) ); 47 48 // not lvalues and not borrowed ranges 49 static_assert( !has_data<R> ); 50 static_assert( !has_data<const R> ); 51 } 52 53 54 void test02()55test02() 56 { 57 int a[] = { 0, 1 }; 58 VERIFY( std::ranges::data(a) == a + 0 ); 59 60 __gnu_test::test_range<int, __gnu_test::contiguous_iterator_wrapper> r(a); 61 VERIFY( std::ranges::data(r) == std::to_address(std::ranges::begin(r)) ); 62 63 static_assert( has_data<int(&)[2]> ); 64 static_assert( has_data<decltype(r)&> ); 65 static_assert( !has_data<int(&&)[2]> ); 66 static_assert( !has_data<decltype(r)&&> ); 67 } 68 69 struct R3 70 { 71 static inline int i; 72 static inline long l; 73 dataR374 int* data() & { return &i; } begin(const R3 & r)75 friend long* begin(const R3& r) { return &l; } 76 friend const short* begin(const R3&&); // not defined 77 }; 78 79 template<> constexpr bool std::ranges::enable_borrowed_range<R3> = true; 80 81 void test03()82test03() 83 { 84 static_assert( has_data<R3&> ); 85 static_assert( has_data<R3> ); // borrowed range 86 static_assert( has_data<const R3&> ); 87 static_assert( has_data<const R3> ); // borrowed range 88 89 R3 r; 90 const R3& c = r; 91 // PR libstdc++/100824 92 // ranges::data should treat the subexpression as an lvalue 93 VERIFY( std::ranges::data(std::move(r)) == &R3::i ); 94 VERIFY( std::ranges::data(std::move(c)) == &R3::l ); 95 96 // PR libstdc++/100824 comment 3 97 // Check for member data() should use decay-copy 98 struct A { int*&& data(); }; 99 static_assert( has_data<A&> ); 100 } 101 102 int main()103main() 104 { 105 test01(); 106 test02(); 107 test03(); 108 } 109