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