xref: /llvm-project/libcxx/include/__iterator/next.h (revision e9c0c6604e47a7cda323544217c056f7f5aec888)
1857fa7b7SChristopher Di Bella // -*- C++ -*-
2857fa7b7SChristopher Di Bella //===----------------------------------------------------------------------===//
3857fa7b7SChristopher Di Bella //
4857fa7b7SChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5857fa7b7SChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
6857fa7b7SChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7857fa7b7SChristopher Di Bella //
8857fa7b7SChristopher Di Bella //===----------------------------------------------------------------------===//
9857fa7b7SChristopher Di Bella 
10857fa7b7SChristopher Di Bella #ifndef _LIBCPP___ITERATOR_NEXT_H
11857fa7b7SChristopher Di Bella #define _LIBCPP___ITERATOR_NEXT_H
12857fa7b7SChristopher Di Bella 
13f87aa19bSLouis Dionne #include <__assert>
14857fa7b7SChristopher Di Bella #include <__config>
15857fa7b7SChristopher Di Bella #include <__iterator/advance.h>
16857fa7b7SChristopher Di Bella #include <__iterator/concepts.h>
17857fa7b7SChristopher Di Bella #include <__iterator/incrementable_traits.h>
18332da1c2SChristopher Di Bella #include <__iterator/iterator_traits.h>
19e0a66116SNikolas Klauser #include <__type_traits/enable_if.h>
20857fa7b7SChristopher Di Bella 
21857fa7b7SChristopher Di Bella #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22857fa7b7SChristopher Di Bella #  pragma GCC system_header
23857fa7b7SChristopher Di Bella #endif
24857fa7b7SChristopher Di Bella 
25857fa7b7SChristopher Di Bella _LIBCPP_BEGIN_NAMESPACE_STD
26857fa7b7SChristopher Di Bella 
27475bd19eSNikolas Klauser template <class _InputIter, __enable_if_t<__has_input_iterator_category<_InputIter>::value, int> = 0>
28*e9c0c660SMarc Auberer [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _InputIter
29bf92bdadSChristopher Di Bella next(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) {
304f215fddSKonstantin Varlamov   // Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation.
314f215fddSKonstantin Varlamov   // Note that this check duplicates the similar check in `std::advance`.
324f215fddSKonstantin Varlamov   _LIBCPP_ASSERT_PEDANTIC(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value,
33bf92bdadSChristopher Di Bella                           "Attempt to next(it, n) with negative n on a non-bidirectional iterator");
34bf92bdadSChristopher Di Bella 
3577a00c0dSLouis Dionne   std::advance(__x, __n);
36bf92bdadSChristopher Di Bella   return __x;
37bf92bdadSChristopher Di Bella }
38bf92bdadSChristopher Di Bella 
394f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20
40857fa7b7SChristopher Di Bella 
416ce732cbSArthur O'Dwyer // [range.iter.op.next]
426ce732cbSArthur O'Dwyer 
43857fa7b7SChristopher Di Bella namespace ranges {
44d10dc5a0SChristopher Di Bella struct __next {
45857fa7b7SChristopher Di Bella   template <input_or_output_iterator _Ip>
46*e9c0c660SMarc Auberer   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __x) const {
47857fa7b7SChristopher Di Bella     ++__x;
48857fa7b7SChristopher Di Bella     return __x;
49857fa7b7SChristopher Di Bella   }
50857fa7b7SChristopher Di Bella 
51857fa7b7SChristopher Di Bella   template <input_or_output_iterator _Ip>
52*e9c0c660SMarc Auberer   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n) const {
53857fa7b7SChristopher Di Bella     ranges::advance(__x, __n);
54857fa7b7SChristopher Di Bella     return __x;
55857fa7b7SChristopher Di Bella   }
56857fa7b7SChristopher Di Bella 
57857fa7b7SChristopher Di Bella   template <input_or_output_iterator _Ip, sentinel_for<_Ip> _Sp>
58*e9c0c660SMarc Auberer   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __x, _Sp __bound_sentinel) const {
595a4f177cSPeter Kasting     ranges::advance(__x, __bound_sentinel);
60857fa7b7SChristopher Di Bella     return __x;
61857fa7b7SChristopher Di Bella   }
62857fa7b7SChristopher Di Bella 
63857fa7b7SChristopher Di Bella   template <input_or_output_iterator _Ip, sentinel_for<_Ip> _Sp>
64*e9c0c660SMarc Auberer   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip
65*e9c0c660SMarc Auberer   operator()(_Ip __x, iter_difference_t<_Ip> __n, _Sp __bound_sentinel) const {
665a4f177cSPeter Kasting     ranges::advance(__x, __n, __bound_sentinel);
67857fa7b7SChristopher Di Bella     return __x;
68857fa7b7SChristopher Di Bella   }
69857fa7b7SChristopher Di Bella };
70857fa7b7SChristopher Di Bella 
716ce732cbSArthur O'Dwyer inline namespace __cpo {
72d10dc5a0SChristopher Di Bella inline constexpr auto next = __next{};
736ce732cbSArthur O'Dwyer } // namespace __cpo
74857fa7b7SChristopher Di Bella } // namespace ranges
75857fa7b7SChristopher Di Bella 
764f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20
77857fa7b7SChristopher Di Bella 
78857fa7b7SChristopher Di Bella _LIBCPP_END_NAMESPACE_STD
79857fa7b7SChristopher Di Bella 
800b609efdSArthur O'Dwyer #endif // _LIBCPP___ITERATOR_NEXT_H
81