1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 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 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___ITERATOR_DISTANCE_H 11 #define _LIBCPP___ITERATOR_DISTANCE_H 12 13 #include <__config> 14 #include <__iterator/concepts.h> 15 #include <__iterator/incrementable_traits.h> 16 #include <__iterator/iterator_traits.h> 17 #include <__ranges/access.h> 18 #include <__ranges/concepts.h> 19 #include <__ranges/size.h> 20 #include <__type_traits/decay.h> 21 #include <__type_traits/remove_cvref.h> 22 23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 24 # pragma GCC system_header 25 #endif 26 27 _LIBCPP_BEGIN_NAMESPACE_STD 28 29 template <class _InputIter> 30 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 31 typename iterator_traits<_InputIter>::difference_type 32 __distance(_InputIter __first, _InputIter __last, input_iterator_tag) 33 { 34 typename iterator_traits<_InputIter>::difference_type __r(0); 35 for (; __first != __last; ++__first) 36 ++__r; 37 return __r; 38 } 39 40 template <class _RandIter> 41 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 42 typename iterator_traits<_RandIter>::difference_type 43 __distance(_RandIter __first, _RandIter __last, random_access_iterator_tag) 44 { 45 return __last - __first; 46 } 47 48 template <class _InputIter> 49 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 50 typename iterator_traits<_InputIter>::difference_type 51 distance(_InputIter __first, _InputIter __last) 52 { 53 return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category()); 54 } 55 56 #if _LIBCPP_STD_VER >= 20 57 58 // [range.iter.op.distance] 59 60 namespace ranges { 61 namespace __distance { 62 63 struct __fn { 64 template<class _Ip, sentinel_for<_Ip> _Sp> 65 requires (!sized_sentinel_for<_Sp, _Ip>) 66 _LIBCPP_HIDE_FROM_ABI 67 constexpr iter_difference_t<_Ip> operator()(_Ip __first, _Sp __last) const { 68 iter_difference_t<_Ip> __n = 0; 69 while (__first != __last) { 70 ++__first; 71 ++__n; 72 } 73 return __n; 74 } 75 76 template<class _Ip, sized_sentinel_for<decay_t<_Ip>> _Sp> 77 _LIBCPP_HIDE_FROM_ABI 78 constexpr iter_difference_t<_Ip> operator()(_Ip&& __first, _Sp __last) const { 79 if constexpr (sized_sentinel_for<_Sp, __remove_cvref_t<_Ip>>) { 80 return __last - __first; 81 } else { 82 return __last - decay_t<_Ip>(__first); 83 } 84 } 85 86 template<range _Rp> 87 _LIBCPP_HIDE_FROM_ABI 88 constexpr range_difference_t<_Rp> operator()(_Rp&& __r) const { 89 if constexpr (sized_range<_Rp>) { 90 return static_cast<range_difference_t<_Rp>>(ranges::size(__r)); 91 } else { 92 return operator()(ranges::begin(__r), ranges::end(__r)); 93 } 94 } 95 }; 96 97 } // namespace __distance 98 99 inline namespace __cpo { 100 inline constexpr auto distance = __distance::__fn{}; 101 } // namespace __cpo 102 } // namespace ranges 103 104 #endif // _LIBCPP_STD_VER >= 20 105 106 _LIBCPP_END_NAMESPACE_STD 107 108 #endif // _LIBCPP___ITERATOR_DISTANCE_H 109