1010#ifndef _LIBCPP___ITERATOR_DISTANCE_H
1111#define _LIBCPP___ITERATOR_DISTANCE_H
1212
13+ #include < __algorithm/for_each_segment.h>
1314#include < __config>
1415#include < __iterator/concepts.h>
1516#include < __iterator/incrementable_traits.h>
1617#include < __iterator/iterator_traits.h>
18+ #include < __iterator/segmented_iterator.h>
1719#include < __ranges/access.h>
1820#include < __ranges/concepts.h>
1921#include < __ranges/size.h>
2022#include < __type_traits/decay.h>
23+ #include < __type_traits/enable_if.h>
2124#include < __type_traits/remove_cvref.h>
25+ #include < __utility/move.h>
2226
2327#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2428# pragma GCC system_header
2529#endif
2630
31+ _LIBCPP_PUSH_MACROS
32+ #include < __undef_macros>
33+
2734_LIBCPP_BEGIN_NAMESPACE_STD
2835
29- template <class _InputIter >
30- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InputIter>::difference_type
31- __distance (_InputIter __first, _InputIter __last, input_iterator_tag) {
32- typename iterator_traits<_InputIter>::difference_type __r (0 );
36+ #if _LIBCPP_STD_VER >= 20
37+ template <class _Iter >
38+ using __iter_distance_t _LIBCPP_NODEBUG = std::iter_difference_t <_Iter>;
39+ #else
40+ template <class _Iter >
41+ using __iter_distance_t _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type;
42+ #endif
43+
44+ template <class _InputIter , class _Sent >
45+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t <_InputIter>
46+ __distance (_InputIter __first, _Sent __last) {
47+ __iter_distance_t <_InputIter> __r (0 );
3348 for (; __first != __last; ++__first)
3449 ++__r;
3550 return __r;
3651}
3752
38- template <class _RandIter >
39- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits <_RandIter>::difference_type
40- __distance (_RandIter __first, _RandIter __last, random_access_iterator_tag ) {
53+ template <class _RandIter , __enable_if_t <__has_random_access_iterator_category<_RandIter>::value, int > = 0 >
54+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t <_RandIter>
55+ __distance (_RandIter __first, _RandIter __last) {
4156 return __last - __first;
4257}
4358
59+ template <class _SegmentedIter , class _Difference >
60+ struct __segment_distance {
61+ using _Traits _LIBCPP_NODEBUG = __segmented_iterator_traits<_SegmentedIter>;
62+
63+ _Difference& __r_;
64+
65+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __segment_distance (_Difference& __r) : __r_(__r) {}
66+
67+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
68+ operator ()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) {
69+ __r_ += std::__distance (__lfirst, __llast);
70+ }
71+ };
72+
73+ template <class _SegmentedIter ,
74+ __enable_if_t <!__has_random_access_iterator_category<_SegmentedIter>::value &&
75+ __is_segmented_iterator<_SegmentedIter>::value,
76+ int > = 0 >
77+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t <_SegmentedIter>
78+ __distance (_SegmentedIter __first, _SegmentedIter __last) {
79+ using __difference_type = __iter_distance_t <_SegmentedIter>;
80+ __difference_type __r (0 );
81+ std::__for_each_segment (__first, __last, std::__segment_distance<_SegmentedIter, __difference_type>(__r));
82+ return __r;
83+ }
84+
4485template <class _InputIter >
45- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits <_InputIter>::difference_type
86+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t <_InputIter>
4687distance (_InputIter __first, _InputIter __last) {
47- return std::__distance (__first, __last, typename iterator_traits<_InputIter>:: iterator_category () );
88+ return std::__distance (__first, __last);
4889}
4990
5091#if _LIBCPP_STD_VER >= 20
@@ -56,12 +97,7 @@ struct __distance {
5697 template <class _Ip , sentinel_for<_Ip> _Sp>
5798 requires (!sized_sentinel_for<_Sp, _Ip>)
5899 _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t <_Ip> operator ()(_Ip __first, _Sp __last) const {
59- iter_difference_t <_Ip> __n = 0 ;
60- while (__first != __last) {
61- ++__first;
62- ++__n;
63- }
64- return __n;
100+ return std::__distance (std::move (__first), std::move (__last));
65101 }
66102
67103 template <class _Ip , sized_sentinel_for<decay_t <_Ip>> _Sp>
@@ -92,4 +128,6 @@ inline constexpr auto distance = __distance{};
92128
93129_LIBCPP_END_NAMESPACE_STD
94130
131+ _LIBCPP_POP_MACROS
132+
95133#endif // _LIBCPP___ITERATOR_DISTANCE_H
0 commit comments