1 // Copyright (C) 2019-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 void
test01()26 test01()
27 {
28   constexpr int a[10] = { };
29   static_assert( std::ranges::size(a) == 10 );
30   static_assert( noexcept(std::ranges::size(a)) );
31 
32   int a2[2];
33   VERIFY( std::ranges::size(a2) == 2);
34   static_assert( noexcept(std::ranges::size(a2)) );
35 
36   struct Incomplete;
37   using A = Incomplete[2]; // bounded array of incomplete type
38   extern A& f();
39   static_assert( std::same_as<decltype(std::ranges::size(f())), std::size_t> );
40 }
41 
42 void
test02()43 test02()
44 {
45   struct R
46   {
47     int size() { return 1; }
48     long size() const noexcept { return 2; }
49   };
50   R r;
51   const R& c = r;
52   VERIFY( std::ranges::size(r) == 1 );
53   static_assert( !noexcept(std::ranges::size(r)) );
54   VERIFY( std::ranges::size(c) == 2L );
55   static_assert( noexcept(std::ranges::size(c)) );
56 
57   int a[3] = { };
58   __gnu_test::test_sized_range<int, __gnu_test::input_iterator_wrapper> ri(a);
59   VERIFY( std::ranges::size(ri) == 3 );
60   static_assert( noexcept(std::ranges::size(ri)) );
61 }
62 
63 struct R3
64 {
sizeR365   int* size() { return nullptr; }
size(R3 &)66   friend int size(R3&) noexcept { return 1; }
size(const R3 &)67   friend long size(const R3&) { return 2L; }
size(R3 &&)68   friend unsigned int size(R3&&) { return 3U; }
size(const R3 &&)69   friend unsigned long size(const R3&&) noexcept { return 4UL; }
70 };
71 
72 void
test03()73 test03()
74 {
75   R3 r;
76   const R3& c = r;
77   VERIFY( std::ranges::size(r) == 1 );
78   static_assert( noexcept(std::ranges::size(r)) );
79   // PR libstdc++/100824
80   // ranges::size should treat the subexpression as an lvalue
81   VERIFY( std::ranges::size(std::move(r)) == 1 );
82   static_assert( noexcept(std::ranges::size(std::move(r))) );
83   VERIFY( std::ranges::size(c) == 2L );
84   static_assert( !noexcept(std::ranges::size(c)) );
85   VERIFY( std::ranges::size(std::move(c)) == 2L );
86   static_assert( !noexcept(std::ranges::size(std::move(c))) );
87 }
88 
89 void
test04()90 test04()
91 {
92   int a[] = { 0, 1 };
93   __gnu_test::test_range<int, __gnu_test::random_access_iterator_wrapper> r(a);
94   VERIFY( std::ranges::size(r) == unsigned(std::ranges::end(r) - std::ranges::begin(r)) );
95 }
96 
97 struct R5
98 {
sizeR599   int size() const noexcept { return 0; }
beginR5100   R5* begin() { return this; }
endR5101   R5* end() { return this + 1; }
102 };
103 
104 template<>
105 constexpr bool std::ranges::disable_sized_range<R5> = true;
106 
107 void
test05()108 test05()
109 {
110   R5 r;
111   VERIFY( std::ranges::size(r) == 1 );
112 }
113 
114 void
test06()115 test06()
116 {
117   // PR libstdc++/100824
118   // ranges::size should treat the subexpression as an lvalue
119   struct R { constexpr int size() & { return 42; } };
120   static_assert( std::ranges::size(R{}) == 42 );
121 }
122 
123 int
main()124 main()
125 {
126   test01();
127   test02();
128   test03();
129   test04();
130   test05();
131   test06();
132 }
133