xref: /llvm-project/libcxx/test/std/ranges/range.access/ssize.pass.cpp (revision 6842f52a0bbf851b43b51fa8dc7dd8dfb533d0e7)
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 static_assert(std::semiregular<std::remove_cv_t<RangeSSizeT>>);
29 
30 struct SizeMember {
31   constexpr size_t size() { return 42; }
32 };
33 static_assert(!std::is_invocable_v<decltype(std::ranges::ssize), const SizeMember&>);
34 
35 struct SizeFunction {
36   friend constexpr size_t size(SizeFunction) { return 42; }
37 };
38 
39 struct SizeFunctionSigned {
40   friend constexpr std::ptrdiff_t size(SizeFunctionSigned) { return 42; }
41 };
42 
43 struct SizedSentinelRange {
44   int data_[2] = {};
45   constexpr int *begin() { return data_; }
46   constexpr auto end() { return sized_sentinel<int*>(data_ + 2); }
47 };
48 
49 struct ShortUnsignedReturnType {
50   constexpr unsigned short size() { return 42; }
51 };
52 
53 // size_t changes depending on the platform.
54 using SignedSizeT = std::make_signed_t<size_t>;
55 
56 constexpr bool test() {
57   int a[4];
58 
59   assert(std::ranges::ssize(a) == 4);
60   ASSERT_SAME_TYPE(decltype(std::ranges::ssize(a)), SignedSizeT);
61 
62   assert(std::ranges::ssize(SizeMember()) == 42);
63   ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeMember())), SignedSizeT);
64 
65   assert(std::ranges::ssize(SizeFunction()) == 42);
66   ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunction())), SignedSizeT);
67 
68   assert(std::ranges::ssize(SizeFunctionSigned()) == 42);
69   ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunctionSigned())), std::ptrdiff_t);
70 
71   SizedSentinelRange b;
72   assert(std::ranges::ssize(b) == 2);
73   ASSERT_SAME_TYPE(decltype(std::ranges::ssize(b)), std::ptrdiff_t);
74 
75   // This gets converted to ptrdiff_t because it's wider.
76   ShortUnsignedReturnType c;
77   assert(std::ranges::ssize(c) == 42);
78   ASSERT_SAME_TYPE(decltype(std::ranges::ssize(c)), ptrdiff_t);
79 
80   return true;
81 }
82 
83 int main(int, char**) {
84   test();
85   static_assert(test());
86 
87   return 0;
88 }
89