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