//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 // std::ranges::data #include #include #include #include "test_macros.h" #include "test_iterators.h" using RangeDataT = decltype(std::ranges::data); using RangeCDataT = decltype(std::ranges::cdata); static int globalBuff[2]; struct Incomplete; static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); struct DataMember { int x; constexpr const int *data() const { return &x; } }; static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); constexpr bool testReturnTypes() { { int *x[2]; ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int**); ASSERT_SAME_TYPE(decltype(std::ranges::cdata(x)), int* const*); } { int x[2][2]; ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int(*)[2]); ASSERT_SAME_TYPE(decltype(std::ranges::cdata(x)), const int(*)[2]); } { struct D { char*& data(); short*& data() const; }; ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval())), char*); static_assert(!std::is_invocable_v); ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval())), short*); static_assert(!std::is_invocable_v); ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval())), short*); static_assert(!std::is_invocable_v); ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval())), short*); static_assert(!std::is_invocable_v); } { struct NC { char *begin() const; char *end() const; int *data(); }; static_assert(!std::ranges::contiguous_range); static_assert( std::ranges::contiguous_range); ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval())), int*); static_assert(!std::is_invocable_v); ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval())), char*); static_assert(!std::is_invocable_v); ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval())), char*); static_assert(!std::is_invocable_v); ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval())), char*); static_assert(!std::is_invocable_v); } return true; } struct VoidDataMember { void *data() const; }; static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); struct Empty { }; struct EmptyDataMember { Empty data() const; }; static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); struct PtrConvertibleDataMember { struct Ptr { operator int*() const; }; Ptr data() const; }; static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); struct NonConstDataMember { int x; constexpr int *data() { return &x; } }; struct EnabledBorrowingDataMember { constexpr int *data() { return &globalBuff[0]; } }; template<> inline constexpr bool std::ranges::enable_borrowed_range = true; struct DataMemberAndBegin { int x; constexpr const int *data() const { return &x; } const int *begin() const; }; constexpr bool testDataMember() { DataMember a; assert(std::ranges::data(a) == &a.x); assert(std::ranges::cdata(a) == &a.x); NonConstDataMember b; assert(std::ranges::data(b) == &b.x); static_assert(!std::is_invocable_v); EnabledBorrowingDataMember c; assert(std::ranges::data(std::move(c)) == &globalBuff[0]); static_assert(!std::is_invocable_v); DataMemberAndBegin d; assert(std::ranges::data(d) == &d.x); assert(std::ranges::cdata(d) == &d.x); return true; } using ContiguousIter = contiguous_iterator; struct BeginMemberContiguousIterator { int buff[8]; constexpr ContiguousIter begin() const { return ContiguousIter(buff); } }; static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); struct BeginMemberRandomAccess { int buff[8]; random_access_iterator begin() const; }; static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); struct BeginFriendContiguousIterator { int buff[8]; friend constexpr ContiguousIter begin(const BeginFriendContiguousIterator &iter) { return ContiguousIter(iter.buff); } }; static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); struct BeginFriendRandomAccess { friend random_access_iterator begin(const BeginFriendRandomAccess iter); }; static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); struct BeginMemberRvalue { int buff[8]; ContiguousIter begin() &&; }; static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); struct BeginMemberBorrowingEnabled { constexpr contiguous_iterator begin() { return contiguous_iterator{&globalBuff[1]}; } }; template<> inline constexpr bool std::ranges::enable_borrowed_range = true; static_assert( std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); constexpr bool testViaRangesBegin() { int arr[2]; assert(std::ranges::data(arr) == arr + 0); assert(std::ranges::cdata(arr) == arr + 0); BeginMemberContiguousIterator a; assert(std::ranges::data(a) == a.buff); assert(std::ranges::cdata(a) == a.buff); const BeginFriendContiguousIterator b {}; assert(std::ranges::data(b) == b.buff); assert(std::ranges::cdata(b) == b.buff); BeginMemberBorrowingEnabled c; assert(std::ranges::data(std::move(c)) == &globalBuff[1]); static_assert(!std::is_invocable_v); return true; } // Test ADL-proofing. struct Incomplete; template struct Holder { T t; }; static_assert(!std::is_invocable_v*>); static_assert(!std::is_invocable_v*&>); static_assert(!std::is_invocable_v*>); static_assert(!std::is_invocable_v*&>); struct RandomButNotContiguous { random_access_iterator begin() const; random_access_iterator end() const; }; static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); int main(int, char**) { static_assert(testReturnTypes()); testDataMember(); static_assert(testDataMember()); testViaRangesBegin(); static_assert(testViaRangesBegin()); return 0; }