xref: /freebsd-src/contrib/llvm-project/libcxx/include/__iterator/distance.h (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
1fe6060f1SDimitry Andric // -*- C++ -*-
2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
3fe6060f1SDimitry Andric //
4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7fe6060f1SDimitry Andric //
8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9fe6060f1SDimitry Andric 
10fe6060f1SDimitry Andric #ifndef _LIBCPP___ITERATOR_DISTANCE_H
11fe6060f1SDimitry Andric #define _LIBCPP___ITERATOR_DISTANCE_H
12fe6060f1SDimitry Andric 
13fe6060f1SDimitry Andric #include <__config>
141fd87a68SDimitry Andric #include <__iterator/concepts.h>
151fd87a68SDimitry Andric #include <__iterator/incrementable_traits.h>
16fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h>
171fd87a68SDimitry Andric #include <__ranges/access.h>
181fd87a68SDimitry Andric #include <__ranges/concepts.h>
191fd87a68SDimitry Andric #include <__ranges/size.h>
20bdd1243dSDimitry Andric #include <__type_traits/decay.h>
21bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h>
22fe6060f1SDimitry Andric 
23fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24fe6060f1SDimitry Andric #  pragma GCC system_header
25fe6060f1SDimitry Andric #endif
26fe6060f1SDimitry Andric 
27fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
28fe6060f1SDimitry Andric 
29fe6060f1SDimitry Andric template <class _InputIter>
30*cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InputIter>::difference_type
__distance(_InputIter __first,_InputIter __last,input_iterator_tag)31*cb14a3feSDimitry Andric __distance(_InputIter __first, _InputIter __last, input_iterator_tag) {
32fe6060f1SDimitry Andric   typename iterator_traits<_InputIter>::difference_type __r(0);
33fe6060f1SDimitry Andric   for (; __first != __last; ++__first)
34fe6060f1SDimitry Andric     ++__r;
35fe6060f1SDimitry Andric   return __r;
36fe6060f1SDimitry Andric }
37fe6060f1SDimitry Andric 
38fe6060f1SDimitry Andric template <class _RandIter>
39*cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_RandIter>::difference_type
__distance(_RandIter __first,_RandIter __last,random_access_iterator_tag)40*cb14a3feSDimitry Andric __distance(_RandIter __first, _RandIter __last, random_access_iterator_tag) {
41fe6060f1SDimitry Andric   return __last - __first;
42fe6060f1SDimitry Andric }
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric template <class _InputIter>
45*cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InputIter>::difference_type
distance(_InputIter __first,_InputIter __last)46*cb14a3feSDimitry Andric distance(_InputIter __first, _InputIter __last) {
475f757f3fSDimitry Andric   return std::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category());
48fe6060f1SDimitry Andric }
49fe6060f1SDimitry Andric 
5006c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
511fd87a68SDimitry Andric 
521fd87a68SDimitry Andric // [range.iter.op.distance]
531fd87a68SDimitry Andric 
541fd87a68SDimitry Andric namespace ranges {
551fd87a68SDimitry Andric namespace __distance {
561fd87a68SDimitry Andric 
571fd87a68SDimitry Andric struct __fn {
581fd87a68SDimitry Andric   template <class _Ip, sentinel_for<_Ip> _Sp>
591fd87a68SDimitry Andric     requires(!sized_sentinel_for<_Sp, _Ip>)
operator__fn60*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip> operator()(_Ip __first, _Sp __last) const {
611fd87a68SDimitry Andric     iter_difference_t<_Ip> __n = 0;
621fd87a68SDimitry Andric     while (__first != __last) {
631fd87a68SDimitry Andric       ++__first;
641fd87a68SDimitry Andric       ++__n;
651fd87a68SDimitry Andric     }
661fd87a68SDimitry Andric     return __n;
671fd87a68SDimitry Andric   }
681fd87a68SDimitry Andric 
691fd87a68SDimitry Andric   template <class _Ip, sized_sentinel_for<decay_t<_Ip>> _Sp>
operator__fn70*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip> operator()(_Ip&& __first, _Sp __last) const {
71bdd1243dSDimitry Andric     if constexpr (sized_sentinel_for<_Sp, __remove_cvref_t<_Ip>>) {
721fd87a68SDimitry Andric       return __last - __first;
731fd87a68SDimitry Andric     } else {
741fd87a68SDimitry Andric       return __last - decay_t<_Ip>(__first);
751fd87a68SDimitry Andric     }
761fd87a68SDimitry Andric   }
771fd87a68SDimitry Andric 
781fd87a68SDimitry Andric   template <range _Rp>
operator__fn79*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Rp> operator()(_Rp&& __r) const {
801fd87a68SDimitry Andric     if constexpr (sized_range<_Rp>) {
811fd87a68SDimitry Andric       return static_cast<range_difference_t<_Rp>>(ranges::size(__r));
821fd87a68SDimitry Andric     } else {
831fd87a68SDimitry Andric       return operator()(ranges::begin(__r), ranges::end(__r));
841fd87a68SDimitry Andric     }
851fd87a68SDimitry Andric   }
861fd87a68SDimitry Andric };
871fd87a68SDimitry Andric 
881fd87a68SDimitry Andric } // namespace __distance
891fd87a68SDimitry Andric 
901fd87a68SDimitry Andric inline namespace __cpo {
911fd87a68SDimitry Andric inline constexpr auto distance = __distance::__fn{};
921fd87a68SDimitry Andric } // namespace __cpo
931fd87a68SDimitry Andric } // namespace ranges
941fd87a68SDimitry Andric 
9506c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
961fd87a68SDimitry Andric 
97fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
98fe6060f1SDimitry Andric 
99fe6060f1SDimitry Andric #endif // _LIBCPP___ITERATOR_DISTANCE_H
100