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 11 // template<class D> 12 // requires is_class_v<D> && same_as<D, remove_cv_t<D>> 13 // class view_interface; 14 15 #include <ranges> 16 17 #include <cassert> 18 #include <utility> 19 #include "test_macros.h" 20 #include "test_iterators.h" 21 22 template<class T> 23 concept ValidViewInterfaceType = requires { typename std::ranges::view_interface<T>; }; 24 25 struct Empty { }; 26 27 static_assert(!ValidViewInterfaceType<void>); 28 static_assert(!ValidViewInterfaceType<void*>); 29 static_assert(!ValidViewInterfaceType<Empty*>); 30 static_assert(!ValidViewInterfaceType<Empty const>); 31 static_assert(!ValidViewInterfaceType<Empty &>); 32 static_assert( ValidViewInterfaceType<Empty>); 33 34 using InputIter = cpp20_input_iterator<const int*>; 35 36 struct InputRange : std::ranges::view_interface<InputRange> { 37 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 38 constexpr InputIter begin() const { return InputIter(buff); } 39 constexpr InputIter end() const { return InputIter(buff + 8); } 40 }; 41 42 struct NotSizedSentinel { 43 using value_type = int; 44 using difference_type = std::ptrdiff_t; 45 using iterator_concept = std::forward_iterator_tag; 46 47 explicit NotSizedSentinel() = default; 48 explicit NotSizedSentinel(int*); 49 int& operator*() const; 50 NotSizedSentinel& operator++(); 51 NotSizedSentinel operator++(int); 52 bool operator==(NotSizedSentinel const&) const; 53 }; 54 static_assert(std::forward_iterator<NotSizedSentinel>); 55 56 using ForwardIter = forward_iterator<int*>; 57 58 // So that we conform to sized_sentinel_for. 59 constexpr std::ptrdiff_t operator-(const ForwardIter& x, const ForwardIter& y) { 60 return base(x) - base(y); 61 } 62 63 struct ForwardRange : std::ranges::view_interface<ForwardRange> { 64 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 65 constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); } 66 constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); } 67 }; 68 static_assert(std::ranges::view<ForwardRange>); 69 70 struct MoveOnlyForwardRange : std::ranges::view_interface<MoveOnlyForwardRange> { 71 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 72 MoveOnlyForwardRange(MoveOnlyForwardRange const&) = delete; 73 MoveOnlyForwardRange(MoveOnlyForwardRange &&) = default; 74 MoveOnlyForwardRange& operator=(MoveOnlyForwardRange &&) = default; 75 MoveOnlyForwardRange() = default; 76 constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); } 77 constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); } 78 }; 79 static_assert(std::ranges::view<MoveOnlyForwardRange>); 80 81 struct MI : std::ranges::view_interface<InputRange>, 82 std::ranges::view_interface<MoveOnlyForwardRange> { 83 }; 84 static_assert(!std::ranges::view<MI>); 85 86 struct EmptyIsTrue : std::ranges::view_interface<EmptyIsTrue> { 87 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 88 constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); } 89 constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); } 90 constexpr bool empty() const { return true; } 91 }; 92 static_assert(std::ranges::view<EmptyIsTrue>); 93 94 struct SizeIsTen : std::ranges::view_interface<SizeIsTen> { 95 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 96 constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); } 97 constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); } 98 constexpr std::size_t size() const { return 10; } 99 }; 100 static_assert(std::ranges::view<SizeIsTen>); 101 102 using RAIter = random_access_iterator<int*>; 103 104 struct RARange : std::ranges::view_interface<RARange> { 105 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 106 constexpr RAIter begin() const { return RAIter(const_cast<int*>(buff)); } 107 constexpr RAIter end() const { return RAIter(const_cast<int*>(buff) + 8); } 108 }; 109 static_assert(std::ranges::view<RARange>); 110 111 using ContIter = contiguous_iterator<const int*>; 112 113 struct ContRange : std::ranges::view_interface<ContRange> { 114 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 115 constexpr ContIter begin() const { return ContIter(buff); } 116 constexpr ContIter end() const { return ContIter(buff + 8); } 117 }; 118 static_assert(std::ranges::view<ContRange>); 119 120 struct DataIsNull : std::ranges::view_interface<DataIsNull> { 121 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 122 constexpr ContIter begin() const { return ContIter(buff); } 123 constexpr ContIter end() const { return ContIter(buff + 8); } 124 constexpr const int *data() const { return nullptr; } 125 }; 126 static_assert(std::ranges::view<DataIsNull>); 127 128 struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleComparison> { 129 struct ResultType { 130 bool value; 131 constexpr operator bool() const { return value; } 132 }; 133 134 struct SentinelType { 135 int *base_; 136 explicit SentinelType() = default; 137 constexpr explicit SentinelType(int *base) : base_(base) {} 138 friend constexpr ResultType operator==(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) == sent.base_}; } 139 friend constexpr ResultType operator==(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) == sent.base_}; } 140 friend constexpr ResultType operator!=(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) != sent.base_}; } 141 friend constexpr ResultType operator!=(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) != sent.base_}; } 142 }; 143 144 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 145 constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); } 146 constexpr SentinelType end() const { return SentinelType(const_cast<int*>(buff) + 8); } 147 }; 148 static_assert(std::ranges::view<BoolConvertibleComparison>); 149 150 template<class T> 151 concept EmptyInvocable = requires (T const& obj) { obj.empty(); }; 152 153 template<class T> 154 concept BoolOpInvocable = requires (T const& obj) { bool(obj); }; 155 156 constexpr bool testEmpty() { 157 static_assert(!EmptyInvocable<InputRange>); 158 static_assert( EmptyInvocable<ForwardRange>); 159 160 static_assert(!BoolOpInvocable<InputRange>); 161 static_assert( BoolOpInvocable<ForwardRange>); 162 163 ForwardRange forwardRange; 164 assert(!forwardRange.empty()); 165 assert(!static_cast<ForwardRange const&>(forwardRange).empty()); 166 167 assert(forwardRange); 168 assert(static_cast<ForwardRange const&>(forwardRange)); 169 170 assert(!std::ranges::empty(forwardRange)); 171 assert(!std::ranges::empty(static_cast<ForwardRange const&>(forwardRange))); 172 173 EmptyIsTrue emptyTrue; 174 assert(emptyTrue.empty()); 175 assert(static_cast<EmptyIsTrue const&>(emptyTrue).empty()); 176 assert(!emptyTrue.std::ranges::view_interface<EmptyIsTrue>::empty()); 177 178 assert(!emptyTrue); 179 assert(!static_cast<EmptyIsTrue const&>(emptyTrue)); 180 assert(!emptyTrue.std::ranges::view_interface<EmptyIsTrue>::operator bool()); 181 182 assert(std::ranges::empty(emptyTrue)); 183 assert(std::ranges::empty(static_cast<EmptyIsTrue const&>(emptyTrue))); 184 185 // Try calling empty on an rvalue. 186 MoveOnlyForwardRange moveOnly; 187 assert(!std::move(moveOnly).empty()); 188 189 BoolConvertibleComparison boolConv; 190 ASSERT_NOT_NOEXCEPT(boolConv.empty()); 191 192 assert(!boolConv.empty()); 193 assert(!static_cast<const BoolConvertibleComparison&>(boolConv).empty()); 194 195 assert(boolConv); 196 assert(static_cast<const BoolConvertibleComparison&>(boolConv)); 197 198 assert(!std::ranges::empty(boolConv)); 199 assert(!std::ranges::empty(static_cast<const BoolConvertibleComparison&>(boolConv))); 200 201 return true; 202 } 203 204 template<class T> 205 concept DataInvocable = requires (T const& obj) { obj.data(); }; 206 207 constexpr bool testData() { 208 static_assert(!DataInvocable<ForwardRange>); 209 static_assert( DataInvocable<ContRange>); 210 211 ContRange contiguous; 212 assert(contiguous.data() == contiguous.buff); 213 assert(static_cast<ContRange const&>(contiguous).data() == contiguous.buff); 214 215 assert(std::ranges::data(contiguous) == contiguous.buff); 216 assert(std::ranges::data(static_cast<ContRange const&>(contiguous)) == contiguous.buff); 217 218 DataIsNull dataNull; 219 assert(dataNull.data() == nullptr); 220 assert(static_cast<DataIsNull const&>(dataNull).data() == nullptr); 221 assert(dataNull.std::ranges::view_interface<DataIsNull>::data() == dataNull.buff); 222 223 assert(std::ranges::data(dataNull) == nullptr); 224 assert(std::ranges::data(static_cast<DataIsNull const&>(dataNull)) == nullptr); 225 226 return true; 227 } 228 229 template<class T> 230 concept SizeInvocable = requires (T const& obj) { obj.size(); }; 231 232 constexpr bool testSize() { 233 static_assert(!SizeInvocable<InputRange>); 234 static_assert(!SizeInvocable<NotSizedSentinel>); 235 static_assert( SizeInvocable<ForwardRange>); 236 237 // Test the test. 238 static_assert(std::same_as<decltype(std::declval<ForwardIter>() - std::declval<ForwardIter>()), std::ptrdiff_t>); 239 using UnsignedSize = std::make_unsigned_t<std::ptrdiff_t>; 240 using SignedSize = std::common_type_t<std::ptrdiff_t, std::make_signed_t<UnsignedSize>>; 241 ForwardRange forwardRange; 242 assert(forwardRange.size() == 8); 243 assert(static_cast<ForwardRange const&>(forwardRange).size() == 8); 244 245 assert(std::ranges::size(forwardRange) == 8); 246 static_assert(std::same_as<decltype(std::ranges::size(std::declval<ForwardRange>())), UnsignedSize>); 247 static_assert(std::same_as<decltype(std::ranges::ssize(std::declval<ForwardRange>())), SignedSize>); 248 249 assert(std::ranges::size(static_cast<ForwardRange const&>(forwardRange)) == 8); 250 static_assert(std::same_as<decltype(std::ranges::size(std::declval<ForwardRange const>())), UnsignedSize>); 251 static_assert(std::same_as<decltype(std::ranges::ssize(std::declval<ForwardRange const>())), SignedSize>); 252 253 SizeIsTen sizeTen; 254 assert(sizeTen.size() == 10); 255 assert(static_cast<SizeIsTen const&>(sizeTen).size() == 10); 256 assert(sizeTen.std::ranges::view_interface<SizeIsTen>::size() == 8); 257 258 assert(std::ranges::size(sizeTen) == 10); 259 assert(std::ranges::size(static_cast<SizeIsTen const&>(sizeTen)) == 10); 260 261 return true; 262 } 263 264 template<class T> 265 concept SubscriptInvocable = requires (T const& obj, std::size_t n) { obj[n]; }; 266 267 constexpr bool testSubscript() { 268 static_assert(!SubscriptInvocable<ForwardRange>); 269 static_assert( SubscriptInvocable<RARange>); 270 271 RARange randomAccess; 272 assert(randomAccess[2] == 2); 273 assert(static_cast<RARange const&>(randomAccess)[2] == 2); 274 randomAccess[2] = 3; 275 assert(randomAccess[2] == 3); 276 277 return true; 278 } 279 280 template<class T> 281 concept FrontInvocable = requires (T const& obj) { obj.front(); }; 282 283 template<class T> 284 concept BackInvocable = requires (T const& obj) { obj.back(); }; 285 286 constexpr bool testFrontBack() { 287 static_assert(!FrontInvocable<InputRange>); 288 static_assert( FrontInvocable<ForwardRange>); 289 static_assert(!BackInvocable<ForwardRange>); 290 static_assert( BackInvocable<RARange>); 291 292 ForwardRange forwardRange; 293 assert(forwardRange.front() == 0); 294 assert(static_cast<ForwardRange const&>(forwardRange).front() == 0); 295 forwardRange.front() = 2; 296 assert(forwardRange.front() == 2); 297 298 RARange randomAccess; 299 assert(randomAccess.front() == 0); 300 assert(static_cast<RARange const&>(randomAccess).front() == 0); 301 randomAccess.front() = 2; 302 assert(randomAccess.front() == 2); 303 304 assert(randomAccess.back() == 7); 305 assert(static_cast<RARange const&>(randomAccess).back() == 7); 306 randomAccess.back() = 2; 307 assert(randomAccess.back() == 2); 308 309 return true; 310 } 311 312 struct V1 : std::ranges::view_interface<V1> { }; 313 struct V2 : std::ranges::view_interface<V2> { V1 base_; }; 314 static_assert(sizeof(V2) == sizeof(V1)); 315 316 int main(int, char**) { 317 testEmpty(); 318 static_assert(testEmpty()); 319 320 testData(); 321 static_assert(testData()); 322 323 testSize(); 324 static_assert(testSize()); 325 326 testSubscript(); 327 static_assert(testSubscript()); 328 329 testFrontBack(); 330 static_assert(testFrontBack()); 331 332 return 0; 333 } 334