File indexing completed on 2026-05-03 08:13:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
0011 #define _LIBCPP___ITERATOR_ITERATOR_TRAITS_H
0012
0013 #include <__concepts/arithmetic.h>
0014 #include <__concepts/constructible.h>
0015 #include <__concepts/convertible_to.h>
0016 #include <__concepts/copyable.h>
0017 #include <__concepts/equality_comparable.h>
0018 #include <__concepts/same_as.h>
0019 #include <__concepts/totally_ordered.h>
0020 #include <__config>
0021 #include <__cstddef/ptrdiff_t.h>
0022 #include <__fwd/pair.h>
0023 #include <__iterator/incrementable_traits.h>
0024 #include <__iterator/readable_traits.h>
0025 #include <__type_traits/common_reference.h>
0026 #include <__type_traits/conditional.h>
0027 #include <__type_traits/disjunction.h>
0028 #include <__type_traits/enable_if.h>
0029 #include <__type_traits/integral_constant.h>
0030 #include <__type_traits/is_convertible.h>
0031 #include <__type_traits/is_object.h>
0032 #include <__type_traits/is_primary_template.h>
0033 #include <__type_traits/is_reference.h>
0034 #include <__type_traits/is_valid_expansion.h>
0035 #include <__type_traits/remove_const.h>
0036 #include <__type_traits/remove_cv.h>
0037 #include <__type_traits/remove_cvref.h>
0038 #include <__type_traits/void_t.h>
0039 #include <__utility/declval.h>
0040
0041 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0042 # pragma GCC system_header
0043 #endif
0044
0045 _LIBCPP_BEGIN_NAMESPACE_STD
0046
0047 #if _LIBCPP_STD_VER >= 20
0048
0049 template <class _Tp>
0050 using __with_reference _LIBCPP_NODEBUG = _Tp&;
0051
0052 template <class _Tp>
0053 concept __can_reference = requires { typename __with_reference<_Tp>; };
0054
0055 template <class _Tp>
0056 concept __dereferenceable = requires(_Tp& __t) {
0057 { *__t } -> __can_reference;
0058 };
0059
0060
0061 template <__dereferenceable _Tp>
0062 using iter_reference_t = decltype(*std::declval<_Tp&>());
0063
0064 #endif
0065
0066 template <class _Iter>
0067 struct _LIBCPP_TEMPLATE_VIS iterator_traits;
0068
0069 struct _LIBCPP_TEMPLATE_VIS input_iterator_tag {};
0070 struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {};
0071 struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag : public input_iterator_tag {};
0072 struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {};
0073 struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {};
0074 #if _LIBCPP_STD_VER >= 20
0075 struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag : public random_access_iterator_tag {};
0076 #endif
0077
0078 template <class _Iter>
0079 struct __iter_traits_cache {
0080 using type = _If< __is_primary_template<iterator_traits<_Iter> >::value, _Iter, iterator_traits<_Iter> >;
0081 };
0082 template <class _Iter>
0083 using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type;
0084
0085 struct __iter_concept_concept_test {
0086 template <class _Iter>
0087 using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_concept;
0088 };
0089 struct __iter_concept_category_test {
0090 template <class _Iter>
0091 using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_category;
0092 };
0093 struct __iter_concept_random_fallback {
0094 template <class _Iter>
0095 using _Apply _LIBCPP_NODEBUG =
0096 __enable_if_t<__is_primary_template<iterator_traits<_Iter> >::value, random_access_iterator_tag>;
0097 };
0098
0099 template <class _Iter, class _Tester>
0100 struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>, _Tester {};
0101
0102 template <class _Iter>
0103 struct __iter_concept_cache {
0104 using type = _Or< __test_iter_concept<_Iter, __iter_concept_concept_test>,
0105 __test_iter_concept<_Iter, __iter_concept_category_test>,
0106 __test_iter_concept<_Iter, __iter_concept_random_fallback> >;
0107 };
0108
0109 template <class _Iter>
0110 using _ITER_CONCEPT _LIBCPP_NODEBUG = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>;
0111
0112 template <class _Tp>
0113 struct __has_iterator_typedefs {
0114 private:
0115 template <class _Up>
0116 static false_type __test(...);
0117 template <class _Up>
0118 static true_type
0119 __test(__void_t<typename _Up::iterator_category>* = nullptr,
0120 __void_t<typename _Up::difference_type>* = nullptr,
0121 __void_t<typename _Up::value_type>* = nullptr,
0122 __void_t<typename _Up::reference>* = nullptr,
0123 __void_t<typename _Up::pointer>* = nullptr);
0124
0125 public:
0126 static const bool value = decltype(__test<_Tp>(nullptr, nullptr, nullptr, nullptr, nullptr))::value;
0127 };
0128
0129 template <class _Tp>
0130 struct __has_iterator_category {
0131 private:
0132 template <class _Up>
0133 static false_type __test(...);
0134 template <class _Up>
0135 static true_type __test(typename _Up::iterator_category* = nullptr);
0136
0137 public:
0138 static const bool value = decltype(__test<_Tp>(nullptr))::value;
0139 };
0140
0141 template <class _Tp>
0142 struct __has_iterator_concept {
0143 private:
0144 template <class _Up>
0145 static false_type __test(...);
0146 template <class _Up>
0147 static true_type __test(typename _Up::iterator_concept* = nullptr);
0148
0149 public:
0150 static const bool value = decltype(__test<_Tp>(nullptr))::value;
0151 };
0152
0153 #if _LIBCPP_STD_VER >= 20
0154
0155
0156
0157
0158 namespace __iterator_traits_detail {
0159 template <class _Ip>
0160 concept __cpp17_iterator = requires(_Ip __i) {
0161 { *__i } -> __can_reference;
0162 { ++__i } -> same_as<_Ip&>;
0163 { *__i++ } -> __can_reference;
0164 } && copyable<_Ip>;
0165
0166 template <class _Ip>
0167 concept __cpp17_input_iterator = __cpp17_iterator<_Ip> && equality_comparable<_Ip> && requires(_Ip __i) {
0168 typename incrementable_traits<_Ip>::difference_type;
0169 typename indirectly_readable_traits<_Ip>::value_type;
0170 typename common_reference_t<iter_reference_t<_Ip>&&, typename indirectly_readable_traits<_Ip>::value_type&>;
0171 typename common_reference_t<decltype(*__i++)&&, typename indirectly_readable_traits<_Ip>::value_type&>;
0172 requires signed_integral<typename incrementable_traits<_Ip>::difference_type>;
0173 };
0174
0175 template <class _Ip>
0176 concept __cpp17_forward_iterator =
0177 __cpp17_input_iterator<_Ip> && constructible_from<_Ip> && is_reference_v<iter_reference_t<_Ip>> &&
0178 same_as<remove_cvref_t<iter_reference_t<_Ip>>, typename indirectly_readable_traits<_Ip>::value_type> &&
0179 requires(_Ip __i) {
0180 { __i++ } -> convertible_to<_Ip const&>;
0181 { *__i++ } -> same_as<iter_reference_t<_Ip>>;
0182 };
0183
0184 template <class _Ip>
0185 concept __cpp17_bidirectional_iterator = __cpp17_forward_iterator<_Ip> && requires(_Ip __i) {
0186 { --__i } -> same_as<_Ip&>;
0187 { __i-- } -> convertible_to<_Ip const&>;
0188 { *__i-- } -> same_as<iter_reference_t<_Ip>>;
0189 };
0190
0191 template <class _Ip>
0192 concept __cpp17_random_access_iterator =
0193 __cpp17_bidirectional_iterator<_Ip> && totally_ordered<_Ip> &&
0194 requires(_Ip __i, typename incrementable_traits<_Ip>::difference_type __n) {
0195 { __i += __n } -> same_as<_Ip&>;
0196 { __i -= __n } -> same_as<_Ip&>;
0197 { __i + __n } -> same_as<_Ip>;
0198 { __n + __i } -> same_as<_Ip>;
0199 { __i - __n } -> same_as<_Ip>;
0200 { __i - __i } -> same_as<decltype(__n)>;
0201 { __i[__n] } -> convertible_to<iter_reference_t<_Ip>>;
0202 };
0203 }
0204
0205 template <class _Ip>
0206 concept __has_member_reference = requires { typename _Ip::reference; };
0207
0208 template <class _Ip>
0209 concept __has_member_pointer = requires { typename _Ip::pointer; };
0210
0211 template <class _Ip>
0212 concept __has_member_iterator_category = requires { typename _Ip::iterator_category; };
0213
0214 template <class _Ip>
0215 concept __specifies_members = requires {
0216 typename _Ip::value_type;
0217 typename _Ip::difference_type;
0218 requires __has_member_reference<_Ip>;
0219 requires __has_member_iterator_category<_Ip>;
0220 };
0221
0222 template <class>
0223 struct __iterator_traits_member_pointer_or_void {
0224 using type = void;
0225 };
0226
0227 template <__has_member_pointer _Tp>
0228 struct __iterator_traits_member_pointer_or_void<_Tp> {
0229 using type = typename _Tp::pointer;
0230 };
0231
0232 template <class _Tp>
0233 concept __cpp17_iterator_missing_members = !__specifies_members<_Tp> && __iterator_traits_detail::__cpp17_iterator<_Tp>;
0234
0235 template <class _Tp>
0236 concept __cpp17_input_iterator_missing_members =
0237 __cpp17_iterator_missing_members<_Tp> && __iterator_traits_detail::__cpp17_input_iterator<_Tp>;
0238
0239
0240 template <class>
0241 struct __iterator_traits_member_pointer_or_arrow_or_void {
0242 using type = void;
0243 };
0244
0245
0246
0247 template <__has_member_pointer _Ip>
0248 struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> {
0249 using type = typename _Ip::pointer;
0250 };
0251
0252
0253
0254 template <class _Ip>
0255 requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>)
0256 struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> {
0257 using type = decltype(std::declval<_Ip&>().operator->());
0258 };
0259
0260
0261 template <class _Ip>
0262 struct __iterator_traits_member_reference {
0263 using type = iter_reference_t<_Ip>;
0264 };
0265
0266
0267
0268 template <__has_member_reference _Ip>
0269 struct __iterator_traits_member_reference<_Ip> {
0270 using type = typename _Ip::reference;
0271 };
0272
0273
0274
0275 template <class _Ip>
0276 struct __deduce_iterator_category {
0277 using type = input_iterator_tag;
0278 };
0279
0280
0281
0282 template <__iterator_traits_detail::__cpp17_random_access_iterator _Ip>
0283 struct __deduce_iterator_category<_Ip> {
0284 using type = random_access_iterator_tag;
0285 };
0286
0287
0288
0289 template <__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip>
0290 struct __deduce_iterator_category<_Ip> {
0291 using type = bidirectional_iterator_tag;
0292 };
0293
0294
0295
0296 template <__iterator_traits_detail::__cpp17_forward_iterator _Ip>
0297 struct __deduce_iterator_category<_Ip> {
0298 using type = forward_iterator_tag;
0299 };
0300
0301 template <class _Ip>
0302 struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {};
0303
0304
0305
0306
0307 template <__has_member_iterator_category _Ip>
0308 struct __iterator_traits_iterator_category<_Ip> {
0309 using type = typename _Ip::iterator_category;
0310 };
0311
0312
0313 template <class>
0314 struct __iterator_traits_difference_type {
0315 using type = void;
0316 };
0317
0318
0319
0320 template <class _Ip>
0321 requires requires { typename incrementable_traits<_Ip>::difference_type; }
0322 struct __iterator_traits_difference_type<_Ip> {
0323 using type = typename incrementable_traits<_Ip>::difference_type;
0324 };
0325
0326
0327
0328 template <class>
0329 struct __iterator_traits {};
0330
0331
0332
0333
0334 template <__specifies_members _Ip>
0335 struct __iterator_traits<_Ip> {
0336 using iterator_category = typename _Ip::iterator_category;
0337 using value_type = typename _Ip::value_type;
0338 using difference_type = typename _Ip::difference_type;
0339 using pointer = typename __iterator_traits_member_pointer_or_void<_Ip>::type;
0340 using reference = typename _Ip::reference;
0341 };
0342
0343
0344
0345
0346 template <__cpp17_input_iterator_missing_members _Ip>
0347 struct __iterator_traits<_Ip> {
0348 using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type;
0349 using value_type = typename indirectly_readable_traits<_Ip>::value_type;
0350 using difference_type = typename incrementable_traits<_Ip>::difference_type;
0351 using pointer = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type;
0352 using reference = typename __iterator_traits_member_reference<_Ip>::type;
0353 };
0354
0355
0356
0357 template <__cpp17_iterator_missing_members _Ip>
0358 struct __iterator_traits<_Ip> {
0359 using iterator_category = output_iterator_tag;
0360 using value_type = void;
0361 using difference_type = typename __iterator_traits_difference_type<_Ip>::type;
0362 using pointer = void;
0363 using reference = void;
0364 };
0365
0366 template <class _Ip>
0367 struct iterator_traits : __iterator_traits<_Ip> {
0368 using __primary_template _LIBCPP_NODEBUG = iterator_traits;
0369 };
0370
0371 #else
0372
0373 template <class _Iter, bool>
0374 struct __iterator_traits {};
0375
0376 template <class _Iter, bool>
0377 struct __iterator_traits_impl {};
0378
0379 template <class _Iter>
0380 struct __iterator_traits_impl<_Iter, true> {
0381 typedef typename _Iter::difference_type difference_type;
0382 typedef typename _Iter::value_type value_type;
0383 typedef typename _Iter::pointer pointer;
0384 typedef typename _Iter::reference reference;
0385 typedef typename _Iter::iterator_category iterator_category;
0386 };
0387
0388 template <class _Iter>
0389 struct __iterator_traits<_Iter, true>
0390 : __iterator_traits_impl< _Iter,
0391 is_convertible<typename _Iter::iterator_category, input_iterator_tag>::value ||
0392 is_convertible<typename _Iter::iterator_category, output_iterator_tag>::value > {};
0393
0394
0395
0396
0397
0398
0399 template <class _Iter>
0400 struct _LIBCPP_TEMPLATE_VIS iterator_traits : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {
0401 using __primary_template _LIBCPP_NODEBUG = iterator_traits;
0402 };
0403 #endif
0404
0405 template <class _Tp>
0406 #if _LIBCPP_STD_VER >= 20
0407 requires is_object_v<_Tp>
0408 #endif
0409 struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> {
0410 typedef ptrdiff_t difference_type;
0411 typedef __remove_cv_t<_Tp> value_type;
0412 typedef _Tp* pointer;
0413 typedef _Tp& reference;
0414 typedef random_access_iterator_tag iterator_category;
0415 #if _LIBCPP_STD_VER >= 20
0416 typedef contiguous_iterator_tag iterator_concept;
0417 #endif
0418 };
0419
0420 template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value>
0421 struct __has_iterator_category_convertible_to : is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up> {
0422 };
0423
0424 template <class _Tp, class _Up>
0425 struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {};
0426
0427 template <class _Tp, class _Up, bool = __has_iterator_concept<_Tp>::value>
0428 struct __has_iterator_concept_convertible_to : is_convertible<typename _Tp::iterator_concept, _Up> {};
0429
0430 template <class _Tp, class _Up>
0431 struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {};
0432
0433 template <class _Tp>
0434 using __has_input_iterator_category _LIBCPP_NODEBUG = __has_iterator_category_convertible_to<_Tp, input_iterator_tag>;
0435
0436 template <class _Tp>
0437 using __has_forward_iterator_category _LIBCPP_NODEBUG =
0438 __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>;
0439
0440 template <class _Tp>
0441 using __has_bidirectional_iterator_category _LIBCPP_NODEBUG =
0442 __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>;
0443
0444 template <class _Tp>
0445 using __has_random_access_iterator_category _LIBCPP_NODEBUG =
0446 __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>;
0447
0448
0449
0450
0451
0452
0453
0454
0455 #if _LIBCPP_STD_VER >= 20
0456 template <class _Tp>
0457 struct __libcpp_is_contiguous_iterator
0458 : _Or< __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>,
0459 __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag> > {};
0460 #else
0461 template <class _Tp>
0462 struct __libcpp_is_contiguous_iterator : false_type {};
0463 #endif
0464
0465
0466 template <class _Up>
0467 struct __libcpp_is_contiguous_iterator<_Up*> : true_type {};
0468
0469 template <class _Iter>
0470 class __wrap_iter;
0471
0472 template <class _Tp>
0473 using __has_exactly_input_iterator_category _LIBCPP_NODEBUG =
0474 integral_constant<bool,
0475 __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value &&
0476 !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value>;
0477
0478 template <class _Tp>
0479 using __has_exactly_forward_iterator_category _LIBCPP_NODEBUG =
0480 integral_constant<bool,
0481 __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value &&
0482 !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value>;
0483
0484 template <class _Tp>
0485 using __has_exactly_bidirectional_iterator_category _LIBCPP_NODEBUG =
0486 integral_constant<bool,
0487 __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value &&
0488 !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value>;
0489
0490 template <class _InputIterator>
0491 using __iter_value_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type;
0492
0493 template <class _InputIterator>
0494 using __iter_key_type _LIBCPP_NODEBUG =
0495 __remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>;
0496
0497 template <class _InputIterator>
0498 using __iter_mapped_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type::second_type;
0499
0500 template <class _InputIterator>
0501 using __iter_to_alloc_type _LIBCPP_NODEBUG =
0502 pair<const typename iterator_traits<_InputIterator>::value_type::first_type,
0503 typename iterator_traits<_InputIterator>::value_type::second_type>;
0504
0505 template <class _Iter>
0506 using __iterator_category_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category;
0507
0508 template <class _Iter>
0509 using __iterator_pointer_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::pointer;
0510
0511 template <class _Iter>
0512 using __iter_diff_t _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type;
0513
0514 template <class _Iter>
0515 using __iter_reference _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::reference;
0516
0517 #if _LIBCPP_STD_VER >= 20
0518
0519
0520
0521
0522
0523
0524
0525 template <class _Ip>
0526 using iter_value_t =
0527 typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
0528 indirectly_readable_traits<remove_cvref_t<_Ip> >,
0529 iterator_traits<remove_cvref_t<_Ip> > >::value_type;
0530
0531 #endif
0532
0533 _LIBCPP_END_NAMESPACE_STD
0534
0535 #endif