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