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_PSTL_REPLACE_H
10 #define _LIBCPP___ALGORITHM_PSTL_REPLACE_H
11 
12 #include <__algorithm/pstl_backend.h>
13 #include <__algorithm/pstl_for_each.h>
14 #include <__algorithm/pstl_frontend_dispatch.h>
15 #include <__algorithm/pstl_transform.h>
16 #include <__config>
17 #include <__iterator/iterator_traits.h>
18 #include <__type_traits/enable_if.h>
19 #include <__type_traits/remove_cvref.h>
20 #include <__utility/move.h>
21 #include <optional>
22 
23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24 #  pragma GCC system_header
25 #endif
26 
27 _LIBCPP_PUSH_MACROS
28 #include <__undef_macros>
29 
30 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
31 
32 _LIBCPP_BEGIN_NAMESPACE_STD
33 
34 template <class>
35 void __pstl_replace_if();
36 
37 template <class _ExecutionPolicy,
38           class _ForwardIterator,
39           class _Pred,
40           class _Tp,
41           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
42           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
43 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
44 __replace_if(_ExecutionPolicy&& __policy,
45              _ForwardIterator&& __first,
46              _ForwardIterator&& __last,
47              _Pred&& __pred,
48              const _Tp& __new_value) noexcept {
49   return std::__pstl_frontend_dispatch(
50       _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_if, _RawPolicy),
51       [&__policy](
52           _ForwardIterator&& __g_first, _ForwardIterator&& __g_last, _Pred&& __g_pred, const _Tp& __g_new_value) {
53         std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) {
54           if (__g_pred(__element))
55             __element = __g_new_value;
56         });
57         return optional<__empty>{__empty{}};
58       },
59       std::move(__first),
60       std::move(__last),
61       std::move(__pred),
62       __new_value);
63 }
64 
65 template <class _ExecutionPolicy,
66           class _ForwardIterator,
67           class _Pred,
68           class _Tp,
69           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
70           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
71 _LIBCPP_HIDE_FROM_ABI void
72 replace_if(_ExecutionPolicy&& __policy,
73            _ForwardIterator __first,
74            _ForwardIterator __last,
75            _Pred __pred,
76            const _Tp& __new_value) {
77   auto __res = std::__replace_if(__policy, std::move(__first), std::move(__last), std::move(__pred), __new_value);
78   if (!__res)
79     std::__throw_bad_alloc();
80 }
81 
82 template <class>
83 void __pstl_replace();
84 
85 template <class _ExecutionPolicy,
86           class _ForwardIterator,
87           class _Tp,
88           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
89           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
90 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
91 __replace(_ExecutionPolicy&& __policy,
92           _ForwardIterator __first,
93           _ForwardIterator __last,
94           const _Tp& __old_value,
95           const _Tp& __new_value) noexcept {
96   return std::__pstl_frontend_dispatch(
97       _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace, _RawPolicy),
98       [&__policy](
99           _ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_old_value, const _Tp& __g_new_value) {
100         return std::__replace_if(
101             __policy,
102             std::move(__g_first),
103             std::move(__g_last),
104             [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; },
105             __g_new_value);
106       },
107       std::move(__first),
108       std::move(__last),
109       __old_value,
110       __new_value);
111 }
112 
113 template <class _ExecutionPolicy,
114           class _ForwardIterator,
115           class _Tp,
116           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
117           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
118 _LIBCPP_HIDE_FROM_ABI void
119 replace(_ExecutionPolicy&& __policy,
120         _ForwardIterator __first,
121         _ForwardIterator __last,
122         const _Tp& __old_value,
123         const _Tp& __new_value) {
124   if (!std::__replace(__policy, std::move(__first), std::move(__last), __old_value, __new_value))
125     std::__throw_bad_alloc();
126 }
127 
128 template <class>
129 void __pstl_replace_copy_if();
130 
131 template <class _ExecutionPolicy,
132           class _ForwardIterator,
133           class _ForwardOutIterator,
134           class _Pred,
135           class _Tp,
136           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
137           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
138 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __replace_copy_if(
139     _ExecutionPolicy&& __policy,
140     _ForwardIterator&& __first,
141     _ForwardIterator&& __last,
142     _ForwardOutIterator&& __result,
143     _Pred&& __pred,
144     const _Tp& __new_value) {
145   return std::__pstl_frontend_dispatch(
146       _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy_if, _RawPolicy),
147       [&__policy](_ForwardIterator __g_first,
148                   _ForwardIterator __g_last,
149                   _ForwardOutIterator __g_result,
150                   _Pred __g_pred,
151                   const _Tp& __g_new_value) -> optional<__empty> {
152         if (!std::__transform(
153                 __policy, __g_first, __g_last, __g_result, [&](__iter_reference<_ForwardIterator> __element) {
154                   return __g_pred(__element) ? __g_new_value : __element;
155                 }))
156           return nullopt;
157         return __empty{};
158       },
159       std::move(__first),
160       std::move(__last),
161       std::move(__result),
162       std::move(__pred),
163       __new_value);
164 }
165 
166 template <class _ExecutionPolicy,
167           class _ForwardIterator,
168           class _ForwardOutIterator,
169           class _Pred,
170           class _Tp,
171           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
172           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
173 _LIBCPP_HIDE_FROM_ABI void replace_copy_if(
174     _ExecutionPolicy&& __policy,
175     _ForwardIterator __first,
176     _ForwardIterator __last,
177     _ForwardOutIterator __result,
178     _Pred __pred,
179     const _Tp& __new_value) {
180   if (!std::__replace_copy_if(
181           __policy, std::move(__first), std::move(__last), std::move(__result), std::move(__pred), __new_value))
182     std::__throw_bad_alloc();
183 }
184 
185 template <class>
186 void __pstl_replace_copy();
187 
188 template <class _ExecutionPolicy,
189           class _ForwardIterator,
190           class _ForwardOutIterator,
191           class _Tp,
192           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
193           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
194 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __replace_copy(
195     _ExecutionPolicy&& __policy,
196     _ForwardIterator&& __first,
197     _ForwardIterator&& __last,
198     _ForwardOutIterator&& __result,
199     const _Tp& __old_value,
200     const _Tp& __new_value) noexcept {
201   return std::__pstl_frontend_dispatch(
202       _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy, _RawPolicy),
203       [&__policy](_ForwardIterator __g_first,
204                   _ForwardIterator __g_last,
205                   _ForwardOutIterator __g_result,
206                   const _Tp& __g_old_value,
207                   const _Tp& __g_new_value) {
208         return std::__replace_copy_if(
209             __policy,
210             std::move(__g_first),
211             std::move(__g_last),
212             std::move(__g_result),
213             [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; },
214             __g_new_value);
215       },
216       std::move(__first),
217       std::move(__last),
218       std::move(__result),
219       __old_value,
220       __new_value);
221 }
222 
223 template <class _ExecutionPolicy,
224           class _ForwardIterator,
225           class _ForwardOutIterator,
226           class _Tp,
227           class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
228           enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
229 _LIBCPP_HIDE_FROM_ABI void replace_copy(
230     _ExecutionPolicy&& __policy,
231     _ForwardIterator __first,
232     _ForwardIterator __last,
233     _ForwardOutIterator __result,
234     const _Tp& __old_value,
235     const _Tp& __new_value) {
236   if (!std::__replace_copy(
237           __policy, std::move(__first), std::move(__last), std::move(__result), __old_value, __new_value))
238     std::__throw_bad_alloc();
239 }
240 
241 _LIBCPP_END_NAMESPACE_STD
242 
243 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
244 
245 _LIBCPP_POP_MACROS
246 
247 #endif // _LIBCPP___ALGORITHM_PSTL_REPLACE_H
248