xref: /llvm-project/libcxx/test/std/ranges/range.access/ssize.pass.cpp (revision 9be193bc58b356e2d2e0bddff59a404358e2c75e)
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