Line data Source code
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 0 : __distance(_RandIter __first, _RandIter __last, random_access_iterator_tag)
44 : {
45 0 : 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 0 : distance(_InputIter __first, _InputIter __last)
52 : {
53 0 : return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category());
54 : }
55 :
56 : #if _LIBCPP_STD_VER > 17
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 > 17
105 :
106 : _LIBCPP_END_NAMESPACE_STD
107 :
108 : #endif // _LIBCPP___ITERATOR_DISTANCE_H
|