1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
11 #define _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
12 
13 #include <__config>
14 #include <__iterator/incrementable_traits.h>
15 #include <__iterator/readable_traits.h>
16 #include <concepts>
17 #include <type_traits>
18 
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #  pragma GCC system_header
21 #endif
22 
23 _LIBCPP_BEGIN_NAMESPACE_STD
24 
25 #if _LIBCPP_STD_VER > 17
26 
27 template <class _Tp>
28 using __with_reference = _Tp&;
29 
30 template <class _Tp>
31 concept __can_reference = requires {
32   typename __with_reference<_Tp>;
33 };
34 
35 template <class _Tp>
36 concept __dereferenceable = requires(_Tp& __t) {
37   { *__t } -> __can_reference; // not required to be equality-preserving
38 };
39 
40 // [iterator.traits]
41 template<__dereferenceable _Tp>
42 using iter_reference_t = decltype(*declval<_Tp&>());
43 
44 #endif // _LIBCPP_STD_VER > 17
45 
46 template <class _Iter>
47 struct _LIBCPP_TEMPLATE_VIS iterator_traits;
48 
49 struct _LIBCPP_TEMPLATE_VIS input_iterator_tag {};
50 struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {};
51 struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag       : public input_iterator_tag {};
52 struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {};
53 struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {};
54 #if _LIBCPP_STD_VER > 17
55 struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag    : public random_access_iterator_tag {};
56 #endif
57 
58 template <class _Iter>
59 struct __iter_traits_cache {
60   using type = _If<
61     __is_primary_template<iterator_traits<_Iter> >::value,
62     _Iter,
63     iterator_traits<_Iter>
64   >;
65 };
66 template <class _Iter>
67 using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type;
68 
69 struct __iter_concept_concept_test {
70   template <class _Iter>
71   using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept;
72 };
73 struct __iter_concept_category_test {
74   template <class _Iter>
75   using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category;
76 };
77 struct __iter_concept_random_fallback {
78   template <class _Iter>
79   using _Apply = __enable_if_t<
80                           __is_primary_template<iterator_traits<_Iter> >::value,
81                           random_access_iterator_tag
82                         >;
83 };
84 
85 template <class _Iter, class _Tester> struct __test_iter_concept
86     : _IsValidExpansion<_Tester::template _Apply, _Iter>,
87       _Tester
88 {
89 };
90 
91 template <class _Iter>
92 struct __iter_concept_cache {
93   using type = _Or<
94     __test_iter_concept<_Iter, __iter_concept_concept_test>,
95     __test_iter_concept<_Iter, __iter_concept_category_test>,
96     __test_iter_concept<_Iter, __iter_concept_random_fallback>
97   >;
98 };
99 
100 template <class _Iter>
101 using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>;
102 
103 
104 template <class _Tp>
105 struct __has_iterator_typedefs
106 {
107 private:
108     template <class _Up> static false_type __test(...);
109     template <class _Up> static true_type __test(typename __void_t<typename _Up::iterator_category>::type* = 0,
110                                                  typename __void_t<typename _Up::difference_type>::type* = 0,
111                                                  typename __void_t<typename _Up::value_type>::type* = 0,
112                                                  typename __void_t<typename _Up::reference>::type* = 0,
113                                                  typename __void_t<typename _Up::pointer>::type* = 0);
114 public:
115     static const bool value = decltype(__test<_Tp>(0,0,0,0,0))::value;
116 };
117 
118 
119 template <class _Tp>
120 struct __has_iterator_category
121 {
122 private:
123     template <class _Up> static false_type __test(...);
124     template <class _Up> static true_type __test(typename _Up::iterator_category* = nullptr);
125 public:
126     static const bool value = decltype(__test<_Tp>(nullptr))::value;
127 };
128 
129 template <class _Tp>
130 struct __has_iterator_concept
131 {
132 private:
133     template <class _Up> static false_type __test(...);
134     template <class _Up> static true_type __test(typename _Up::iterator_concept* = nullptr);
135 public:
136     static const bool value = decltype(__test<_Tp>(nullptr))::value;
137 };
138 
139 #if _LIBCPP_STD_VER > 17
140 
141 // The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements
142 // from `[iterator.cpp17]`. To avoid confusion between the two, the exposition-only concepts have been banished to
143 // a "detail" namespace indicating they have a niche use-case.
144 namespace __iterator_traits_detail {
145 template<class _Ip>
146 concept __cpp17_iterator =
147   requires(_Ip __i) {
148     {   *__i } -> __can_reference;
149     {  ++__i } -> same_as<_Ip&>;
150     { *__i++ } -> __can_reference;
151   } &&
152   copyable<_Ip>;
153 
154 template<class _Ip>
155 concept __cpp17_input_iterator =
156   __cpp17_iterator<_Ip> &&
157   equality_comparable<_Ip> &&
158   requires(_Ip __i) {
159     typename incrementable_traits<_Ip>::difference_type;
160     typename indirectly_readable_traits<_Ip>::value_type;
161     typename common_reference_t<iter_reference_t<_Ip>&&,
162                                 typename indirectly_readable_traits<_Ip>::value_type&>;
163     typename common_reference_t<decltype(*__i++)&&,
164                                 typename indirectly_readable_traits<_Ip>::value_type&>;
165     requires signed_integral<typename incrementable_traits<_Ip>::difference_type>;
166   };
167 
168 template<class _Ip>
169 concept __cpp17_forward_iterator =
170   __cpp17_input_iterator<_Ip> &&
171   constructible_from<_Ip> &&
172   is_lvalue_reference_v<iter_reference_t<_Ip>> &&
173   same_as<remove_cvref_t<iter_reference_t<_Ip>>,
174           typename indirectly_readable_traits<_Ip>::value_type> &&
175   requires(_Ip __i) {
176     {  __i++ } -> convertible_to<_Ip const&>;
177     { *__i++ } -> same_as<iter_reference_t<_Ip>>;
178   };
179 
180 template<class _Ip>
181 concept __cpp17_bidirectional_iterator =
182   __cpp17_forward_iterator<_Ip> &&
183   requires(_Ip __i) {
184     {  --__i } -> same_as<_Ip&>;
185     {  __i-- } -> convertible_to<_Ip const&>;
186     { *__i-- } -> same_as<iter_reference_t<_Ip>>;
187   };
188 
189 template<class _Ip>
190 concept __cpp17_random_access_iterator =
191   __cpp17_bidirectional_iterator<_Ip> &&
192   totally_ordered<_Ip> &&
193   requires(_Ip __i, typename incrementable_traits<_Ip>::difference_type __n) {
194     { __i += __n } -> same_as<_Ip&>;
195     { __i -= __n } -> same_as<_Ip&>;
196     { __i +  __n } -> same_as<_Ip>;
197     { __n +  __i } -> same_as<_Ip>;
198     { __i -  __n } -> same_as<_Ip>;
199     { __i -  __i } -> same_as<decltype(__n)>; // NOLINT(misc-redundant-expression) ; This is llvm.org/PR54114
200     {  __i[__n]  } -> convertible_to<iter_reference_t<_Ip>>;
201   };
202 } // namespace __iterator_traits_detail
203 
204 template<class _Ip>
205 concept __has_member_reference = requires { typename _Ip::reference; };
206 
207 template<class _Ip>
208 concept __has_member_pointer = requires { typename _Ip::pointer; };
209 
210 template<class _Ip>
211 concept __has_member_iterator_category = requires { typename _Ip::iterator_category; };
212 
213 template<class _Ip>
214 concept __specifies_members = requires {
215     typename _Ip::value_type;
216     typename _Ip::difference_type;
217     requires __has_member_reference<_Ip>;
218     requires __has_member_iterator_category<_Ip>;
219   };
220 
221 template<class>
222 struct __iterator_traits_member_pointer_or_void {
223   using type = void;
224 };
225 
226 template<__has_member_pointer _Tp>
227 struct __iterator_traits_member_pointer_or_void<_Tp> {
228   using type = typename _Tp::pointer;
229 };
230 
231 template<class _Tp>
232 concept __cpp17_iterator_missing_members =
233   !__specifies_members<_Tp> &&
234   __iterator_traits_detail::__cpp17_iterator<_Tp>;
235 
236 template<class _Tp>
237 concept __cpp17_input_iterator_missing_members =
238   __cpp17_iterator_missing_members<_Tp> &&
239   __iterator_traits_detail::__cpp17_input_iterator<_Tp>;
240 
241 // Otherwise, `pointer` names `void`.
242 template<class>
243 struct __iterator_traits_member_pointer_or_arrow_or_void { using type = void; };
244 
245 // [iterator.traits]/3.2.1
246 // If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type.
247 template<__has_member_pointer _Ip>
248 struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typename _Ip::pointer; };
249 
250 // Otherwise, if `decltype(declval<I&>().operator->())` is well-formed, then `pointer` names that
251 // type.
252 template<class _Ip>
253   requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>)
254 struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> {
255   using type = decltype(declval<_Ip&>().operator->());
256 };
257 
258 // Otherwise, `reference` names `iter-reference-t<I>`.
259 template<class _Ip>
260 struct __iterator_traits_member_reference { using type = iter_reference_t<_Ip>; };
261 
262 // [iterator.traits]/3.2.2
263 // If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type.
264 template<__has_member_reference _Ip>
265 struct __iterator_traits_member_reference<_Ip> { using type = typename _Ip::reference; };
266 
267 // [iterator.traits]/3.2.3.4
268 // input_iterator_tag
269 template<class _Ip>
270 struct __deduce_iterator_category {
271   using type = input_iterator_tag;
272 };
273 
274 // [iterator.traits]/3.2.3.1
275 // `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise
276 template<__iterator_traits_detail::__cpp17_random_access_iterator _Ip>
277 struct __deduce_iterator_category<_Ip> {
278   using type = random_access_iterator_tag;
279 };
280 
281 // [iterator.traits]/3.2.3.2
282 // `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise
283 template<__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip>
284 struct __deduce_iterator_category<_Ip> {
285   using type = bidirectional_iterator_tag;
286 };
287 
288 // [iterator.traits]/3.2.3.3
289 // `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise
290 template<__iterator_traits_detail::__cpp17_forward_iterator _Ip>
291 struct __deduce_iterator_category<_Ip> {
292   using type = forward_iterator_tag;
293 };
294 
295 template<class _Ip>
296 struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {};
297 
298 // [iterator.traits]/3.2.3
299 // If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names
300 // that type.
301 template<__has_member_iterator_category _Ip>
302 struct __iterator_traits_iterator_category<_Ip> {
303   using type = typename _Ip::iterator_category;
304 };
305 
306 // otherwise, it names void.
307 template<class>
308 struct __iterator_traits_difference_type { using type = void; };
309 
310 // If the qualified-id `incrementable_traits<I>::difference_type` is valid and denotes a type, then
311 // `difference_type` names that type;
312 template<class _Ip>
313 requires requires { typename incrementable_traits<_Ip>::difference_type; }
314 struct __iterator_traits_difference_type<_Ip> {
315   using type = typename incrementable_traits<_Ip>::difference_type;
316 };
317 
318 // [iterator.traits]/3.4
319 // Otherwise, `iterator_traits<I>` has no members by any of the above names.
320 template<class>
321 struct __iterator_traits {};
322 
323 // [iterator.traits]/3.1
324 // If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and
325 // `iterator-category`, then `iterator-traits<I>` has the following publicly accessible members:
326 template<__specifies_members _Ip>
327 struct __iterator_traits<_Ip> {
328   using iterator_category  = typename _Ip::iterator_category;
329   using value_type         = typename _Ip::value_type;
330   using difference_type    = typename _Ip::difference_type;
331   using pointer            = typename __iterator_traits_member_pointer_or_void<_Ip>::type;
332   using reference          = typename _Ip::reference;
333 };
334 
335 // [iterator.traits]/3.2
336 // Otherwise, if `I` satisfies the exposition-only concept `cpp17-input-iterator`,
337 // `iterator-traits<I>` has the following publicly accessible members:
338 template<__cpp17_input_iterator_missing_members _Ip>
339 struct __iterator_traits<_Ip> {
340   using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type;
341   using value_type        = typename indirectly_readable_traits<_Ip>::value_type;
342   using difference_type   = typename incrementable_traits<_Ip>::difference_type;
343   using pointer           = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type;
344   using reference         = typename __iterator_traits_member_reference<_Ip>::type;
345 };
346 
347 // Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then
348 // `iterator_traits<I>` has the following publicly accessible members:
349 template<__cpp17_iterator_missing_members _Ip>
350 struct __iterator_traits<_Ip> {
351   using iterator_category = output_iterator_tag;
352   using value_type        = void;
353   using difference_type   = typename __iterator_traits_difference_type<_Ip>::type;
354   using pointer           = void;
355   using reference         = void;
356 };
357 
358 template<class _Ip>
359 struct iterator_traits : __iterator_traits<_Ip> {
360   using __primary_template = iterator_traits;
361 };
362 
363 #else // _LIBCPP_STD_VER > 17
364 
365 template <class _Iter, bool> struct __iterator_traits {};
366 
367 template <class _Iter, bool> struct __iterator_traits_impl {};
368 
369 template <class _Iter>
370 struct __iterator_traits_impl<_Iter, true>
371 {
372     typedef typename _Iter::difference_type   difference_type;
373     typedef typename _Iter::value_type        value_type;
374     typedef typename _Iter::pointer           pointer;
375     typedef typename _Iter::reference         reference;
376     typedef typename _Iter::iterator_category iterator_category;
377 };
378 
379 template <class _Iter>
380 struct __iterator_traits<_Iter, true>
381     :  __iterator_traits_impl
382       <
383         _Iter,
384         is_convertible<typename _Iter::iterator_category, input_iterator_tag>::value ||
385         is_convertible<typename _Iter::iterator_category, output_iterator_tag>::value
386       >
387 {};
388 
389 // iterator_traits<Iterator> will only have the nested types if Iterator::iterator_category
390 //    exists.  Else iterator_traits<Iterator> will be an empty class.  This is a
391 //    conforming extension which allows some programs to compile and behave as
392 //    the client expects instead of failing at compile time.
393 
394 template <class _Iter>
395 struct _LIBCPP_TEMPLATE_VIS iterator_traits
396     : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {
397 
398   using __primary_template = iterator_traits;
399 };
400 #endif // _LIBCPP_STD_VER > 17
401 
402 template<class _Tp>
403 #if _LIBCPP_STD_VER > 17
404 requires is_object_v<_Tp>
405 #endif
406 struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*>
407 {
408     typedef ptrdiff_t difference_type;
409     typedef typename remove_cv<_Tp>::type value_type;
410     typedef _Tp* pointer;
411     typedef _Tp& reference;
412     typedef random_access_iterator_tag iterator_category;
413 #if _LIBCPP_STD_VER > 17
414     typedef contiguous_iterator_tag    iterator_concept;
415 #endif
416 };
417 
418 template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value>
419 struct __has_iterator_category_convertible_to
420     : is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>
421 {};
422 
423 template <class _Tp, class _Up>
424 struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {};
425 
426 template <class _Tp, class _Up, bool = __has_iterator_concept<_Tp>::value>
427 struct __has_iterator_concept_convertible_to
428     : is_convertible<typename _Tp::iterator_concept, _Up>
429 {};
430 
431 template <class _Tp, class _Up>
432 struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {};
433 
434 template <class _Tp>
435 struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {};
436 
437 template <class _Tp>
438 struct __is_cpp17_forward_iterator : public __has_iterator_category_convertible_to<_Tp, forward_iterator_tag> {};
439 
440 template <class _Tp>
441 struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag> {};
442 
443 template <class _Tp>
444 struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {};
445 
446 // __is_cpp17_contiguous_iterator determines if an iterator is known by
447 // libc++ to be contiguous, either because it advertises itself as such
448 // (in C++20) or because it is a pointer type or a known trivial wrapper
449 // around a (possibly fancy) pointer type, such as __wrap_iter<T*>.
450 // Such iterators receive special "contiguous" optimizations in
451 // std::copy and std::sort.
452 //
453 #if _LIBCPP_STD_VER > 17
454 template <class _Tp>
455 struct __is_cpp17_contiguous_iterator : _Or<
456     __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>,
457     __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag>
458 > {};
459 #else
460 template <class _Tp>
461 struct __is_cpp17_contiguous_iterator : false_type {};
462 #endif
463 
464 // Any native pointer which is an iterator is also a contiguous iterator.
465 template <class _Up>
466 struct __is_cpp17_contiguous_iterator<_Up*> : true_type {};
467 
468 
469 template <class _Iter>
470 class __wrap_iter;
471 
472 template <class _Tp>
473 struct __is_exactly_cpp17_input_iterator
474     : public integral_constant<bool,
475          __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value &&
476         !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {};
477 
478 template<class _InputIterator>
479 using __iter_value_type = typename iterator_traits<_InputIterator>::value_type;
480 
481 template<class _InputIterator>
482 using __iter_key_type = typename remove_const<typename iterator_traits<_InputIterator>::value_type::first_type>::type;
483 
484 template<class _InputIterator>
485 using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type;
486 
487 template<class _InputIterator>
488 using __iter_to_alloc_type = pair<
489     typename add_const<typename iterator_traits<_InputIterator>::value_type::first_type>::type,
490     typename iterator_traits<_InputIterator>::value_type::second_type>;
491 
492 _LIBCPP_END_NAMESPACE_STD
493 
494 #endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
495