1 // Copyright (C) 2020-2021 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3.  If not see
16 // <http://www.gnu.org/licenses/>.
17 
18 // { dg-options "-std=gnu++2a" }
19 // { dg-do run { target c++2a } }
20 
21 #include <ranges>
22 #include <testsuite_hooks.h>
23 #include <testsuite_iterators.h>
24 
25 static_assert(__gnu_test::is_customization_point_object(std::ranges::ssize));
26 
27 using std::ptrdiff_t;
28 
29 void
test01()30 test01()
31 {
32   constexpr int a[10] = { };
33   static_assert( std::same_as<decltype(std::ranges::ssize(a)), ptrdiff_t> );
34   static_assert( std::ranges::ssize(a) == 10 );
35   static_assert( noexcept(std::ranges::ssize(a)) );
36 
37   int a2[2];
38   static_assert( std::same_as<decltype(std::ranges::ssize(a2)), ptrdiff_t> );
39   VERIFY( std::ranges::ssize(a2) == 2);
40   static_assert( noexcept(std::ranges::ssize(a2)) );
41 }
42 
43 void
test02()44 test02()
45 {
46   int a[3] = { };
47   __gnu_test::test_sized_range<int, __gnu_test::input_iterator_wrapper> ri(a);
48   VERIFY( std::ranges::ssize(ri) == 3 );
49   static_assert( noexcept(std::ranges::ssize(ri)) );
50 }
51 
52 void
test04()53 test04()
54 {
55   int a[] = { 0, 1 };
56   __gnu_test::test_range<int, __gnu_test::random_access_iterator_wrapper> r(a);
57   VERIFY( std::ranges::ssize(r) == std::ranges::end(r) - std::ranges::begin(r) );
58 }
59 
60 struct R5
61 {
sizeR562   int size() const noexcept { return 0; }
beginR563   R5* begin() { return this; }
endR564   R5* end() { return this + 1; }
65 };
66 
67 template<>
68 constexpr bool std::ranges::disable_sized_range<R5> = true;
69 
70 void
test05()71 test05()
72 {
73   R5 r;
74   VERIFY( std::ranges::ssize(r) == 1 );
75 }
76 
77 void
test06()78 test06()
79 {
80   auto i = std::views::iota(1ull, 5u);
81   auto s = std::ranges::size(i);
82   auto ss = std::ranges::ssize(i);
83   // std::ranges::range_difference_t<decltype(i)> is larger than long long,
84   // but LWG 3403 says ranges::ssize(i) returns the signed version of the
85   // type that ranges::size(i) returns, not the range's difference_type.
86   static_assert( std::same_as<decltype(ss), std::make_signed_t<decltype(s)>> );
87   VERIFY( s == 4 );
88 }
89 
90 void
test07()91 test07()
92 {
93 #ifdef __SIZEOF_INT128__
94   struct R
95   {
96     unsigned __int128 size() const { return 4; }
97   };
98   R r;
99   static_assert( std::same_as<decltype(std::ranges::ssize(r)), __int128> );
100   VERIFY( std::ranges::ssize(r) == 4 );
101 #endif
102 }
103 
104 int
main()105 main()
106 {
107   test01();
108   test02();
109   test04();
110   test05();
111   test06();
112   test07();
113 }
114