xref: /openbsd-src/gnu/llvm/libcxx/include/__algorithm/iterator_operations.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
1*4bdff4beSrobert //===----------------------------------------------------------------------===//
2*4bdff4beSrobert //
3*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information.
5*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4bdff4beSrobert //
7*4bdff4beSrobert //===----------------------------------------------------------------------===//
8*4bdff4beSrobert 
9*4bdff4beSrobert #ifndef _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H
10*4bdff4beSrobert #define _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H
11*4bdff4beSrobert 
12*4bdff4beSrobert #include <__algorithm/iter_swap.h>
13*4bdff4beSrobert #include <__algorithm/ranges_iterator_concept.h>
14*4bdff4beSrobert #include <__config>
15*4bdff4beSrobert #include <__iterator/advance.h>
16*4bdff4beSrobert #include <__iterator/distance.h>
17*4bdff4beSrobert #include <__iterator/incrementable_traits.h>
18*4bdff4beSrobert #include <__iterator/iter_move.h>
19*4bdff4beSrobert #include <__iterator/iter_swap.h>
20*4bdff4beSrobert #include <__iterator/iterator_traits.h>
21*4bdff4beSrobert #include <__iterator/next.h>
22*4bdff4beSrobert #include <__iterator/prev.h>
23*4bdff4beSrobert #include <__iterator/readable_traits.h>
24*4bdff4beSrobert #include <__type_traits/enable_if.h>
25*4bdff4beSrobert #include <__type_traits/is_reference.h>
26*4bdff4beSrobert #include <__type_traits/is_same.h>
27*4bdff4beSrobert #include <__type_traits/remove_cvref.h>
28*4bdff4beSrobert #include <__utility/declval.h>
29*4bdff4beSrobert #include <__utility/forward.h>
30*4bdff4beSrobert #include <__utility/move.h>
31*4bdff4beSrobert 
32*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
33*4bdff4beSrobert #  pragma GCC system_header
34*4bdff4beSrobert #endif
35*4bdff4beSrobert 
36*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
37*4bdff4beSrobert 
38*4bdff4beSrobert template <class _AlgPolicy> struct _IterOps;
39*4bdff4beSrobert 
40*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
41*4bdff4beSrobert struct _RangeAlgPolicy {};
42*4bdff4beSrobert 
43*4bdff4beSrobert template <>
44*4bdff4beSrobert struct _IterOps<_RangeAlgPolicy> {
45*4bdff4beSrobert 
46*4bdff4beSrobert   template <class _Iter>
47*4bdff4beSrobert   using __value_type = iter_value_t<_Iter>;
48*4bdff4beSrobert 
49*4bdff4beSrobert   template <class _Iter>
50*4bdff4beSrobert   using __iterator_category = ranges::__iterator_concept<_Iter>;
51*4bdff4beSrobert 
52*4bdff4beSrobert   template <class _Iter>
53*4bdff4beSrobert   using __difference_type = iter_difference_t<_Iter>;
54*4bdff4beSrobert 
55*4bdff4beSrobert   static constexpr auto advance = ranges::advance;
56*4bdff4beSrobert   static constexpr auto distance = ranges::distance;
57*4bdff4beSrobert   static constexpr auto __iter_move = ranges::iter_move;
58*4bdff4beSrobert   static constexpr auto iter_swap = ranges::iter_swap;
59*4bdff4beSrobert   static constexpr auto next = ranges::next;
60*4bdff4beSrobert   static constexpr auto prev = ranges::prev;
61*4bdff4beSrobert   static constexpr auto __advance_to = ranges::advance;
62*4bdff4beSrobert };
63*4bdff4beSrobert 
64*4bdff4beSrobert #endif
65*4bdff4beSrobert 
66*4bdff4beSrobert struct _ClassicAlgPolicy {};
67*4bdff4beSrobert 
68*4bdff4beSrobert template <>
69*4bdff4beSrobert struct _IterOps<_ClassicAlgPolicy> {
70*4bdff4beSrobert 
71*4bdff4beSrobert   template <class _Iter>
72*4bdff4beSrobert   using __value_type = typename iterator_traits<_Iter>::value_type;
73*4bdff4beSrobert 
74*4bdff4beSrobert   template <class _Iter>
75*4bdff4beSrobert   using __iterator_category = typename iterator_traits<_Iter>::iterator_category;
76*4bdff4beSrobert 
77*4bdff4beSrobert   template <class _Iter>
78*4bdff4beSrobert   using __difference_type = typename iterator_traits<_Iter>::difference_type;
79*4bdff4beSrobert 
80*4bdff4beSrobert   // advance
81*4bdff4beSrobert   template <class _Iter, class _Distance>
82*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
83*4bdff4beSrobert   static void advance(_Iter& __iter, _Distance __count) {
84*4bdff4beSrobert     std::advance(__iter, __count);
85*4bdff4beSrobert   }
86*4bdff4beSrobert 
87*4bdff4beSrobert   // distance
88*4bdff4beSrobert   template <class _Iter>
89*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
90*4bdff4beSrobert   static typename iterator_traits<_Iter>::difference_type distance(_Iter __first, _Iter __last) {
91*4bdff4beSrobert     return std::distance(__first, __last);
92*4bdff4beSrobert   }
93*4bdff4beSrobert 
94*4bdff4beSrobert   template <class _Iter>
95*4bdff4beSrobert   using __deref_t = decltype(*std::declval<_Iter&>());
96*4bdff4beSrobert 
97*4bdff4beSrobert   template <class _Iter>
98*4bdff4beSrobert   using __move_t = decltype(std::move(*std::declval<_Iter&>()));
99*4bdff4beSrobert 
100*4bdff4beSrobert   template <class _Iter>
101*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
102*4bdff4beSrobert   static void __validate_iter_reference() {
103*4bdff4beSrobert     static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__remove_cvref_t<_Iter> >::reference>::value,
104*4bdff4beSrobert         "It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of "
105*4bdff4beSrobert         "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] "
106*4bdff4beSrobert         "and can lead to dangling reference issues at runtime, so we are flagging this.");
107*4bdff4beSrobert   }
108*4bdff4beSrobert 
109*4bdff4beSrobert   // iter_move
110*4bdff4beSrobert   template <class _Iter>
111*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
112*4bdff4beSrobert   // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note
113*4bdff4beSrobert   // that the C++03 mode doesn't support `decltype(auto)` as the return type.
114*4bdff4beSrobert   __enable_if_t<
115*4bdff4beSrobert       is_reference<__deref_t<_Iter> >::value,
116*4bdff4beSrobert       __move_t<_Iter> >
117*4bdff4beSrobert   __iter_move(_Iter&& __i) {
118*4bdff4beSrobert     __validate_iter_reference<_Iter>();
119*4bdff4beSrobert 
120*4bdff4beSrobert     return std::move(*std::forward<_Iter>(__i));
121*4bdff4beSrobert   }
122*4bdff4beSrobert 
123*4bdff4beSrobert   template <class _Iter>
124*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
125*4bdff4beSrobert   // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a
126*4bdff4beSrobert   // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that
127*4bdff4beSrobert   // temporary. Note that the C++03 mode doesn't support `auto` as the return type.
128*4bdff4beSrobert   __enable_if_t<
129*4bdff4beSrobert       !is_reference<__deref_t<_Iter> >::value,
130*4bdff4beSrobert       __deref_t<_Iter> >
131*4bdff4beSrobert   __iter_move(_Iter&& __i) {
132*4bdff4beSrobert     __validate_iter_reference<_Iter>();
133*4bdff4beSrobert 
134*4bdff4beSrobert     return *std::forward<_Iter>(__i);
135*4bdff4beSrobert   }
136*4bdff4beSrobert 
137*4bdff4beSrobert   // iter_swap
138*4bdff4beSrobert   template <class _Iter1, class _Iter2>
139*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
140*4bdff4beSrobert   static void iter_swap(_Iter1&& __a, _Iter2&& __b) {
141*4bdff4beSrobert     std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b));
142*4bdff4beSrobert   }
143*4bdff4beSrobert 
144*4bdff4beSrobert   // next
145*4bdff4beSrobert   template <class _Iterator>
146*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
147*4bdff4beSrobert   _Iterator next(_Iterator, _Iterator __last) {
148*4bdff4beSrobert     return __last;
149*4bdff4beSrobert   }
150*4bdff4beSrobert 
151*4bdff4beSrobert   template <class _Iter>
152*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
153*4bdff4beSrobert   __remove_cvref_t<_Iter> next(_Iter&& __it,
154*4bdff4beSrobert                           typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
155*4bdff4beSrobert     return std::next(std::forward<_Iter>(__it), __n);
156*4bdff4beSrobert   }
157*4bdff4beSrobert 
158*4bdff4beSrobert   // prev
159*4bdff4beSrobert   template <class _Iter>
160*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
161*4bdff4beSrobert   __remove_cvref_t<_Iter> prev(_Iter&& __iter,
162*4bdff4beSrobert                  typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
163*4bdff4beSrobert     return std::prev(std::forward<_Iter>(__iter), __n);
164*4bdff4beSrobert   }
165*4bdff4beSrobert 
166*4bdff4beSrobert   template <class _Iter>
167*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
168*4bdff4beSrobert   void __advance_to(_Iter& __first, _Iter __last) {
169*4bdff4beSrobert     __first = __last;
170*4bdff4beSrobert   }
171*4bdff4beSrobert };
172*4bdff4beSrobert 
173*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
174*4bdff4beSrobert 
175*4bdff4beSrobert #endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H
176