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::views::counted;
14 
15 #include <concepts>
16 #include <ranges>
17 #include <span>
18 
19 #include <cassert>
20 #include "test_macros.h"
21 #include "test_iterators.h"
22 
23 struct Unrelated {};
24 
25 struct ConvertibleToSize {
26   constexpr operator std::ptrdiff_t() const { return 8; }
27 };
28 
29 struct ImplicitlyConvertible {
30     operator short();
31     explicit operator std::ptrdiff_t() = delete;
32 };
33 
34 template<class Iter, class T>
35 concept CountedInvocable = requires(Iter& i, T t) { std::views::counted(i, t); };
36 
37 constexpr bool test() {
38   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
39 
40   {
41     static_assert( CountedInvocable<contiguous_iterator<int*>, ConvertibleToSize>);
42     static_assert(!CountedInvocable<contiguous_iterator<int*>, ImplicitlyConvertible>);
43     static_assert(!CountedInvocable<contiguous_iterator<int*>, Unrelated>);
44 
45     static_assert(std::semiregular<std::remove_const_t<decltype(std::views::counted)>>);
46   }
47 
48   {
49     {
50       contiguous_iterator<int*> iter(buffer);
51       std::span<int> s = std::views::counted(iter, 8);
52       assert(s.size() == 8);
53       assert(s.data() == buffer);
54 
55       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)), std::span<int>);
56     }
57     {
58       const contiguous_iterator<int*> iter(buffer);
59       std::span<int> s = std::views::counted(iter, 8);
60       assert(s.size() == 8);
61       assert(s.data() == buffer);
62 
63       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)), std::span<int>);
64     }
65     {
66       contiguous_iterator<const int*> iter(buffer);
67       std::span<const int> s = std::views::counted(iter, 8);
68       assert(s.size() == 8);
69       assert(s.data() == buffer);
70 
71       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)), std::span<const int>);
72     }
73     {
74       const contiguous_iterator<const int*> iter(buffer);
75       std::span<const int> s = std::views::counted(iter, 8);
76       assert(s.size() == 8);
77       assert(s.data() == buffer);
78 
79       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)), std::span<const int>);
80     }
81   }
82 
83   {
84     {
85       random_access_iterator<int*> iter(buffer);
86       std::ranges::subrange<random_access_iterator<int*>> s = std::views::counted(iter, 8);
87       assert(s.size() == 8);
88       assert(s.begin() == iter);
89 
90       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)), std::ranges::subrange<random_access_iterator<int*>>);
91     }
92     {
93       const random_access_iterator<int*> iter(buffer);
94       std::ranges::subrange<random_access_iterator<int*>> s = std::views::counted(iter, 8);
95       assert(s.size() == 8);
96       assert(s.begin() == iter);
97 
98       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)), std::ranges::subrange<random_access_iterator<int*>>);
99     }
100     {
101       random_access_iterator<const int*> iter(buffer);
102       std::ranges::subrange<random_access_iterator<const int*>> s = std::views::counted(iter, 8);
103       assert(s.size() == 8);
104       assert(s.begin() == iter);
105 
106       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)), std::ranges::subrange<random_access_iterator<const int*>>);
107     }
108     {
109       const random_access_iterator<const int*> iter(buffer);
110       std::ranges::subrange<random_access_iterator<const int*>> s = std::views::counted(iter, 8);
111       assert(s.size() == 8);
112       assert(s.begin() == iter);
113 
114       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)), std::ranges::subrange<random_access_iterator<const int*>>);
115     }
116   }
117 
118   {
119     {
120       bidirectional_iterator<int*> iter(buffer);
121       std::ranges::subrange<
122         std::counted_iterator<bidirectional_iterator<int*>>,
123         std::default_sentinel_t> s = std::views::counted(iter, 8);
124       assert(s.size() == 8);
125       assert(s.begin() == std::counted_iterator(iter, 8));
126 
127       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)),
128                        std::ranges::subrange<
129                          std::counted_iterator<bidirectional_iterator<int*>>,
130                          std::default_sentinel_t>);
131     }
132     {
133       const bidirectional_iterator<int*> iter(buffer);
134       std::ranges::subrange<
135         std::counted_iterator<bidirectional_iterator<int*>>,
136         std::default_sentinel_t> s = std::views::counted(iter, 8);
137       assert(s.size() == 8);
138       assert(s.begin() == std::counted_iterator(iter, 8));
139 
140       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)),
141                        std::ranges::subrange<
142                          std::counted_iterator<bidirectional_iterator<int*>>,
143                          std::default_sentinel_t>);
144     }
145     {
146       output_iterator<const int*> iter(buffer);
147       std::ranges::subrange<
148         std::counted_iterator<output_iterator<const int*>>,
149         std::default_sentinel_t> s = std::views::counted(iter, 8);
150       assert(s.size() == 8);
151       assert(s.begin() == std::counted_iterator(iter, 8));
152 
153       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)),
154                        std::ranges::subrange<
155                          std::counted_iterator<output_iterator<const int*>>,
156                          std::default_sentinel_t>);
157     }
158     {
159       const output_iterator<const int*> iter(buffer);
160       std::ranges::subrange<
161         std::counted_iterator<output_iterator<const int*>>,
162         std::default_sentinel_t> s = std::views::counted(iter, 8);
163       assert(s.size() == 8);
164       assert(s.begin() == std::counted_iterator(iter, 8));
165 
166       ASSERT_SAME_TYPE(decltype(std::views::counted(iter, 8)),
167                        std::ranges::subrange<
168                          std::counted_iterator<output_iterator<const int*>>,
169                          std::default_sentinel_t>);
170     }
171     {
172       cpp20_input_iterator<int*> iter(buffer);
173       std::ranges::subrange<
174         std::counted_iterator<cpp20_input_iterator<int*>>,
175         std::default_sentinel_t> s = std::views::counted(std::move(iter), 8);
176       assert(s.size() == 8);
177       assert(s.begin().base().base() == buffer);
178 
179       ASSERT_SAME_TYPE(decltype(std::views::counted(std::move(iter), 8)),
180                        std::ranges::subrange<
181                          std::counted_iterator<cpp20_input_iterator<int*>>,
182                          std::default_sentinel_t>);
183     }
184     {
185       std::ranges::subrange<
186         std::counted_iterator<cpp20_input_iterator<int*>>,
187         std::default_sentinel_t> s = std::views::counted(cpp20_input_iterator<int*>(buffer), 8);
188       assert(s.size() == 8);
189       assert(s.begin().base().base() == buffer);
190 
191       ASSERT_SAME_TYPE(decltype(std::views::counted(cpp20_input_iterator<int*>(buffer), 8)),
192                        std::ranges::subrange<
193                          std::counted_iterator<cpp20_input_iterator<int*>>,
194                          std::default_sentinel_t>);
195     }
196   }
197 
198   {
199     static_assert(std::same_as<decltype(std::views::counted), decltype(std::ranges::views::counted)>);
200   }
201 
202   return true;
203 }
204 
205 int main(int, char**) {
206   test();
207   static_assert(test());
208 
209   return 0;
210 }
211