xref: /freebsd-src/contrib/llvm-project/libcxx/include/__iterator/distance.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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>
20*bdd1243dSDimitry Andric #include <__type_traits/decay.h>
21*bdd1243dSDimitry 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*bdd1243dSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17
31fe6060f1SDimitry Andric typename iterator_traits<_InputIter>::difference_type
32fe6060f1SDimitry Andric __distance(_InputIter __first, _InputIter __last, input_iterator_tag)
33fe6060f1SDimitry Andric {
34fe6060f1SDimitry Andric     typename iterator_traits<_InputIter>::difference_type __r(0);
35fe6060f1SDimitry Andric     for (; __first != __last; ++__first)
36fe6060f1SDimitry Andric         ++__r;
37fe6060f1SDimitry Andric     return __r;
38fe6060f1SDimitry Andric }
39fe6060f1SDimitry Andric 
40fe6060f1SDimitry Andric template <class _RandIter>
41*bdd1243dSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17
42fe6060f1SDimitry Andric typename iterator_traits<_RandIter>::difference_type
43fe6060f1SDimitry Andric __distance(_RandIter __first, _RandIter __last, random_access_iterator_tag)
44fe6060f1SDimitry Andric {
45fe6060f1SDimitry Andric     return __last - __first;
46fe6060f1SDimitry Andric }
47fe6060f1SDimitry Andric 
48fe6060f1SDimitry Andric template <class _InputIter>
49*bdd1243dSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17
50fe6060f1SDimitry Andric typename iterator_traits<_InputIter>::difference_type
51fe6060f1SDimitry Andric distance(_InputIter __first, _InputIter __last)
52fe6060f1SDimitry Andric {
53fe6060f1SDimitry Andric     return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category());
54fe6060f1SDimitry Andric }
55fe6060f1SDimitry Andric 
56*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17
571fd87a68SDimitry Andric 
581fd87a68SDimitry Andric // [range.iter.op.distance]
591fd87a68SDimitry Andric 
601fd87a68SDimitry Andric namespace ranges {
611fd87a68SDimitry Andric namespace __distance {
621fd87a68SDimitry Andric 
631fd87a68SDimitry Andric struct __fn {
641fd87a68SDimitry Andric   template<class _Ip, sentinel_for<_Ip> _Sp>
651fd87a68SDimitry Andric     requires (!sized_sentinel_for<_Sp, _Ip>)
661fd87a68SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
671fd87a68SDimitry Andric   constexpr iter_difference_t<_Ip> operator()(_Ip __first, _Sp __last) const {
681fd87a68SDimitry Andric     iter_difference_t<_Ip> __n = 0;
691fd87a68SDimitry Andric     while (__first != __last) {
701fd87a68SDimitry Andric       ++__first;
711fd87a68SDimitry Andric       ++__n;
721fd87a68SDimitry Andric     }
731fd87a68SDimitry Andric     return __n;
741fd87a68SDimitry Andric   }
751fd87a68SDimitry Andric 
761fd87a68SDimitry Andric   template<class _Ip, sized_sentinel_for<decay_t<_Ip>> _Sp>
771fd87a68SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
781fd87a68SDimitry Andric   constexpr iter_difference_t<_Ip> operator()(_Ip&& __first, _Sp __last) const {
79*bdd1243dSDimitry Andric     if constexpr (sized_sentinel_for<_Sp, __remove_cvref_t<_Ip>>) {
801fd87a68SDimitry Andric       return __last - __first;
811fd87a68SDimitry Andric     } else {
821fd87a68SDimitry Andric       return __last - decay_t<_Ip>(__first);
831fd87a68SDimitry Andric     }
841fd87a68SDimitry Andric   }
851fd87a68SDimitry Andric 
861fd87a68SDimitry Andric   template<range _Rp>
871fd87a68SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
881fd87a68SDimitry Andric   constexpr range_difference_t<_Rp> operator()(_Rp&& __r) const {
891fd87a68SDimitry Andric     if constexpr (sized_range<_Rp>) {
901fd87a68SDimitry Andric       return static_cast<range_difference_t<_Rp>>(ranges::size(__r));
911fd87a68SDimitry Andric     } else {
921fd87a68SDimitry Andric       return operator()(ranges::begin(__r), ranges::end(__r));
931fd87a68SDimitry Andric     }
941fd87a68SDimitry Andric   }
951fd87a68SDimitry Andric };
961fd87a68SDimitry Andric 
971fd87a68SDimitry Andric } // namespace __distance
981fd87a68SDimitry Andric 
991fd87a68SDimitry Andric inline namespace __cpo {
1001fd87a68SDimitry Andric   inline constexpr auto distance = __distance::__fn{};
1011fd87a68SDimitry Andric } // namespace __cpo
1021fd87a68SDimitry Andric } // namespace ranges
1031fd87a68SDimitry Andric 
104*bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER > 17
1051fd87a68SDimitry Andric 
106fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
107fe6060f1SDimitry Andric 
108fe6060f1SDimitry Andric #endif // _LIBCPP___ITERATOR_DISTANCE_H
109