xref: /freebsd-src/contrib/llvm-project/libcxx/include/__iterator/iterator_traits.h (revision 8cc087a1eee9ec1ca9f7ac1e63ad51bdb5a682eb)
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 !defined(_LIBCPP_HAS_NO_CONCEPTS)
26 
27 template <class _Tp>
28 using __with_reference = _Tp&;
29 
30 template <class _Tp>
31 concept __referenceable = requires {
32   typename __with_reference<_Tp>;
33 };
34 
35 template <class _Tp>
36 concept __dereferenceable = requires(_Tp& __t) {
37   { *__t } -> __referenceable; // 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 // !defined(_LIBCPP_HAS_NO_CONCEPTS)
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     struct __two {char __lx; char __lxx;};
109     template <class _Up> static __two __test(...);
110     template <class _Up> static char __test(typename __void_t<typename _Up::iterator_category>::type* = 0,
111                                             typename __void_t<typename _Up::difference_type>::type* = 0,
112                                             typename __void_t<typename _Up::value_type>::type* = 0,
113                                             typename __void_t<typename _Up::reference>::type* = 0,
114                                             typename __void_t<typename _Up::pointer>::type* = 0);
115 public:
116     static const bool value = sizeof(__test<_Tp>(0,0,0,0,0)) == 1;
117 };
118 
119 
120 template <class _Tp>
121 struct __has_iterator_category
122 {
123 private:
124     struct __two {char __lx; char __lxx;};
125     template <class _Up> static __two __test(...);
126     template <class _Up> static char __test(typename _Up::iterator_category* = nullptr);
127 public:
128     static const bool value = sizeof(__test<_Tp>(nullptr)) == 1;
129 };
130 
131 template <class _Tp>
132 struct __has_iterator_concept
133 {
134 private:
135     struct __two {char __lx; char __lxx;};
136     template <class _Up> static __two __test(...);
137     template <class _Up> static char __test(typename _Up::iterator_concept* = nullptr);
138 public:
139     static const bool value = sizeof(__test<_Tp>(nullptr)) == 1;
140 };
141 
142 #if !defined(_LIBCPP_HAS_NO_CONCEPTS)
143 
144 // The `cpp17-*-iterator` exposition-only concepts are easily confused with the Cpp17*Iterator tables,
145 // so they've been banished to a namespace that makes it obvious they have a niche use-case.
146 namespace __iterator_traits_detail {
147 template<class _Ip>
148 concept __cpp17_iterator =
149   requires(_Ip __i) {
150     {   *__i } -> __referenceable;
151     {  ++__i } -> same_as<_Ip&>;
152     { *__i++ } -> __referenceable;
153   } &&
154   copyable<_Ip>;
155 
156 template<class _Ip>
157 concept __cpp17_input_iterator =
158   __cpp17_iterator<_Ip> &&
159   equality_comparable<_Ip> &&
160   requires(_Ip __i) {
161     typename incrementable_traits<_Ip>::difference_type;
162     typename indirectly_readable_traits<_Ip>::value_type;
163     typename common_reference_t<iter_reference_t<_Ip>&&,
164                                 typename indirectly_readable_traits<_Ip>::value_type&>;
165     typename common_reference_t<decltype(*__i++)&&,
166                                 typename indirectly_readable_traits<_Ip>::value_type&>;
167     requires signed_integral<typename incrementable_traits<_Ip>::difference_type>;
168   };
169 
170 template<class _Ip>
171 concept __cpp17_forward_iterator =
172   __cpp17_input_iterator<_Ip> &&
173   constructible_from<_Ip> &&
174   is_lvalue_reference_v<iter_reference_t<_Ip>> &&
175   same_as<remove_cvref_t<iter_reference_t<_Ip>>,
176           typename indirectly_readable_traits<_Ip>::value_type> &&
177   requires(_Ip __i) {
178     {  __i++ } -> convertible_to<_Ip const&>;
179     { *__i++ } -> same_as<iter_reference_t<_Ip>>;
180   };
181 
182 template<class _Ip>
183 concept __cpp17_bidirectional_iterator =
184   __cpp17_forward_iterator<_Ip> &&
185   requires(_Ip __i) {
186     {  --__i } -> same_as<_Ip&>;
187     {  __i-- } -> convertible_to<_Ip const&>;
188     { *__i-- } -> same_as<iter_reference_t<_Ip>>;
189   };
190 
191 template<class _Ip>
192 concept __cpp17_random_access_iterator =
193   __cpp17_bidirectional_iterator<_Ip> &&
194   totally_ordered<_Ip> &&
195   requires(_Ip __i, typename incrementable_traits<_Ip>::difference_type __n) {
196     { __i += __n } -> same_as<_Ip&>;
197     { __i -= __n } -> same_as<_Ip&>;
198     { __i +  __n } -> same_as<_Ip>;
199     { __n +  __i } -> same_as<_Ip>;
200     { __i -  __n } -> same_as<_Ip>;
201     { __i -  __i } -> same_as<decltype(__n)>;
202     {  __i[__n]  } -> convertible_to<iter_reference_t<_Ip>>;
203   };
204 } // namespace __iterator_traits_detail
205 
206 template<class _Ip>
207 concept __has_member_reference = requires { typename _Ip::reference; };
208 
209 template<class _Ip>
210 concept __has_member_pointer = requires { typename _Ip::pointer; };
211 
212 template<class _Ip>
213 concept __has_member_iterator_category = requires { typename _Ip::iterator_category; };
214 
215 template<class _Ip>
216 concept __specifies_members = requires {
217     typename _Ip::value_type;
218     typename _Ip::difference_type;
219     requires __has_member_reference<_Ip>;
220     requires __has_member_iterator_category<_Ip>;
221   };
222 
223 template<class>
224 struct __iterator_traits_member_pointer_or_void {
225   using type = void;
226 };
227 
228 template<__has_member_pointer _Tp>
229 struct __iterator_traits_member_pointer_or_void<_Tp> {
230   using type = typename _Tp::pointer;
231 };
232 
233 template<class _Tp>
234 concept __cpp17_iterator_missing_members =
235   !__specifies_members<_Tp> &&
236   __iterator_traits_detail::__cpp17_iterator<_Tp>;
237 
238 template<class _Tp>
239 concept __cpp17_input_iterator_missing_members =
240   __cpp17_iterator_missing_members<_Tp> &&
241   __iterator_traits_detail::__cpp17_input_iterator<_Tp>;
242 
243 // Otherwise, `pointer` names `void`.
244 template<class>
245 struct __iterator_traits_member_pointer_or_arrow_or_void { using type = void; };
246 
247 // [iterator.traits]/3.2.1
248 // If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type.
249 template<__has_member_pointer _Ip>
250 struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typename _Ip::pointer; };
251 
252 // Otherwise, if `decltype(declval<I&>().operator->())` is well-formed, then `pointer` names that
253 // type.
254 template<class _Ip>
255   requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>)
256 struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> {
257   using type = decltype(declval<_Ip&>().operator->());
258 };
259 
260 // Otherwise, `reference` names `iter-reference-t<I>`.
261 template<class _Ip>
262 struct __iterator_traits_member_reference { using type = iter_reference_t<_Ip>; };
263 
264 // [iterator.traits]/3.2.2
265 // If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type.
266 template<__has_member_reference _Ip>
267 struct __iterator_traits_member_reference<_Ip> { using type = typename _Ip::reference; };
268 
269 // [iterator.traits]/3.2.3.4
270 // input_iterator_tag
271 template<class _Ip>
272 struct __deduce_iterator_category {
273   using type = input_iterator_tag;
274 };
275 
276 // [iterator.traits]/3.2.3.1
277 // `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise
278 template<__iterator_traits_detail::__cpp17_random_access_iterator _Ip>
279 struct __deduce_iterator_category<_Ip> {
280   using type = random_access_iterator_tag;
281 };
282 
283 // [iterator.traits]/3.2.3.2
284 // `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise
285 template<__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip>
286 struct __deduce_iterator_category<_Ip> {
287   using type = bidirectional_iterator_tag;
288 };
289 
290 // [iterator.traits]/3.2.3.3
291 // `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise
292 template<__iterator_traits_detail::__cpp17_forward_iterator _Ip>
293 struct __deduce_iterator_category<_Ip> {
294   using type = forward_iterator_tag;
295 };
296 
297 template<class _Ip>
298 struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {};
299 
300 // [iterator.traits]/3.2.3
301 // If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names
302 // that type.
303 template<__has_member_iterator_category _Ip>
304 struct __iterator_traits_iterator_category<_Ip> {
305   using type = typename _Ip::iterator_category;
306 };
307 
308 // otherwise, it names void.
309 template<class>
310 struct __iterator_traits_difference_type { using type = void; };
311 
312 // If the qualified-id `incrementable_traits<I>::difference_type` is valid and denotes a type, then
313 // `difference_type` names that type;
314 template<class _Ip>
315 requires requires { typename incrementable_traits<_Ip>::difference_type; }
316 struct __iterator_traits_difference_type<_Ip> {
317   using type = typename incrementable_traits<_Ip>::difference_type;
318 };
319 
320 // [iterator.traits]/3.4
321 // Otherwise, `iterator_traits<I>` has no members by any of the above names.
322 template<class>
323 struct __iterator_traits {};
324 
325 // [iterator.traits]/3.1
326 // If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and
327 // `iterator-category`, then `iterator-traits<I>` has the following publicly accessible members:
328 template<__specifies_members _Ip>
329 struct __iterator_traits<_Ip> {
330   using iterator_category  = typename _Ip::iterator_category;
331   using value_type         = typename _Ip::value_type;
332   using difference_type    = typename _Ip::difference_type;
333   using pointer            = typename __iterator_traits_member_pointer_or_void<_Ip>::type;
334   using reference          = typename _Ip::reference;
335 };
336 
337 // [iterator.traits]/3.2
338 // Otherwise, if `I` satisfies the exposition-only concept `cpp17-input-iterator`,
339 // `iterator-traits<I>` has the following publicly accessible members:
340 template<__cpp17_input_iterator_missing_members _Ip>
341 struct __iterator_traits<_Ip> {
342   using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type;
343   using value_type        = typename indirectly_readable_traits<_Ip>::value_type;
344   using difference_type   = typename incrementable_traits<_Ip>::difference_type;
345   using pointer           = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type;
346   using reference         = typename __iterator_traits_member_reference<_Ip>::type;
347 };
348 
349 // Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then
350 // `iterator_traits<I>` has the following publicly accessible members:
351 template<__cpp17_iterator_missing_members _Ip>
352 struct __iterator_traits<_Ip> {
353   using iterator_category = output_iterator_tag;
354   using value_type        = void;
355   using difference_type   = typename __iterator_traits_difference_type<_Ip>::type;
356   using pointer           = void;
357   using reference         = void;
358 };
359 
360 template<class _Ip>
361 struct iterator_traits : __iterator_traits<_Ip> {
362   using __primary_template = iterator_traits;
363 };
364 
365 #else // !defined(_LIBCPP_HAS_NO_CONCEPTS)
366 
367 template <class _Iter, bool> struct __iterator_traits {};
368 
369 template <class _Iter, bool> struct __iterator_traits_impl {};
370 
371 template <class _Iter>
372 struct __iterator_traits_impl<_Iter, true>
373 {
374     typedef typename _Iter::difference_type   difference_type;
375     typedef typename _Iter::value_type        value_type;
376     typedef typename _Iter::pointer           pointer;
377     typedef typename _Iter::reference         reference;
378     typedef typename _Iter::iterator_category iterator_category;
379 };
380 
381 template <class _Iter>
382 struct __iterator_traits<_Iter, true>
383     :  __iterator_traits_impl
384       <
385         _Iter,
386         is_convertible<typename _Iter::iterator_category, input_iterator_tag>::value ||
387         is_convertible<typename _Iter::iterator_category, output_iterator_tag>::value
388       >
389 {};
390 
391 // iterator_traits<Iterator> will only have the nested types if Iterator::iterator_category
392 //    exists.  Else iterator_traits<Iterator> will be an empty class.  This is a
393 //    conforming extension which allows some programs to compile and behave as
394 //    the client expects instead of failing at compile time.
395 
396 template <class _Iter>
397 struct _LIBCPP_TEMPLATE_VIS iterator_traits
398     : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {
399 
400   using __primary_template = iterator_traits;
401 };
402 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
403 
404 template<class _Tp>
405 #if !defined(_LIBCPP_HAS_NO_CONCEPTS)
406 requires is_object_v<_Tp>
407 #endif
408 struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*>
409 {
410     typedef ptrdiff_t difference_type;
411     typedef typename remove_cv<_Tp>::type value_type;
412     typedef _Tp* pointer;
413     typedef _Tp& reference;
414     typedef random_access_iterator_tag iterator_category;
415 #if _LIBCPP_STD_VER > 17
416     typedef contiguous_iterator_tag    iterator_concept;
417 #endif
418 };
419 
420 template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value>
421 struct __has_iterator_category_convertible_to
422     : is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>
423 {};
424 
425 template <class _Tp, class _Up>
426 struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {};
427 
428 template <class _Tp, class _Up, bool = __has_iterator_concept<_Tp>::value>
429 struct __has_iterator_concept_convertible_to
430     : is_convertible<typename _Tp::iterator_concept, _Up>
431 {};
432 
433 template <class _Tp, class _Up>
434 struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {};
435 
436 template <class _Tp>
437 struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {};
438 
439 template <class _Tp>
440 struct __is_cpp17_forward_iterator : public __has_iterator_category_convertible_to<_Tp, forward_iterator_tag> {};
441 
442 template <class _Tp>
443 struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag> {};
444 
445 template <class _Tp>
446 struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {};
447 
448 // __is_cpp17_contiguous_iterator determines if an iterator is known by
449 // libc++ to be contiguous, either because it advertises itself as such
450 // (in C++20) or because it is a pointer type or a known trivial wrapper
451 // around a (possibly fancy) pointer type, such as __wrap_iter<T*>.
452 // Such iterators receive special "contiguous" optimizations in
453 // std::copy and std::sort.
454 //
455 #if _LIBCPP_STD_VER > 17
456 template <class _Tp>
457 struct __is_cpp17_contiguous_iterator : _Or<
458     __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>,
459     __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag>
460 > {};
461 #else
462 template <class _Tp>
463 struct __is_cpp17_contiguous_iterator : false_type {};
464 #endif
465 
466 // Any native pointer which is an iterator is also a contiguous iterator.
467 template <class _Up>
468 struct __is_cpp17_contiguous_iterator<_Up*> : true_type {};
469 
470 
471 template <class _Tp>
472 struct __is_exactly_cpp17_input_iterator
473     : public integral_constant<bool,
474          __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value &&
475         !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {};
476 
477 #if _LIBCPP_STD_VER >= 17
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 = remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_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     add_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>,
490     typename iterator_traits<_InputIterator>::value_type::second_type>;
491 #endif // _LIBCPP_STD_VER >= 17
492 
493 _LIBCPP_END_NAMESPACE_STD
494 
495 #endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
496