xref: /openbsd-src/gnu/llvm/libcxx/include/__iterator/distance.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_DISTANCE_H
1176d0caaeSpatrick #define _LIBCPP___ITERATOR_DISTANCE_H
1276d0caaeSpatrick 
1376d0caaeSpatrick #include <__config>
14*4bdff4beSrobert #include <__iterator/concepts.h>
15*4bdff4beSrobert #include <__iterator/incrementable_traits.h>
1676d0caaeSpatrick #include <__iterator/iterator_traits.h>
17*4bdff4beSrobert #include <__ranges/access.h>
18*4bdff4beSrobert #include <__ranges/concepts.h>
19*4bdff4beSrobert #include <__ranges/size.h>
20*4bdff4beSrobert #include <__type_traits/decay.h>
21*4bdff4beSrobert #include <__type_traits/remove_cvref.h>
2276d0caaeSpatrick 
2376d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2476d0caaeSpatrick #  pragma GCC system_header
2576d0caaeSpatrick #endif
2676d0caaeSpatrick 
2776d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD
2876d0caaeSpatrick 
2976d0caaeSpatrick template <class _InputIter>
30*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17
3176d0caaeSpatrick typename iterator_traits<_InputIter>::difference_type
__distance(_InputIter __first,_InputIter __last,input_iterator_tag)3276d0caaeSpatrick __distance(_InputIter __first, _InputIter __last, input_iterator_tag)
3376d0caaeSpatrick {
3476d0caaeSpatrick     typename iterator_traits<_InputIter>::difference_type __r(0);
3576d0caaeSpatrick     for (; __first != __last; ++__first)
3676d0caaeSpatrick         ++__r;
3776d0caaeSpatrick     return __r;
3876d0caaeSpatrick }
3976d0caaeSpatrick 
4076d0caaeSpatrick template <class _RandIter>
41*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17
4276d0caaeSpatrick typename iterator_traits<_RandIter>::difference_type
__distance(_RandIter __first,_RandIter __last,random_access_iterator_tag)4376d0caaeSpatrick __distance(_RandIter __first, _RandIter __last, random_access_iterator_tag)
4476d0caaeSpatrick {
4576d0caaeSpatrick     return __last - __first;
4676d0caaeSpatrick }
4776d0caaeSpatrick 
4876d0caaeSpatrick template <class _InputIter>
49*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17
5076d0caaeSpatrick typename iterator_traits<_InputIter>::difference_type
distance(_InputIter __first,_InputIter __last)5176d0caaeSpatrick distance(_InputIter __first, _InputIter __last)
5276d0caaeSpatrick {
5376d0caaeSpatrick     return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category());
5476d0caaeSpatrick }
5576d0caaeSpatrick 
56*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
5776d0caaeSpatrick 
58*4bdff4beSrobert // [range.iter.op.distance]
59*4bdff4beSrobert 
60*4bdff4beSrobert namespace ranges {
61*4bdff4beSrobert namespace __distance {
62*4bdff4beSrobert 
63*4bdff4beSrobert struct __fn {
64*4bdff4beSrobert   template<class _Ip, sentinel_for<_Ip> _Sp>
65*4bdff4beSrobert     requires (!sized_sentinel_for<_Sp, _Ip>)
66*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
operator__fn67*4bdff4beSrobert   constexpr iter_difference_t<_Ip> operator()(_Ip __first, _Sp __last) const {
68*4bdff4beSrobert     iter_difference_t<_Ip> __n = 0;
69*4bdff4beSrobert     while (__first != __last) {
70*4bdff4beSrobert       ++__first;
71*4bdff4beSrobert       ++__n;
72*4bdff4beSrobert     }
73*4bdff4beSrobert     return __n;
74*4bdff4beSrobert   }
75*4bdff4beSrobert 
76*4bdff4beSrobert   template<class _Ip, sized_sentinel_for<decay_t<_Ip>> _Sp>
77*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
operator__fn78*4bdff4beSrobert   constexpr iter_difference_t<_Ip> operator()(_Ip&& __first, _Sp __last) const {
79*4bdff4beSrobert     if constexpr (sized_sentinel_for<_Sp, __remove_cvref_t<_Ip>>) {
80*4bdff4beSrobert       return __last - __first;
81*4bdff4beSrobert     } else {
82*4bdff4beSrobert       return __last - decay_t<_Ip>(__first);
83*4bdff4beSrobert     }
84*4bdff4beSrobert   }
85*4bdff4beSrobert 
86*4bdff4beSrobert   template<range _Rp>
87*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
operator__fn88*4bdff4beSrobert   constexpr range_difference_t<_Rp> operator()(_Rp&& __r) const {
89*4bdff4beSrobert     if constexpr (sized_range<_Rp>) {
90*4bdff4beSrobert       return static_cast<range_difference_t<_Rp>>(ranges::size(__r));
91*4bdff4beSrobert     } else {
92*4bdff4beSrobert       return operator()(ranges::begin(__r), ranges::end(__r));
93*4bdff4beSrobert     }
94*4bdff4beSrobert   }
95*4bdff4beSrobert };
96*4bdff4beSrobert 
97*4bdff4beSrobert } // namespace __distance
98*4bdff4beSrobert 
99*4bdff4beSrobert inline namespace __cpo {
100*4bdff4beSrobert   inline constexpr auto distance = __distance::__fn{};
101*4bdff4beSrobert } // namespace __cpo
102*4bdff4beSrobert } // namespace ranges
103*4bdff4beSrobert 
104*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
105*4bdff4beSrobert 
106*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
10776d0caaeSpatrick 
10876d0caaeSpatrick #endif // _LIBCPP___ITERATOR_DISTANCE_H
109