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_PUSH_MACROS
37 #include <__undef_macros>
38 
39 _LIBCPP_BEGIN_NAMESPACE_STD
40 
41 template <class _AlgPolicy> struct _IterOps;
42 
43 #if _LIBCPP_STD_VER >= 20
44 struct _RangeAlgPolicy {};
45 
46 template <>
47 struct _IterOps<_RangeAlgPolicy> {
48 
49   template <class _Iter>
50   using __value_type = iter_value_t<_Iter>;
51 
52   template <class _Iter>
53   using __iterator_category = ranges::__iterator_concept<_Iter>;
54 
55   template <class _Iter>
56   using __difference_type = iter_difference_t<_Iter>;
57 
58   static constexpr auto advance = ranges::advance;
59   static constexpr auto distance = ranges::distance;
60   static constexpr auto __iter_move = ranges::iter_move;
61   static constexpr auto iter_swap = ranges::iter_swap;
62   static constexpr auto next = ranges::next;
63   static constexpr auto prev = ranges::prev;
64   static constexpr auto __advance_to = ranges::advance;
65 };
66 
67 #endif
68 
69 struct _ClassicAlgPolicy {};
70 
71 template <>
72 struct _IterOps<_ClassicAlgPolicy> {
73 
74   template <class _Iter>
75   using __value_type = typename iterator_traits<_Iter>::value_type;
76 
77   template <class _Iter>
78   using __iterator_category = typename iterator_traits<_Iter>::iterator_category;
79 
80   template <class _Iter>
81   using __difference_type = typename iterator_traits<_Iter>::difference_type;
82 
83   // advance
84   template <class _Iter, class _Distance>
85   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
86   static void advance(_Iter& __iter, _Distance __count) {
87     std::advance(__iter, __count);
88   }
89 
90   // distance
91   template <class _Iter>
92   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
93   static typename iterator_traits<_Iter>::difference_type distance(_Iter __first, _Iter __last) {
94     return std::distance(__first, __last);
95   }
96 
97   template <class _Iter>
98   using __deref_t = decltype(*std::declval<_Iter&>());
99 
100   template <class _Iter>
101   using __move_t = decltype(std::move(*std::declval<_Iter&>()));
102 
103   template <class _Iter>
104   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
105   static void __validate_iter_reference() {
106     static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__remove_cvref_t<_Iter> >::reference>::value,
107         "It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of "
108         "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] "
109         "and can lead to dangling reference issues at runtime, so we are flagging this.");
110   }
111 
112   // iter_move
113   template <class _Iter>
114   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
115   // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note
116   // that the C++03 mode doesn't support `decltype(auto)` as the return type.
117   __enable_if_t<
118       is_reference<__deref_t<_Iter> >::value,
119       __move_t<_Iter> >
120   __iter_move(_Iter&& __i) {
121     __validate_iter_reference<_Iter>();
122 
123     return std::move(*std::forward<_Iter>(__i));
124   }
125 
126   template <class _Iter>
127   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
128   // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a
129   // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that
130   // temporary. Note that the C++03 mode doesn't support `auto` as the return type.
131   __enable_if_t<
132       !is_reference<__deref_t<_Iter> >::value,
133       __deref_t<_Iter> >
134   __iter_move(_Iter&& __i) {
135     __validate_iter_reference<_Iter>();
136 
137     return *std::forward<_Iter>(__i);
138   }
139 
140   // iter_swap
141   template <class _Iter1, class _Iter2>
142   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
143   static void iter_swap(_Iter1&& __a, _Iter2&& __b) {
144     std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b));
145   }
146 
147   // next
148   template <class _Iterator>
149   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
150   _Iterator next(_Iterator, _Iterator __last) {
151     return __last;
152   }
153 
154   template <class _Iter>
155   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
156   __remove_cvref_t<_Iter> next(_Iter&& __it,
157                           typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
158     return std::next(std::forward<_Iter>(__it), __n);
159   }
160 
161   // prev
162   template <class _Iter>
163   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
164   __remove_cvref_t<_Iter> prev(_Iter&& __iter,
165                  typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
166     return std::prev(std::forward<_Iter>(__iter), __n);
167   }
168 
169   template <class _Iter>
170   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
171   void __advance_to(_Iter& __first, _Iter __last) {
172     __first = __last;
173   }
174 };
175 
176 _LIBCPP_END_NAMESPACE_STD
177 
178 _LIBCPP_POP_MACROS
179 
180 #endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H
181