1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: libcpp-no-concepts 11 // UNSUPPORTED: libcpp-has-no-incomplete-ranges 12 13 // std::ranges::data 14 15 #include <ranges> 16 17 #include <cassert> 18 #include "test_macros.h" 19 #include "test_iterators.h" 20 21 using RangeDataT = decltype(std::ranges::data); 22 23 static int globalBuff[2]; 24 25 struct Incomplete; 26 27 static_assert(!std::is_invocable_v<RangeDataT, Incomplete[]>); 28 static_assert(!std::is_invocable_v<RangeDataT, Incomplete[2]>); 29 static_assert(!std::is_invocable_v<RangeDataT, Incomplete[2][2]>); 30 static_assert(!std::is_invocable_v<RangeDataT, int [1]>); 31 static_assert(!std::is_invocable_v<RangeDataT, int (&&)[1]>); 32 static_assert( std::is_invocable_v<RangeDataT, int (&)[1]>); 33 34 struct DataMember { 35 int x; 36 constexpr const int *data() const { return &x; } 37 }; 38 39 static_assert( std::is_invocable_v<RangeDataT, DataMember &>); 40 static_assert(!std::is_invocable_v<RangeDataT, DataMember &&>); 41 42 struct VoidDataMember { 43 void *data() const; 44 }; 45 static_assert(!std::is_invocable_v<RangeDataT, VoidDataMember const&>); 46 47 struct Empty { }; 48 struct EmptyDataMember { 49 Empty data() const; 50 }; 51 52 static_assert(!std::is_invocable_v<RangeDataT, EmptyDataMember const&>); 53 54 struct EmptyPtrDataMember { 55 Empty x; 56 constexpr const Empty *data() const { return &x; } 57 }; 58 59 struct PtrConvertible { 60 operator int*() const; 61 }; 62 struct PtrConvertibleDataMember { 63 PtrConvertible data() const; 64 }; 65 66 static_assert(!std::is_invocable_v<RangeDataT, PtrConvertibleDataMember const&>); 67 68 struct NonConstDataMember { 69 int x; 70 constexpr int *data() { return &x; } 71 }; 72 73 struct EnabledBorrowingDataMember { 74 constexpr int *data() { return &globalBuff[0]; } 75 }; 76 77 template<> 78 inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingDataMember> = true; 79 80 struct DataMemberAndBegin { 81 int x; 82 constexpr const int *data() const { return &x; } 83 constexpr const int *begin() const { return &x; } 84 }; 85 86 constexpr bool testDataMember() { 87 DataMember a; 88 assert(std::ranges::data(a) == &a.x); 89 90 NonConstDataMember b; 91 assert(std::ranges::data(b) == &b.x); 92 93 EnabledBorrowingDataMember c; 94 assert(std::ranges::data(std::move(c)) == &globalBuff[0]); 95 96 DataMemberAndBegin d; 97 assert(std::ranges::data(d) == &d.x); 98 99 return true; 100 } 101 102 using ContiguousIter = contiguous_iterator<const int*>; 103 104 struct BeginMemberContiguousIterator { 105 int buff[8]; 106 107 constexpr ContiguousIter begin() const { return ContiguousIter(buff); } 108 }; 109 static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &>); 110 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &&>); 111 static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&>); 112 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&&>); 113 114 struct BeginMemberRandomAccess { 115 int buff[8]; 116 117 random_access_iterator<const int*> begin() const; 118 }; 119 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRandomAccess>); 120 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRandomAccess const>); 121 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRandomAccess const&>); 122 123 struct BeginFriendContiguousIterator { 124 int buff[8]; 125 126 friend constexpr ContiguousIter begin(const BeginFriendContiguousIterator &iter) { 127 return ContiguousIter(iter.buff); 128 } 129 }; 130 static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &>); 131 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &&>); 132 static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&>); 133 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&&>); 134 135 struct BeginFriendRandomAccess { 136 friend random_access_iterator<const int*> begin(const BeginFriendRandomAccess iter); 137 }; 138 static_assert(!std::is_invocable_v<RangeDataT, BeginFriendRandomAccess>); 139 static_assert(!std::is_invocable_v<RangeDataT, BeginFriendRandomAccess const>); 140 static_assert(!std::is_invocable_v<RangeDataT, BeginFriendRandomAccess const&>); 141 142 struct BeginMemberRvalue { 143 int buff[8]; 144 145 ContiguousIter begin() &&; 146 }; 147 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&&>); 148 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&>); 149 150 struct BeginMemberBorrowingEnabled { 151 constexpr contiguous_iterator<int*> begin() { return contiguous_iterator<int*>{&globalBuff[1]}; } 152 }; 153 template<> 154 inline constexpr bool std::ranges::enable_borrowed_range<BeginMemberBorrowingEnabled> = true; 155 static_assert( std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled &>); 156 static_assert( std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled &&>); 157 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled const&>); 158 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled const&&>); 159 160 constexpr bool testViaRangesBegin() { 161 int arr[2]; 162 assert(std::ranges::data(arr) == arr + 0); 163 164 BeginMemberContiguousIterator a; 165 assert(std::ranges::data(a) == a.buff); 166 167 const BeginFriendContiguousIterator b {}; 168 assert(std::ranges::data(b) == b.buff); 169 170 BeginMemberBorrowingEnabled c; 171 assert(std::ranges::data(std::move(c)) == &globalBuff[1]); 172 173 return true; 174 } 175 176 int main(int, char**) { 177 testDataMember(); 178 static_assert(testDataMember()); 179 180 testViaRangesBegin(); 181 static_assert(testViaRangesBegin()); 182 183 return 0; 184 } 185