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