blob: 002978014cc71e9ec4473c89282124a2eb15bc30 [file] [log] [blame]
Yi Kong878f9942023-12-13 12:55:04 +09001//===----------------------------------------------------------------------===//
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
41template <class _AlgPolicy> struct _IterOps;
42
43#if _LIBCPP_STD_VER >= 20
44struct _RangeAlgPolicy {};
45
46template <>
47struct _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
69struct _ClassicAlgPolicy {};
70
71template <>
72struct _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