xref: /openbsd-src/gnu/llvm/libcxx/include/__iterator/iterator_traits.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
176d0caaeSpatrick // -*- C++ -*-
276d0caaeSpatrick //===----------------------------------------------------------------------===//
376d0caaeSpatrick //
476d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
576d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information.
676d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
776d0caaeSpatrick //
876d0caaeSpatrick //===----------------------------------------------------------------------===//
976d0caaeSpatrick 
1076d0caaeSpatrick #ifndef _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
1176d0caaeSpatrick #define _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
1276d0caaeSpatrick 
13*4bdff4beSrobert #include <__concepts/arithmetic.h>
14*4bdff4beSrobert #include <__concepts/constructible.h>
15*4bdff4beSrobert #include <__concepts/convertible_to.h>
16*4bdff4beSrobert #include <__concepts/copyable.h>
17*4bdff4beSrobert #include <__concepts/equality_comparable.h>
18*4bdff4beSrobert #include <__concepts/same_as.h>
19*4bdff4beSrobert #include <__concepts/totally_ordered.h>
2076d0caaeSpatrick #include <__config>
21*4bdff4beSrobert #include <__fwd/pair.h>
2276d0caaeSpatrick #include <__iterator/incrementable_traits.h>
2376d0caaeSpatrick #include <__iterator/readable_traits.h>
24*4bdff4beSrobert #include <__type_traits/add_const.h>
25*4bdff4beSrobert #include <__type_traits/common_reference.h>
26*4bdff4beSrobert #include <__type_traits/conditional.h>
27*4bdff4beSrobert #include <__type_traits/disjunction.h>
28*4bdff4beSrobert #include <__type_traits/is_convertible.h>
29*4bdff4beSrobert #include <__type_traits/is_object.h>
30*4bdff4beSrobert #include <__type_traits/is_primary_template.h>
31*4bdff4beSrobert #include <__type_traits/is_reference.h>
32*4bdff4beSrobert #include <__type_traits/is_valid_expansion.h>
33*4bdff4beSrobert #include <__type_traits/remove_const.h>
34*4bdff4beSrobert #include <__type_traits/remove_cv.h>
35*4bdff4beSrobert #include <__type_traits/remove_cvref.h>
36*4bdff4beSrobert #include <__type_traits/void_t.h>
37*4bdff4beSrobert #include <__utility/declval.h>
38*4bdff4beSrobert #include <cstddef>
3976d0caaeSpatrick 
4076d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
4176d0caaeSpatrick #  pragma GCC system_header
4276d0caaeSpatrick #endif
4376d0caaeSpatrick 
4476d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD
4576d0caaeSpatrick 
46*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
4776d0caaeSpatrick 
4876d0caaeSpatrick template <class _Tp>
4976d0caaeSpatrick using __with_reference = _Tp&;
5076d0caaeSpatrick 
5176d0caaeSpatrick template <class _Tp>
52*4bdff4beSrobert concept __can_reference = requires {
5376d0caaeSpatrick   typename __with_reference<_Tp>;
5476d0caaeSpatrick };
5576d0caaeSpatrick 
5676d0caaeSpatrick template <class _Tp>
requires(_Tp & __t)5776d0caaeSpatrick concept __dereferenceable = requires(_Tp& __t) {
58*4bdff4beSrobert   { *__t } -> __can_reference; // not required to be equality-preserving
5976d0caaeSpatrick };
6076d0caaeSpatrick 
6176d0caaeSpatrick // [iterator.traits]
6276d0caaeSpatrick template<__dereferenceable _Tp>
63*4bdff4beSrobert using iter_reference_t = decltype(*std::declval<_Tp&>());
6476d0caaeSpatrick 
65*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
6676d0caaeSpatrick 
6776d0caaeSpatrick template <class _Iter>
6876d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS iterator_traits;
6976d0caaeSpatrick 
7076d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS input_iterator_tag {};
7176d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {};
7276d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag       : public input_iterator_tag {};
7376d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {};
7476d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {};
7576d0caaeSpatrick #if _LIBCPP_STD_VER > 17
7676d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag    : public random_access_iterator_tag {};
7776d0caaeSpatrick #endif
7876d0caaeSpatrick 
7976d0caaeSpatrick template <class _Iter>
8076d0caaeSpatrick struct __iter_traits_cache {
8176d0caaeSpatrick   using type = _If<
8276d0caaeSpatrick     __is_primary_template<iterator_traits<_Iter> >::value,
8376d0caaeSpatrick     _Iter,
8476d0caaeSpatrick     iterator_traits<_Iter>
8576d0caaeSpatrick   >;
8676d0caaeSpatrick };
8776d0caaeSpatrick template <class _Iter>
8876d0caaeSpatrick using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type;
8976d0caaeSpatrick 
9076d0caaeSpatrick struct __iter_concept_concept_test {
9176d0caaeSpatrick   template <class _Iter>
9276d0caaeSpatrick   using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept;
9376d0caaeSpatrick };
9476d0caaeSpatrick struct __iter_concept_category_test {
9576d0caaeSpatrick   template <class _Iter>
9676d0caaeSpatrick   using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category;
9776d0caaeSpatrick };
9876d0caaeSpatrick struct __iter_concept_random_fallback {
9976d0caaeSpatrick   template <class _Iter>
100*4bdff4beSrobert   using _Apply = __enable_if_t<
10176d0caaeSpatrick                           __is_primary_template<iterator_traits<_Iter> >::value,
10276d0caaeSpatrick                           random_access_iterator_tag
10376d0caaeSpatrick                         >;
10476d0caaeSpatrick };
10576d0caaeSpatrick 
10676d0caaeSpatrick template <class _Iter, class _Tester> struct __test_iter_concept
10776d0caaeSpatrick     : _IsValidExpansion<_Tester::template _Apply, _Iter>,
10876d0caaeSpatrick       _Tester
10976d0caaeSpatrick {
11076d0caaeSpatrick };
11176d0caaeSpatrick 
11276d0caaeSpatrick template <class _Iter>
11376d0caaeSpatrick struct __iter_concept_cache {
11476d0caaeSpatrick   using type = _Or<
11576d0caaeSpatrick     __test_iter_concept<_Iter, __iter_concept_concept_test>,
11676d0caaeSpatrick     __test_iter_concept<_Iter, __iter_concept_category_test>,
11776d0caaeSpatrick     __test_iter_concept<_Iter, __iter_concept_random_fallback>
11876d0caaeSpatrick   >;
11976d0caaeSpatrick };
12076d0caaeSpatrick 
12176d0caaeSpatrick template <class _Iter>
12276d0caaeSpatrick using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>;
12376d0caaeSpatrick 
12476d0caaeSpatrick 
12576d0caaeSpatrick template <class _Tp>
12676d0caaeSpatrick struct __has_iterator_typedefs
12776d0caaeSpatrick {
12876d0caaeSpatrick private:
129*4bdff4beSrobert     template <class _Up> static false_type __test(...);
130*4bdff4beSrobert     template <class _Up> static true_type __test(__void_t<typename _Up::iterator_category>* = nullptr,
131*4bdff4beSrobert                                                  __void_t<typename _Up::difference_type>* = nullptr,
132*4bdff4beSrobert                                                  __void_t<typename _Up::value_type>* = nullptr,
133*4bdff4beSrobert                                                  __void_t<typename _Up::reference>* = nullptr,
134*4bdff4beSrobert                                                  __void_t<typename _Up::pointer>* = nullptr);
13576d0caaeSpatrick public:
136*4bdff4beSrobert     static const bool value = decltype(__test<_Tp>(0,0,0,0,0))::value;
13776d0caaeSpatrick };
13876d0caaeSpatrick 
13976d0caaeSpatrick 
14076d0caaeSpatrick template <class _Tp>
14176d0caaeSpatrick struct __has_iterator_category
14276d0caaeSpatrick {
14376d0caaeSpatrick private:
144*4bdff4beSrobert     template <class _Up> static false_type __test(...);
145*4bdff4beSrobert     template <class _Up> static true_type __test(typename _Up::iterator_category* = nullptr);
14676d0caaeSpatrick public:
147*4bdff4beSrobert     static const bool value = decltype(__test<_Tp>(nullptr))::value;
14876d0caaeSpatrick };
14976d0caaeSpatrick 
15076d0caaeSpatrick template <class _Tp>
15176d0caaeSpatrick struct __has_iterator_concept
15276d0caaeSpatrick {
15376d0caaeSpatrick private:
154*4bdff4beSrobert     template <class _Up> static false_type __test(...);
155*4bdff4beSrobert     template <class _Up> static true_type __test(typename _Up::iterator_concept* = nullptr);
15676d0caaeSpatrick public:
157*4bdff4beSrobert     static const bool value = decltype(__test<_Tp>(nullptr))::value;
15876d0caaeSpatrick };
15976d0caaeSpatrick 
160*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
16176d0caaeSpatrick 
162*4bdff4beSrobert // The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements
163*4bdff4beSrobert // from `[iterator.cpp17]`. To avoid confusion between the two, the exposition-only concepts have been banished to
164*4bdff4beSrobert // a "detail" namespace indicating they have a niche use-case.
16576d0caaeSpatrick namespace __iterator_traits_detail {
16676d0caaeSpatrick template<class _Ip>
16776d0caaeSpatrick concept __cpp17_iterator =
requires(_Ip __i)16876d0caaeSpatrick   requires(_Ip __i) {
169*4bdff4beSrobert     {   *__i } -> __can_reference;
17076d0caaeSpatrick     {  ++__i } -> same_as<_Ip&>;
171*4bdff4beSrobert     { *__i++ } -> __can_reference;
17276d0caaeSpatrick   } &&
17376d0caaeSpatrick   copyable<_Ip>;
17476d0caaeSpatrick 
17576d0caaeSpatrick template<class _Ip>
17676d0caaeSpatrick concept __cpp17_input_iterator =
17776d0caaeSpatrick   __cpp17_iterator<_Ip> &&
17876d0caaeSpatrick   equality_comparable<_Ip> &&
requires(_Ip __i)17976d0caaeSpatrick   requires(_Ip __i) {
18076d0caaeSpatrick     typename incrementable_traits<_Ip>::difference_type;
18176d0caaeSpatrick     typename indirectly_readable_traits<_Ip>::value_type;
18276d0caaeSpatrick     typename common_reference_t<iter_reference_t<_Ip>&&,
18376d0caaeSpatrick                                 typename indirectly_readable_traits<_Ip>::value_type&>;
18476d0caaeSpatrick     typename common_reference_t<decltype(*__i++)&&,
18576d0caaeSpatrick                                 typename indirectly_readable_traits<_Ip>::value_type&>;
18676d0caaeSpatrick     requires signed_integral<typename incrementable_traits<_Ip>::difference_type>;
18776d0caaeSpatrick   };
18876d0caaeSpatrick 
18976d0caaeSpatrick template<class _Ip>
19076d0caaeSpatrick concept __cpp17_forward_iterator =
19176d0caaeSpatrick   __cpp17_input_iterator<_Ip> &&
19276d0caaeSpatrick   constructible_from<_Ip> &&
19376d0caaeSpatrick   is_lvalue_reference_v<iter_reference_t<_Ip>> &&
19476d0caaeSpatrick   same_as<remove_cvref_t<iter_reference_t<_Ip>>,
19576d0caaeSpatrick           typename indirectly_readable_traits<_Ip>::value_type> &&
requires(_Ip __i)19676d0caaeSpatrick   requires(_Ip __i) {
19776d0caaeSpatrick     {  __i++ } -> convertible_to<_Ip const&>;
19876d0caaeSpatrick     { *__i++ } -> same_as<iter_reference_t<_Ip>>;
19976d0caaeSpatrick   };
20076d0caaeSpatrick 
20176d0caaeSpatrick template<class _Ip>
20276d0caaeSpatrick concept __cpp17_bidirectional_iterator =
20376d0caaeSpatrick   __cpp17_forward_iterator<_Ip> &&
requires(_Ip __i)20476d0caaeSpatrick   requires(_Ip __i) {
20576d0caaeSpatrick     {  --__i } -> same_as<_Ip&>;
20676d0caaeSpatrick     {  __i-- } -> convertible_to<_Ip const&>;
20776d0caaeSpatrick     { *__i-- } -> same_as<iter_reference_t<_Ip>>;
20876d0caaeSpatrick   };
20976d0caaeSpatrick 
21076d0caaeSpatrick template<class _Ip>
21176d0caaeSpatrick concept __cpp17_random_access_iterator =
21276d0caaeSpatrick   __cpp17_bidirectional_iterator<_Ip> &&
21376d0caaeSpatrick   totally_ordered<_Ip> &&
requires(_Ip __i,typename incrementable_traits<_Ip>::difference_type __n)21476d0caaeSpatrick   requires(_Ip __i, typename incrementable_traits<_Ip>::difference_type __n) {
21576d0caaeSpatrick     { __i += __n } -> same_as<_Ip&>;
21676d0caaeSpatrick     { __i -= __n } -> same_as<_Ip&>;
21776d0caaeSpatrick     { __i +  __n } -> same_as<_Ip>;
21876d0caaeSpatrick     { __n +  __i } -> same_as<_Ip>;
21976d0caaeSpatrick     { __i -  __n } -> same_as<_Ip>;
220*4bdff4beSrobert     { __i -  __i } -> same_as<decltype(__n)>; // NOLINT(misc-redundant-expression) ; This is llvm.org/PR54114
22176d0caaeSpatrick     {  __i[__n]  } -> convertible_to<iter_reference_t<_Ip>>;
22276d0caaeSpatrick   };
22376d0caaeSpatrick } // namespace __iterator_traits_detail
22476d0caaeSpatrick 
22576d0caaeSpatrick template<class _Ip>
22676d0caaeSpatrick concept __has_member_reference = requires { typename _Ip::reference; };
22776d0caaeSpatrick 
22876d0caaeSpatrick template<class _Ip>
22976d0caaeSpatrick concept __has_member_pointer = requires { typename _Ip::pointer; };
23076d0caaeSpatrick 
23176d0caaeSpatrick template<class _Ip>
23276d0caaeSpatrick concept __has_member_iterator_category = requires { typename _Ip::iterator_category; };
23376d0caaeSpatrick 
23476d0caaeSpatrick template<class _Ip>
23576d0caaeSpatrick concept __specifies_members = requires {
23676d0caaeSpatrick     typename _Ip::value_type;
23776d0caaeSpatrick     typename _Ip::difference_type;
23876d0caaeSpatrick     requires __has_member_reference<_Ip>;
23976d0caaeSpatrick     requires __has_member_iterator_category<_Ip>;
24076d0caaeSpatrick   };
24176d0caaeSpatrick 
24276d0caaeSpatrick template<class>
24376d0caaeSpatrick struct __iterator_traits_member_pointer_or_void {
24476d0caaeSpatrick   using type = void;
24576d0caaeSpatrick };
24676d0caaeSpatrick 
24776d0caaeSpatrick template<__has_member_pointer _Tp>
24876d0caaeSpatrick struct __iterator_traits_member_pointer_or_void<_Tp> {
24976d0caaeSpatrick   using type = typename _Tp::pointer;
25076d0caaeSpatrick };
25176d0caaeSpatrick 
25276d0caaeSpatrick template<class _Tp>
25376d0caaeSpatrick concept __cpp17_iterator_missing_members =
25476d0caaeSpatrick   !__specifies_members<_Tp> &&
25576d0caaeSpatrick   __iterator_traits_detail::__cpp17_iterator<_Tp>;
25676d0caaeSpatrick 
25776d0caaeSpatrick template<class _Tp>
25876d0caaeSpatrick concept __cpp17_input_iterator_missing_members =
25976d0caaeSpatrick   __cpp17_iterator_missing_members<_Tp> &&
26076d0caaeSpatrick   __iterator_traits_detail::__cpp17_input_iterator<_Tp>;
26176d0caaeSpatrick 
26276d0caaeSpatrick // Otherwise, `pointer` names `void`.
26376d0caaeSpatrick template<class>
26476d0caaeSpatrick struct __iterator_traits_member_pointer_or_arrow_or_void { using type = void; };
26576d0caaeSpatrick 
26676d0caaeSpatrick // [iterator.traits]/3.2.1
26776d0caaeSpatrick // If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type.
26876d0caaeSpatrick template<__has_member_pointer _Ip>
26976d0caaeSpatrick struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typename _Ip::pointer; };
27076d0caaeSpatrick 
27176d0caaeSpatrick // Otherwise, if `decltype(declval<I&>().operator->())` is well-formed, then `pointer` names that
27276d0caaeSpatrick // type.
27376d0caaeSpatrick template<class _Ip>
27476d0caaeSpatrick   requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>)
27576d0caaeSpatrick struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> {
276*4bdff4beSrobert   using type = decltype(std::declval<_Ip&>().operator->());
27776d0caaeSpatrick };
27876d0caaeSpatrick 
27976d0caaeSpatrick // Otherwise, `reference` names `iter-reference-t<I>`.
28076d0caaeSpatrick template<class _Ip>
28176d0caaeSpatrick struct __iterator_traits_member_reference { using type = iter_reference_t<_Ip>; };
28276d0caaeSpatrick 
28376d0caaeSpatrick // [iterator.traits]/3.2.2
28476d0caaeSpatrick // If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type.
28576d0caaeSpatrick template<__has_member_reference _Ip>
28676d0caaeSpatrick struct __iterator_traits_member_reference<_Ip> { using type = typename _Ip::reference; };
28776d0caaeSpatrick 
28876d0caaeSpatrick // [iterator.traits]/3.2.3.4
28976d0caaeSpatrick // input_iterator_tag
29076d0caaeSpatrick template<class _Ip>
29176d0caaeSpatrick struct __deduce_iterator_category {
29276d0caaeSpatrick   using type = input_iterator_tag;
29376d0caaeSpatrick };
29476d0caaeSpatrick 
29576d0caaeSpatrick // [iterator.traits]/3.2.3.1
29676d0caaeSpatrick // `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise
29776d0caaeSpatrick template<__iterator_traits_detail::__cpp17_random_access_iterator _Ip>
29876d0caaeSpatrick struct __deduce_iterator_category<_Ip> {
29976d0caaeSpatrick   using type = random_access_iterator_tag;
30076d0caaeSpatrick };
30176d0caaeSpatrick 
30276d0caaeSpatrick // [iterator.traits]/3.2.3.2
30376d0caaeSpatrick // `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise
30476d0caaeSpatrick template<__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip>
30576d0caaeSpatrick struct __deduce_iterator_category<_Ip> {
30676d0caaeSpatrick   using type = bidirectional_iterator_tag;
30776d0caaeSpatrick };
30876d0caaeSpatrick 
30976d0caaeSpatrick // [iterator.traits]/3.2.3.3
31076d0caaeSpatrick // `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise
31176d0caaeSpatrick template<__iterator_traits_detail::__cpp17_forward_iterator _Ip>
31276d0caaeSpatrick struct __deduce_iterator_category<_Ip> {
31376d0caaeSpatrick   using type = forward_iterator_tag;
31476d0caaeSpatrick };
31576d0caaeSpatrick 
31676d0caaeSpatrick template<class _Ip>
31776d0caaeSpatrick struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {};
31876d0caaeSpatrick 
31976d0caaeSpatrick // [iterator.traits]/3.2.3
32076d0caaeSpatrick // If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names
32176d0caaeSpatrick // that type.
32276d0caaeSpatrick template<__has_member_iterator_category _Ip>
32376d0caaeSpatrick struct __iterator_traits_iterator_category<_Ip> {
32476d0caaeSpatrick   using type = typename _Ip::iterator_category;
32576d0caaeSpatrick };
32676d0caaeSpatrick 
32776d0caaeSpatrick // otherwise, it names void.
32876d0caaeSpatrick template<class>
32976d0caaeSpatrick struct __iterator_traits_difference_type { using type = void; };
33076d0caaeSpatrick 
33176d0caaeSpatrick // If the qualified-id `incrementable_traits<I>::difference_type` is valid and denotes a type, then
33276d0caaeSpatrick // `difference_type` names that type;
33376d0caaeSpatrick template<class _Ip>
33476d0caaeSpatrick requires requires { typename incrementable_traits<_Ip>::difference_type; }
33576d0caaeSpatrick struct __iterator_traits_difference_type<_Ip> {
33676d0caaeSpatrick   using type = typename incrementable_traits<_Ip>::difference_type;
33776d0caaeSpatrick };
33876d0caaeSpatrick 
33976d0caaeSpatrick // [iterator.traits]/3.4
34076d0caaeSpatrick // Otherwise, `iterator_traits<I>` has no members by any of the above names.
34176d0caaeSpatrick template<class>
34276d0caaeSpatrick struct __iterator_traits {};
34376d0caaeSpatrick 
34476d0caaeSpatrick // [iterator.traits]/3.1
34576d0caaeSpatrick // If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and
34676d0caaeSpatrick // `iterator-category`, then `iterator-traits<I>` has the following publicly accessible members:
34776d0caaeSpatrick template<__specifies_members _Ip>
34876d0caaeSpatrick struct __iterator_traits<_Ip> {
34976d0caaeSpatrick   using iterator_category  = typename _Ip::iterator_category;
35076d0caaeSpatrick   using value_type         = typename _Ip::value_type;
35176d0caaeSpatrick   using difference_type    = typename _Ip::difference_type;
35276d0caaeSpatrick   using pointer            = typename __iterator_traits_member_pointer_or_void<_Ip>::type;
35376d0caaeSpatrick   using reference          = typename _Ip::reference;
35476d0caaeSpatrick };
35576d0caaeSpatrick 
35676d0caaeSpatrick // [iterator.traits]/3.2
35776d0caaeSpatrick // Otherwise, if `I` satisfies the exposition-only concept `cpp17-input-iterator`,
35876d0caaeSpatrick // `iterator-traits<I>` has the following publicly accessible members:
35976d0caaeSpatrick template<__cpp17_input_iterator_missing_members _Ip>
36076d0caaeSpatrick struct __iterator_traits<_Ip> {
36176d0caaeSpatrick   using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type;
36276d0caaeSpatrick   using value_type        = typename indirectly_readable_traits<_Ip>::value_type;
36376d0caaeSpatrick   using difference_type   = typename incrementable_traits<_Ip>::difference_type;
36476d0caaeSpatrick   using pointer           = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type;
36576d0caaeSpatrick   using reference         = typename __iterator_traits_member_reference<_Ip>::type;
36676d0caaeSpatrick };
36776d0caaeSpatrick 
36876d0caaeSpatrick // Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then
36976d0caaeSpatrick // `iterator_traits<I>` has the following publicly accessible members:
37076d0caaeSpatrick template<__cpp17_iterator_missing_members _Ip>
37176d0caaeSpatrick struct __iterator_traits<_Ip> {
37276d0caaeSpatrick   using iterator_category = output_iterator_tag;
37376d0caaeSpatrick   using value_type        = void;
37476d0caaeSpatrick   using difference_type   = typename __iterator_traits_difference_type<_Ip>::type;
37576d0caaeSpatrick   using pointer           = void;
37676d0caaeSpatrick   using reference         = void;
37776d0caaeSpatrick };
37876d0caaeSpatrick 
37976d0caaeSpatrick template<class _Ip>
38076d0caaeSpatrick struct iterator_traits : __iterator_traits<_Ip> {
38176d0caaeSpatrick   using __primary_template = iterator_traits;
38276d0caaeSpatrick };
38376d0caaeSpatrick 
384*4bdff4beSrobert #else // _LIBCPP_STD_VER > 17
38576d0caaeSpatrick 
38676d0caaeSpatrick template <class _Iter, bool> struct __iterator_traits {};
38776d0caaeSpatrick 
38876d0caaeSpatrick template <class _Iter, bool> struct __iterator_traits_impl {};
38976d0caaeSpatrick 
39076d0caaeSpatrick template <class _Iter>
39176d0caaeSpatrick struct __iterator_traits_impl<_Iter, true>
39276d0caaeSpatrick {
39376d0caaeSpatrick     typedef typename _Iter::difference_type   difference_type;
39476d0caaeSpatrick     typedef typename _Iter::value_type        value_type;
39576d0caaeSpatrick     typedef typename _Iter::pointer           pointer;
39676d0caaeSpatrick     typedef typename _Iter::reference         reference;
39776d0caaeSpatrick     typedef typename _Iter::iterator_category iterator_category;
39876d0caaeSpatrick };
39976d0caaeSpatrick 
40076d0caaeSpatrick template <class _Iter>
40176d0caaeSpatrick struct __iterator_traits<_Iter, true>
40276d0caaeSpatrick     :  __iterator_traits_impl
40376d0caaeSpatrick       <
40476d0caaeSpatrick         _Iter,
40576d0caaeSpatrick         is_convertible<typename _Iter::iterator_category, input_iterator_tag>::value ||
40676d0caaeSpatrick         is_convertible<typename _Iter::iterator_category, output_iterator_tag>::value
40776d0caaeSpatrick       >
40876d0caaeSpatrick {};
40976d0caaeSpatrick 
41076d0caaeSpatrick // iterator_traits<Iterator> will only have the nested types if Iterator::iterator_category
41176d0caaeSpatrick //    exists.  Else iterator_traits<Iterator> will be an empty class.  This is a
41276d0caaeSpatrick //    conforming extension which allows some programs to compile and behave as
41376d0caaeSpatrick //    the client expects instead of failing at compile time.
41476d0caaeSpatrick 
41576d0caaeSpatrick template <class _Iter>
41676d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS iterator_traits
41776d0caaeSpatrick     : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {
41876d0caaeSpatrick 
41976d0caaeSpatrick   using __primary_template = iterator_traits;
42076d0caaeSpatrick };
421*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
42276d0caaeSpatrick 
42376d0caaeSpatrick template<class _Tp>
424*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
42576d0caaeSpatrick requires is_object_v<_Tp>
42676d0caaeSpatrick #endif
42776d0caaeSpatrick struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*>
42876d0caaeSpatrick {
42976d0caaeSpatrick     typedef ptrdiff_t difference_type;
430*4bdff4beSrobert     typedef __remove_cv_t<_Tp> value_type;
43176d0caaeSpatrick     typedef _Tp* pointer;
43276d0caaeSpatrick     typedef _Tp& reference;
43376d0caaeSpatrick     typedef random_access_iterator_tag iterator_category;
43476d0caaeSpatrick #if _LIBCPP_STD_VER > 17
43576d0caaeSpatrick     typedef contiguous_iterator_tag    iterator_concept;
43676d0caaeSpatrick #endif
43776d0caaeSpatrick };
43876d0caaeSpatrick 
43976d0caaeSpatrick template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value>
44076d0caaeSpatrick struct __has_iterator_category_convertible_to
44176d0caaeSpatrick     : is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>
44276d0caaeSpatrick {};
44376d0caaeSpatrick 
44476d0caaeSpatrick template <class _Tp, class _Up>
44576d0caaeSpatrick struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {};
44676d0caaeSpatrick 
44776d0caaeSpatrick template <class _Tp, class _Up, bool = __has_iterator_concept<_Tp>::value>
44876d0caaeSpatrick struct __has_iterator_concept_convertible_to
44976d0caaeSpatrick     : is_convertible<typename _Tp::iterator_concept, _Up>
45076d0caaeSpatrick {};
45176d0caaeSpatrick 
45276d0caaeSpatrick template <class _Tp, class _Up>
45376d0caaeSpatrick struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {};
45476d0caaeSpatrick 
45576d0caaeSpatrick template <class _Tp>
45676d0caaeSpatrick struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {};
45776d0caaeSpatrick 
45876d0caaeSpatrick template <class _Tp>
45976d0caaeSpatrick struct __is_cpp17_forward_iterator : public __has_iterator_category_convertible_to<_Tp, forward_iterator_tag> {};
46076d0caaeSpatrick 
46176d0caaeSpatrick template <class _Tp>
46276d0caaeSpatrick struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag> {};
46376d0caaeSpatrick 
46476d0caaeSpatrick template <class _Tp>
46576d0caaeSpatrick struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {};
46676d0caaeSpatrick 
46776d0caaeSpatrick // __is_cpp17_contiguous_iterator determines if an iterator is known by
46876d0caaeSpatrick // libc++ to be contiguous, either because it advertises itself as such
46976d0caaeSpatrick // (in C++20) or because it is a pointer type or a known trivial wrapper
47076d0caaeSpatrick // around a (possibly fancy) pointer type, such as __wrap_iter<T*>.
47176d0caaeSpatrick // Such iterators receive special "contiguous" optimizations in
47276d0caaeSpatrick // std::copy and std::sort.
47376d0caaeSpatrick //
47476d0caaeSpatrick #if _LIBCPP_STD_VER > 17
47576d0caaeSpatrick template <class _Tp>
47676d0caaeSpatrick struct __is_cpp17_contiguous_iterator : _Or<
47776d0caaeSpatrick     __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>,
47876d0caaeSpatrick     __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag>
47976d0caaeSpatrick > {};
48076d0caaeSpatrick #else
48176d0caaeSpatrick template <class _Tp>
48276d0caaeSpatrick struct __is_cpp17_contiguous_iterator : false_type {};
48376d0caaeSpatrick #endif
48476d0caaeSpatrick 
48576d0caaeSpatrick // Any native pointer which is an iterator is also a contiguous iterator.
48676d0caaeSpatrick template <class _Up>
48776d0caaeSpatrick struct __is_cpp17_contiguous_iterator<_Up*> : true_type {};
48876d0caaeSpatrick 
48976d0caaeSpatrick 
490*4bdff4beSrobert template <class _Iter>
491*4bdff4beSrobert class __wrap_iter;
492*4bdff4beSrobert 
49376d0caaeSpatrick template <class _Tp>
49476d0caaeSpatrick struct __is_exactly_cpp17_input_iterator
49576d0caaeSpatrick     : public integral_constant<bool,
49676d0caaeSpatrick          __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value &&
49776d0caaeSpatrick         !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {};
49876d0caaeSpatrick 
499*4bdff4beSrobert template <class _Tp>
500*4bdff4beSrobert struct __is_exactly_cpp17_forward_iterator
501*4bdff4beSrobert     : public integral_constant<bool,
502*4bdff4beSrobert          __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value &&
503*4bdff4beSrobert         !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value> {};
504*4bdff4beSrobert 
505*4bdff4beSrobert template <class _Tp>
506*4bdff4beSrobert struct __is_exactly_cpp17_bidirectional_iterator
507*4bdff4beSrobert     : public integral_constant<bool,
508*4bdff4beSrobert          __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value &&
509*4bdff4beSrobert         !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value> {};
510*4bdff4beSrobert 
51176d0caaeSpatrick template<class _InputIterator>
51276d0caaeSpatrick using __iter_value_type = typename iterator_traits<_InputIterator>::value_type;
51376d0caaeSpatrick 
51476d0caaeSpatrick template<class _InputIterator>
515*4bdff4beSrobert using __iter_key_type = __remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>;
51676d0caaeSpatrick 
51776d0caaeSpatrick template<class _InputIterator>
51876d0caaeSpatrick using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type;
51976d0caaeSpatrick 
52076d0caaeSpatrick template<class _InputIterator>
52176d0caaeSpatrick using __iter_to_alloc_type = pair<
522*4bdff4beSrobert     typename add_const<typename iterator_traits<_InputIterator>::value_type::first_type>::type,
52376d0caaeSpatrick     typename iterator_traits<_InputIterator>::value_type::second_type>;
524*4bdff4beSrobert 
525*4bdff4beSrobert template <class _Iter>
526*4bdff4beSrobert using __iterator_category_type = typename iterator_traits<_Iter>::iterator_category;
527*4bdff4beSrobert 
528*4bdff4beSrobert template <class _Iter>
529*4bdff4beSrobert using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer;
530*4bdff4beSrobert 
531*4bdff4beSrobert template <class _Iter>
532*4bdff4beSrobert using __iter_diff_t = typename iterator_traits<_Iter>::difference_type;
533*4bdff4beSrobert 
534*4bdff4beSrobert template<class _InputIterator>
535*4bdff4beSrobert using __iter_value_type = typename iterator_traits<_InputIterator>::value_type;
53676d0caaeSpatrick 
53776d0caaeSpatrick _LIBCPP_END_NAMESPACE_STD
53876d0caaeSpatrick 
53976d0caaeSpatrick #endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
540