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