2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
11 #define _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
13 #include <__concepts/arithmetic.h>
14 #include <__concepts/constructible.h>
15 #include <__concepts/convertible_to.h>
16 #include <__concepts/copyable.h>
17 #include <__concepts/equality_comparable.h>
18 #include <__concepts/same_as.h>
19 #include <__concepts/totally_ordered.h>
21 #include <__fwd/pair.h>
22 #include <__iterator/incrementable_traits.h>
23 #include <__iterator/readable_traits.h>
24 #include <__type_traits/add_const.h>
25 #include <__type_traits/common_reference.h>
26 #include <__type_traits/conditional.h>
27 #include <__type_traits/disjunction.h>
28 #include <__type_traits/is_convertible.h>
29 #include <__type_traits/is_object.h>
30 #include <__type_traits/is_primary_template.h>
31 #include <__type_traits/is_reference.h>
32 #include <__type_traits/is_valid_expansion.h>
33 #include <__type_traits/remove_const.h>
34 #include <__type_traits/remove_cv.h>
35 #include <__type_traits/remove_cvref.h>
36 #include <__type_traits/void_t.h>
37 #include <__utility/declval.h>
40 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
41 # pragma GCC system_header
44 _LIBCPP_BEGIN_NAMESPACE_STD
46 #if _LIBCPP_STD_VER >= 20
49 using __with_reference
= _Tp
&;
52 concept __can_reference
= requires
{
53 typename __with_reference
<_Tp
>;
57 concept __dereferenceable
= requires(_Tp
& __t
) {
58 { *__t
} -> __can_reference
; // not required to be equality-preserving
62 template<__dereferenceable _Tp
>
63 using iter_reference_t
= decltype(*std::declval
<_Tp
&>());
65 #endif // _LIBCPP_STD_VER >= 20
67 template <class _Iter
>
68 struct _LIBCPP_TEMPLATE_VIS iterator_traits
;
70 struct _LIBCPP_TEMPLATE_VIS input_iterator_tag
{};
71 struct _LIBCPP_TEMPLATE_VIS output_iterator_tag
{};
72 struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag
: public input_iterator_tag
{};
73 struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag
: public forward_iterator_tag
{};
74 struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag
: public bidirectional_iterator_tag
{};
75 #if _LIBCPP_STD_VER >= 20
76 struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag
: public random_access_iterator_tag
{};
79 template <class _Iter
>
80 struct __iter_traits_cache
{
82 __is_primary_template
<iterator_traits
<_Iter
> >::value
,
84 iterator_traits
<_Iter
>
87 template <class _Iter
>
88 using _ITER_TRAITS
= typename __iter_traits_cache
<_Iter
>::type
;
90 struct __iter_concept_concept_test
{
91 template <class _Iter
>
92 using _Apply
= typename _ITER_TRAITS
<_Iter
>::iterator_concept
;
94 struct __iter_concept_category_test
{
95 template <class _Iter
>
96 using _Apply
= typename _ITER_TRAITS
<_Iter
>::iterator_category
;
98 struct __iter_concept_random_fallback
{
99 template <class _Iter
>
100 using _Apply
= __enable_if_t
<
101 __is_primary_template
<iterator_traits
<_Iter
> >::value
,
102 random_access_iterator_tag
106 template <class _Iter
, class _Tester
> struct __test_iter_concept
107 : _IsValidExpansion
<_Tester::template _Apply
, _Iter
>,
112 template <class _Iter
>
113 struct __iter_concept_cache
{
115 __test_iter_concept
<_Iter
, __iter_concept_concept_test
>,
116 __test_iter_concept
<_Iter
, __iter_concept_category_test
>,
117 __test_iter_concept
<_Iter
, __iter_concept_random_fallback
>
121 template <class _Iter
>
122 using _ITER_CONCEPT
= typename __iter_concept_cache
<_Iter
>::type::template _Apply
<_Iter
>;
126 struct __has_iterator_typedefs
129 template <class _Up
> static false_type
__test(...);
130 template <class _Up
> static true_type
__test(__void_t
<typename
_Up::iterator_category
>* = nullptr,
131 __void_t
<typename
_Up::difference_type
>* = nullptr,
132 __void_t
<typename
_Up::value_type
>* = nullptr,
133 __void_t
<typename
_Up::reference
>* = nullptr,
134 __void_t
<typename
_Up::pointer
>* = nullptr);
136 static const bool value
= decltype(__test
<_Tp
>(0,0,0,0,0))::value
;
141 struct __has_iterator_category
144 template <class _Up
> static false_type
__test(...);
145 template <class _Up
> static true_type
__test(typename
_Up::iterator_category
* = nullptr);
147 static const bool value
= decltype(__test
<_Tp
>(nullptr))::value
;
151 struct __has_iterator_concept
154 template <class _Up
> static false_type
__test(...);
155 template <class _Up
> static true_type
__test(typename
_Up::iterator_concept
* = nullptr);
157 static const bool value
= decltype(__test
<_Tp
>(nullptr))::value
;
160 #if _LIBCPP_STD_VER >= 20
162 // The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements
163 // from `[iterator.cpp17]`. To avoid confusion between the two, the exposition-only concepts have been banished to
164 // a "detail" namespace indicating they have a niche use-case.
165 namespace __iterator_traits_detail
{
167 concept __cpp17_iterator
=
169 { *__i
} -> __can_reference
;
170 { ++__i
} -> same_as
<_Ip
&>;
171 { *__i
++ } -> __can_reference
;
176 concept __cpp17_input_iterator
=
177 __cpp17_iterator
<_Ip
> &&
178 equality_comparable
<_Ip
> &&
180 typename incrementable_traits
<_Ip
>::difference_type
;
181 typename indirectly_readable_traits
<_Ip
>::value_type
;
182 typename common_reference_t
<iter_reference_t
<_Ip
>&&,
183 typename indirectly_readable_traits
<_Ip
>::value_type
&>;
184 typename common_reference_t
<decltype(*__i
++)&&,
185 typename indirectly_readable_traits
<_Ip
>::value_type
&>;
186 requires signed_integral
<typename incrementable_traits
<_Ip
>::difference_type
>;
190 concept __cpp17_forward_iterator
=
191 __cpp17_input_iterator
<_Ip
> &&
192 constructible_from
<_Ip
> &&
193 is_reference_v
<iter_reference_t
<_Ip
>> &&
194 same_as
<remove_cvref_t
<iter_reference_t
<_Ip
>>,
195 typename indirectly_readable_traits
<_Ip
>::value_type
> &&
197 { __i
++ } -> convertible_to
<_Ip
const&>;
198 { *__i
++ } -> same_as
<iter_reference_t
<_Ip
>>;
202 concept __cpp17_bidirectional_iterator
=
203 __cpp17_forward_iterator
<_Ip
> &&
205 { --__i
} -> same_as
<_Ip
&>;
206 { __i
-- } -> convertible_to
<_Ip
const&>;
207 { *__i
-- } -> same_as
<iter_reference_t
<_Ip
>>;
211 concept __cpp17_random_access_iterator
=
212 __cpp17_bidirectional_iterator
<_Ip
> &&
213 totally_ordered
<_Ip
> &&
214 requires(_Ip __i
, typename incrementable_traits
<_Ip
>::difference_type __n
) {
215 { __i
+= __n
} -> same_as
<_Ip
&>;
216 { __i
-= __n
} -> same_as
<_Ip
&>;
217 { __i
+ __n
} -> same_as
<_Ip
>;
218 { __n
+ __i
} -> same_as
<_Ip
>;
219 { __i
- __n
} -> same_as
<_Ip
>;
220 { __i
- __i
} -> same_as
<decltype(__n
)>; // NOLINT(misc-redundant-expression) ; This is llvm.org/PR54114
221 { __i
[__n
] } -> convertible_to
<iter_reference_t
<_Ip
>>;
223 } // namespace __iterator_traits_detail
226 concept __has_member_reference
= requires
{ typename
_Ip::reference
; };
229 concept __has_member_pointer
= requires
{ typename
_Ip::pointer
; };
232 concept __has_member_iterator_category
= requires
{ typename
_Ip::iterator_category
; };
235 concept __specifies_members
= requires
{
236 typename
_Ip::value_type
;
237 typename
_Ip::difference_type
;
238 requires __has_member_reference
<_Ip
>;
239 requires __has_member_iterator_category
<_Ip
>;
243 struct __iterator_traits_member_pointer_or_void
{
247 template<__has_member_pointer _Tp
>
248 struct __iterator_traits_member_pointer_or_void
<_Tp
> {
249 using type
= typename
_Tp::pointer
;
253 concept __cpp17_iterator_missing_members
=
254 !__specifies_members
<_Tp
> &&
255 __iterator_traits_detail::__cpp17_iterator
<_Tp
>;
258 concept __cpp17_input_iterator_missing_members
=
259 __cpp17_iterator_missing_members
<_Tp
> &&
260 __iterator_traits_detail::__cpp17_input_iterator
<_Tp
>;
262 // Otherwise, `pointer` names `void`.
264 struct __iterator_traits_member_pointer_or_arrow_or_void
{ using type
= void; };
266 // [iterator.traits]/3.2.1
267 // If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type.
268 template<__has_member_pointer _Ip
>
269 struct __iterator_traits_member_pointer_or_arrow_or_void
<_Ip
> { using type
= typename
_Ip::pointer
; };
271 // Otherwise, if `decltype(declval<I&>().operator->())` is well-formed, then `pointer` names that
274 requires
requires(_Ip
& __i
) { __i
.operator->(); } && (!__has_member_pointer
<_Ip
>)
275 struct __iterator_traits_member_pointer_or_arrow_or_void
<_Ip
> {
276 using type
= decltype(std::declval
<_Ip
&>().operator->());
279 // Otherwise, `reference` names `iter-reference-t<I>`.
281 struct __iterator_traits_member_reference
{ using type
= iter_reference_t
<_Ip
>; };
283 // [iterator.traits]/3.2.2
284 // If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type.
285 template<__has_member_reference _Ip
>
286 struct __iterator_traits_member_reference
<_Ip
> { using type
= typename
_Ip::reference
; };
288 // [iterator.traits]/3.2.3.4
289 // input_iterator_tag
291 struct __deduce_iterator_category
{
292 using type
= input_iterator_tag
;
295 // [iterator.traits]/3.2.3.1
296 // `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise
297 template<__iterator_traits_detail::__cpp17_random_access_iterator _Ip
>
298 struct __deduce_iterator_category
<_Ip
> {
299 using type
= random_access_iterator_tag
;
302 // [iterator.traits]/3.2.3.2
303 // `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise
304 template<__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip
>
305 struct __deduce_iterator_category
<_Ip
> {
306 using type
= bidirectional_iterator_tag
;
309 // [iterator.traits]/3.2.3.3
310 // `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise
311 template<__iterator_traits_detail::__cpp17_forward_iterator _Ip
>
312 struct __deduce_iterator_category
<_Ip
> {
313 using type
= forward_iterator_tag
;
317 struct __iterator_traits_iterator_category
: __deduce_iterator_category
<_Ip
> {};
319 // [iterator.traits]/3.2.3
320 // If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names
322 template<__has_member_iterator_category _Ip
>
323 struct __iterator_traits_iterator_category
<_Ip
> {
324 using type
= typename
_Ip::iterator_category
;
327 // otherwise, it names void.
329 struct __iterator_traits_difference_type
{ using type
= void; };
331 // If the qualified-id `incrementable_traits<I>::difference_type` is valid and denotes a type, then
332 // `difference_type` names that type;
334 requires requires
{ typename incrementable_traits
<_Ip
>::difference_type
; }
335 struct __iterator_traits_difference_type
<_Ip
> {
336 using type
= typename incrementable_traits
<_Ip
>::difference_type
;
339 // [iterator.traits]/3.4
340 // Otherwise, `iterator_traits<I>` has no members by any of the above names.
342 struct __iterator_traits
{};
344 // [iterator.traits]/3.1
345 // If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and
346 // `iterator-category`, then `iterator-traits<I>` has the following publicly accessible members:
347 template<__specifies_members _Ip
>
348 struct __iterator_traits
<_Ip
> {
349 using iterator_category
= typename
_Ip::iterator_category
;
350 using value_type
= typename
_Ip::value_type
;
351 using difference_type
= typename
_Ip::difference_type
;
352 using pointer
= typename __iterator_traits_member_pointer_or_void
<_Ip
>::type
;
353 using reference
= typename
_Ip::reference
;
356 // [iterator.traits]/3.2
357 // Otherwise, if `I` satisfies the exposition-only concept `cpp17-input-iterator`,
358 // `iterator-traits<I>` has the following publicly accessible members:
359 template<__cpp17_input_iterator_missing_members _Ip
>
360 struct __iterator_traits
<_Ip
> {
361 using iterator_category
= typename __iterator_traits_iterator_category
<_Ip
>::type
;
362 using value_type
= typename indirectly_readable_traits
<_Ip
>::value_type
;
363 using difference_type
= typename incrementable_traits
<_Ip
>::difference_type
;
364 using pointer
= typename __iterator_traits_member_pointer_or_arrow_or_void
<_Ip
>::type
;
365 using reference
= typename __iterator_traits_member_reference
<_Ip
>::type
;
368 // Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then
369 // `iterator_traits<I>` has the following publicly accessible members:
370 template<__cpp17_iterator_missing_members _Ip
>
371 struct __iterator_traits
<_Ip
> {
372 using iterator_category
= output_iterator_tag
;
373 using value_type
= void;
374 using difference_type
= typename __iterator_traits_difference_type
<_Ip
>::type
;
375 using pointer
= void;
376 using reference
= void;
380 struct iterator_traits
: __iterator_traits
<_Ip
> {
381 using __primary_template
= iterator_traits
;
384 #else // _LIBCPP_STD_VER >= 20
386 template <class _Iter
, bool> struct __iterator_traits
{};
388 template <class _Iter
, bool> struct __iterator_traits_impl
{};
390 template <class _Iter
>
391 struct __iterator_traits_impl
<_Iter
, true>
393 typedef typename
_Iter::difference_type difference_type
;
394 typedef typename
_Iter::value_type value_type
;
395 typedef typename
_Iter::pointer pointer
;
396 typedef typename
_Iter::reference reference
;
397 typedef typename
_Iter::iterator_category iterator_category
;
400 template <class _Iter
>
401 struct __iterator_traits
<_Iter
, true>
402 : __iterator_traits_impl
405 is_convertible
<typename
_Iter::iterator_category
, input_iterator_tag
>::value
||
406 is_convertible
<typename
_Iter::iterator_category
, output_iterator_tag
>::value
410 // iterator_traits<Iterator> will only have the nested types if Iterator::iterator_category
411 // exists. Else iterator_traits<Iterator> will be an empty class. This is a
412 // conforming extension which allows some programs to compile and behave as
413 // the client expects instead of failing at compile time.
415 template <class _Iter
>
416 struct _LIBCPP_TEMPLATE_VIS iterator_traits
417 : __iterator_traits
<_Iter
, __has_iterator_typedefs
<_Iter
>::value
> {
419 using __primary_template
= iterator_traits
;
421 #endif // _LIBCPP_STD_VER >= 20
424 #if _LIBCPP_STD_VER >= 20
425 requires is_object_v
<_Tp
>
427 struct _LIBCPP_TEMPLATE_VIS iterator_traits
<_Tp
*>
429 typedef ptrdiff_t difference_type
;
430 typedef __remove_cv_t
<_Tp
> value_type
;
431 typedef _Tp
* pointer
;
432 typedef _Tp
& reference
;
433 typedef random_access_iterator_tag iterator_category
;
434 #if _LIBCPP_STD_VER >= 20
435 typedef contiguous_iterator_tag iterator_concept
;
439 template <class _Tp
, class _Up
, bool = __has_iterator_category
<iterator_traits
<_Tp
> >::value
>
440 struct __has_iterator_category_convertible_to
441 : is_convertible
<typename iterator_traits
<_Tp
>::iterator_category
, _Up
>
444 template <class _Tp
, class _Up
>
445 struct __has_iterator_category_convertible_to
<_Tp
, _Up
, false> : false_type
{};
447 template <class _Tp
, class _Up
, bool = __has_iterator_concept
<_Tp
>::value
>
448 struct __has_iterator_concept_convertible_to
449 : is_convertible
<typename
_Tp::iterator_concept
, _Up
>
452 template <class _Tp
, class _Up
>
453 struct __has_iterator_concept_convertible_to
<_Tp
, _Up
, false> : false_type
{};
456 using __has_input_iterator_category
= __has_iterator_category_convertible_to
<_Tp
, input_iterator_tag
>;
459 using __has_forward_iterator_category
= __has_iterator_category_convertible_to
<_Tp
, forward_iterator_tag
>;
462 using __has_bidirectional_iterator_category
= __has_iterator_category_convertible_to
<_Tp
, bidirectional_iterator_tag
>;
465 using __has_random_access_iterator_category
= __has_iterator_category_convertible_to
<_Tp
, random_access_iterator_tag
>;
467 // __libcpp_is_contiguous_iterator determines if an iterator is known by
468 // libc++ to be contiguous, either because it advertises itself as such
469 // (in C++20) or because it is a pointer type or a known trivial wrapper
470 // around a (possibly fancy) pointer type, such as __wrap_iter<T*>.
471 // Such iterators receive special "contiguous" optimizations in
472 // std::copy and std::sort.
474 #if _LIBCPP_STD_VER >= 20
476 struct __libcpp_is_contiguous_iterator
: _Or
<
477 __has_iterator_category_convertible_to
<_Tp
, contiguous_iterator_tag
>,
478 __has_iterator_concept_convertible_to
<_Tp
, contiguous_iterator_tag
>
482 struct __libcpp_is_contiguous_iterator
: false_type
{};
485 // Any native pointer which is an iterator is also a contiguous iterator.
487 struct __libcpp_is_contiguous_iterator
<_Up
*> : true_type
{};
490 template <class _Iter
>
494 using __has_exactly_input_iterator_category
495 = integral_constant
<bool,
496 __has_iterator_category_convertible_to
<_Tp
, input_iterator_tag
>::value
&&
497 !__has_iterator_category_convertible_to
<_Tp
, forward_iterator_tag
>::value
>;
500 using __has_exactly_forward_iterator_category
501 = integral_constant
<bool,
502 __has_iterator_category_convertible_to
<_Tp
, forward_iterator_tag
>::value
&&
503 !__has_iterator_category_convertible_to
<_Tp
, bidirectional_iterator_tag
>::value
>;
506 using __has_exactly_bidirectional_iterator_category
507 = integral_constant
<bool,
508 __has_iterator_category_convertible_to
<_Tp
, bidirectional_iterator_tag
>::value
&&
509 !__has_iterator_category_convertible_to
<_Tp
, random_access_iterator_tag
>::value
>;
511 template<class _InputIterator
>
512 using __iter_value_type
= typename iterator_traits
<_InputIterator
>::value_type
;
514 template<class _InputIterator
>
515 using __iter_key_type
= __remove_const_t
<typename iterator_traits
<_InputIterator
>::value_type::first_type
>;
517 template<class _InputIterator
>
518 using __iter_mapped_type
= typename iterator_traits
<_InputIterator
>::value_type::second_type
;
520 template<class _InputIterator
>
521 using __iter_to_alloc_type
= pair
<
522 typename add_const
<typename iterator_traits
<_InputIterator
>::value_type::first_type
>::type
,
523 typename iterator_traits
<_InputIterator
>::value_type::second_type
>;
525 template <class _Iter
>
526 using __iterator_category_type
= typename iterator_traits
<_Iter
>::iterator_category
;
528 template <class _Iter
>
529 using __iterator_pointer_type
= typename iterator_traits
<_Iter
>::pointer
;
531 template <class _Iter
>
532 using __iter_diff_t
= typename iterator_traits
<_Iter
>::difference_type
;
534 template <class _Iter
>
535 using __iter_reference
= typename iterator_traits
<_Iter
>::reference
;
537 #if _LIBCPP_STD_VER >= 20
541 // Let `RI` be `remove_cvref_t<I>`. The type `iter_value_t<I>` denotes
542 // `indirectly_readable_traits<RI>::value_type` if `iterator_traits<RI>` names a specialization
543 // generated from the primary template, and `iterator_traits<RI>::value_type` otherwise.
544 // This has to be in this file and not readable_traits.h to break the include cycle between the two.
546 using iter_value_t
= typename conditional_t
<__is_primary_template
<iterator_traits
<remove_cvref_t
<_Ip
> > >::value
,
547 indirectly_readable_traits
<remove_cvref_t
<_Ip
> >,
548 iterator_traits
<remove_cvref_t
<_Ip
> > >::value_type
;
550 #endif // _LIBCPP_STD_VER >= 20
552 _LIBCPP_END_NAMESPACE_STD
554 #endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H