236
|
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>
|
252
|
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>
|
236
|
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
|
252
|
36 _LIBCPP_PUSH_MACROS
|
|
37 #include <__undef_macros>
|
|
38
|
236
|
39 _LIBCPP_BEGIN_NAMESPACE_STD
|
|
40
|
|
41 template <class _AlgPolicy> struct _IterOps;
|
|
42
|
252
|
43 #if _LIBCPP_STD_VER >= 20
|
236
|
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
|
252
|
178 _LIBCPP_POP_MACROS
|
|
179
|
236
|
180 #endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H
|