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-has-no-incomplete-ranges 11 12 // std::ranges::ssize 13 14 #include <ranges> 15 16 #include <cassert> 17 #include "test_macros.h" 18 #include "test_iterators.h" 19 20 using RangeSSizeT = decltype(std::ranges::ssize); 21 22 static_assert(!std::is_invocable_v<RangeSSizeT, int[]>); 23 static_assert( std::is_invocable_v<RangeSSizeT, int[1]>); 24 static_assert( std::is_invocable_v<RangeSSizeT, int (&&)[1]>); 25 static_assert( std::is_invocable_v<RangeSSizeT, int (&)[1]>); 26 27 struct SizeMember { 28 constexpr size_t size() { return 42; } 29 }; 30 static_assert(!std::is_invocable_v<decltype(std::ranges::ssize), const SizeMember&>); 31 32 struct SizeFunction { 33 friend constexpr size_t size(SizeFunction) { return 42; } 34 }; 35 36 struct SizeFunctionSigned { 37 friend constexpr std::ptrdiff_t size(SizeFunctionSigned) { return 42; } 38 }; 39 40 struct SizedSentinelRange { 41 int data_[2] = {}; 42 constexpr int *begin() { return data_; } 43 constexpr auto end() { return sized_sentinel<int*>(data_ + 2); } 44 }; 45 46 struct ShortUnsignedReturnType { 47 constexpr unsigned short size() { return 42; } 48 }; 49 50 // size_t changes depending on the platform. 51 using SignedSizeT = std::make_signed_t<size_t>; 52 53 constexpr bool test() { 54 int a[4]; 55 56 assert(std::ranges::ssize(a) == 4); 57 ASSERT_SAME_TYPE(decltype(std::ranges::ssize(a)), SignedSizeT); 58 59 assert(std::ranges::ssize(SizeMember()) == 42); 60 ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeMember())), SignedSizeT); 61 62 assert(std::ranges::ssize(SizeFunction()) == 42); 63 ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunction())), SignedSizeT); 64 65 assert(std::ranges::ssize(SizeFunctionSigned()) == 42); 66 ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunctionSigned())), std::ptrdiff_t); 67 68 SizedSentinelRange b; 69 assert(std::ranges::ssize(b) == 2); 70 ASSERT_SAME_TYPE(decltype(std::ranges::ssize(b)), std::ptrdiff_t); 71 72 // This gets converted to ptrdiff_t because it's wider. 73 ShortUnsignedReturnType c; 74 assert(std::ranges::ssize(c) == 42); 75 ASSERT_SAME_TYPE(decltype(std::ranges::ssize(c)), ptrdiff_t); 76 77 return true; 78 } 79 80 // Test ADL-proofing. 81 struct Incomplete; 82 template<class T> struct Holder { T t; }; 83 static_assert(!std::is_invocable_v<RangeSSizeT, Holder<Incomplete>*>); 84 static_assert(!std::is_invocable_v<RangeSSizeT, Holder<Incomplete>*&>); 85 86 int main(int, char**) { 87 test(); 88 static_assert(test()); 89 90 return 0; 91 } 92