Line data Source code
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 3996 : 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 3996 : }
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 3996 : __iter_move(_Iter&& __i) {
118 3996 : __validate_iter_reference<_Iter>();
119 :
120 3996 : 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
|