1 | // Implementation of std::reference_wrapper -*- C++ -*- |
2 | |
3 | // Copyright (C) 2004-2024 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file include/bits/refwrap.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{functional} |
28 | */ |
29 | |
30 | #ifndef _GLIBCXX_REFWRAP_H |
31 | #define _GLIBCXX_REFWRAP_H 1 |
32 | |
33 | #pragma GCC system_header |
34 | |
35 | #if __cplusplus >= 201103L |
36 | |
37 | #include <bits/move.h> |
38 | #include <bits/invoke.h> |
39 | #include <bits/stl_function.h> // for unary_function and binary_function |
40 | |
41 | #if __glibcxx_reference_wrapper >= 202403L // >= C++26 |
42 | # include <compare> |
43 | #endif |
44 | |
45 | namespace std _GLIBCXX_VISIBILITY(default) |
46 | { |
47 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
48 | |
49 | /// @cond undocumented |
50 | |
51 | /** |
52 | * Derives from @c unary_function or @c binary_function, or perhaps |
53 | * nothing, depending on the number of arguments provided. The |
54 | * primary template is the basis case, which derives nothing. |
55 | */ |
56 | template<typename _Res, typename... _ArgTypes> |
57 | struct _Maybe_unary_or_binary_function { }; |
58 | |
59 | // Ignore warnings about unary_function and binary_function. |
60 | #pragma GCC diagnostic push |
61 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
62 | |
63 | /// Derives from @c unary_function, as appropriate. |
64 | template<typename _Res, typename _T1> |
65 | struct _Maybe_unary_or_binary_function<_Res, _T1> |
66 | : std::unary_function<_T1, _Res> { }; |
67 | |
68 | /// Derives from @c binary_function, as appropriate. |
69 | template<typename _Res, typename _T1, typename _T2> |
70 | struct _Maybe_unary_or_binary_function<_Res, _T1, _T2> |
71 | : std::binary_function<_T1, _T2, _Res> { }; |
72 | |
73 | #pragma GCC diagnostic pop |
74 | |
75 | template<typename _Signature> |
76 | struct _Mem_fn_traits; |
77 | |
78 | template<typename _Res, typename _Class, typename... _ArgTypes> |
79 | struct _Mem_fn_traits_base |
80 | { |
81 | using __result_type = _Res; |
82 | using __maybe_type |
83 | = _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>; |
84 | using __arity = integral_constant<size_t, sizeof...(_ArgTypes)>; |
85 | }; |
86 | |
87 | #define _GLIBCXX_MEM_FN_TRAITS2(_CV, _REF, _LVAL, _RVAL) \ |
88 | template<typename _Res, typename _Class, typename... _ArgTypes> \ |
89 | struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF> \ |
90 | : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ |
91 | { \ |
92 | using __vararg = false_type; \ |
93 | }; \ |
94 | template<typename _Res, typename _Class, typename... _ArgTypes> \ |
95 | struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \ |
96 | : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ |
97 | { \ |
98 | using __vararg = true_type; \ |
99 | }; |
100 | |
101 | #define _GLIBCXX_MEM_FN_TRAITS(_REF, _LVAL, _RVAL) \ |
102 | _GLIBCXX_MEM_FN_TRAITS2( , _REF, _LVAL, _RVAL) \ |
103 | _GLIBCXX_MEM_FN_TRAITS2(const , _REF, _LVAL, _RVAL) \ |
104 | _GLIBCXX_MEM_FN_TRAITS2(volatile , _REF, _LVAL, _RVAL) \ |
105 | _GLIBCXX_MEM_FN_TRAITS2(const volatile, _REF, _LVAL, _RVAL) |
106 | |
107 | _GLIBCXX_MEM_FN_TRAITS( , true_type, true_type) |
108 | _GLIBCXX_MEM_FN_TRAITS(&, true_type, false_type) |
109 | _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) |
110 | |
111 | #if __cplusplus > 201402L |
112 | _GLIBCXX_MEM_FN_TRAITS(noexcept, true_type, true_type) |
113 | _GLIBCXX_MEM_FN_TRAITS(& noexcept, true_type, false_type) |
114 | _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) |
115 | #endif |
116 | |
117 | #undef _GLIBCXX_MEM_FN_TRAITS |
118 | #undef _GLIBCXX_MEM_FN_TRAITS2 |
119 | |
120 | /// If we have found a result_type, extract it. |
121 | template<typename _Functor, typename = __void_t<>> |
122 | struct _Maybe_get_result_type |
123 | { }; |
124 | |
125 | template<typename _Functor> |
126 | struct _Maybe_get_result_type<_Functor, |
127 | __void_t<typename _Functor::result_type>> |
128 | { typedef typename _Functor::result_type result_type; }; |
129 | |
130 | /** |
131 | * Base class for any function object that has a weak result type, as |
132 | * defined in 20.8.2 [func.require] of C++11. |
133 | */ |
134 | template<typename _Functor> |
135 | struct _Weak_result_type_impl |
136 | : _Maybe_get_result_type<_Functor> |
137 | { }; |
138 | |
139 | /// Retrieve the result type for a function type. |
140 | template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM> |
141 | struct _Weak_result_type_impl<_Res(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> |
142 | { typedef _Res result_type; }; |
143 | |
144 | /// Retrieve the result type for a varargs function type. |
145 | template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM> |
146 | struct _Weak_result_type_impl<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> |
147 | { typedef _Res result_type; }; |
148 | |
149 | /// Retrieve the result type for a function pointer. |
150 | template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM> |
151 | struct _Weak_result_type_impl<_Res(*)(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> |
152 | { typedef _Res result_type; }; |
153 | |
154 | /// Retrieve the result type for a varargs function pointer. |
155 | template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM> |
156 | struct |
157 | _Weak_result_type_impl<_Res(*)(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> |
158 | { typedef _Res result_type; }; |
159 | |
160 | // Let _Weak_result_type_impl perform the real work. |
161 | template<typename _Functor, |
162 | bool = is_member_function_pointer<_Functor>::value> |
163 | struct _Weak_result_type_memfun |
164 | : _Weak_result_type_impl<_Functor> |
165 | { }; |
166 | |
167 | // A pointer to member function has a weak result type. |
168 | template<typename _MemFunPtr> |
169 | struct _Weak_result_type_memfun<_MemFunPtr, true> |
170 | { |
171 | using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; |
172 | }; |
173 | |
174 | // A pointer to data member doesn't have a weak result type. |
175 | template<typename _Func, typename _Class> |
176 | struct _Weak_result_type_memfun<_Func _Class::*, false> |
177 | { }; |
178 | |
179 | /** |
180 | * Strip top-level cv-qualifiers from the function object and let |
181 | * _Weak_result_type_memfun perform the real work. |
182 | */ |
183 | template<typename _Functor> |
184 | struct _Weak_result_type |
185 | : _Weak_result_type_memfun<typename remove_cv<_Functor>::type> |
186 | { }; |
187 | |
188 | #if __cplusplus <= 201703L |
189 | // Detect nested argument_type. |
190 | template<typename _Tp, typename = __void_t<>> |
191 | struct _Refwrap_base_arg1 |
192 | { }; |
193 | |
194 | // Nested argument_type. |
195 | template<typename _Tp> |
196 | struct _Refwrap_base_arg1<_Tp, |
197 | __void_t<typename _Tp::argument_type>> |
198 | { |
199 | typedef typename _Tp::argument_type argument_type; |
200 | }; |
201 | |
202 | // Detect nested first_argument_type and second_argument_type. |
203 | template<typename _Tp, typename = __void_t<>> |
204 | struct _Refwrap_base_arg2 |
205 | { }; |
206 | |
207 | // Nested first_argument_type and second_argument_type. |
208 | template<typename _Tp> |
209 | struct _Refwrap_base_arg2<_Tp, |
210 | __void_t<typename _Tp::first_argument_type, |
211 | typename _Tp::second_argument_type>> |
212 | { |
213 | typedef typename _Tp::first_argument_type first_argument_type; |
214 | typedef typename _Tp::second_argument_type second_argument_type; |
215 | }; |
216 | |
217 | /** |
218 | * Derives from unary_function or binary_function when it |
219 | * can. Specializations handle all of the easy cases. The primary |
220 | * template determines what to do with a class type, which may |
221 | * derive from both unary_function and binary_function. |
222 | */ |
223 | template<typename _Tp> |
224 | struct _Reference_wrapper_base |
225 | : _Weak_result_type<_Tp>, _Refwrap_base_arg1<_Tp>, _Refwrap_base_arg2<_Tp> |
226 | { }; |
227 | |
228 | // Ignore warnings about unary_function and binary_function. |
229 | #pragma GCC diagnostic push |
230 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
231 | |
232 | // - a function type (unary) |
233 | template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM> |
234 | struct _Reference_wrapper_base<_Res(_T1) _GLIBCXX_NOEXCEPT_QUAL> |
235 | : unary_function<_T1, _Res> |
236 | { }; |
237 | |
238 | template<typename _Res, typename _T1> |
239 | struct _Reference_wrapper_base<_Res(_T1) const> |
240 | : unary_function<_T1, _Res> |
241 | { }; |
242 | |
243 | template<typename _Res, typename _T1> |
244 | struct _Reference_wrapper_base<_Res(_T1) volatile> |
245 | : unary_function<_T1, _Res> |
246 | { }; |
247 | |
248 | template<typename _Res, typename _T1> |
249 | struct _Reference_wrapper_base<_Res(_T1) const volatile> |
250 | : unary_function<_T1, _Res> |
251 | { }; |
252 | |
253 | // - a function type (binary) |
254 | template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM> |
255 | struct _Reference_wrapper_base<_Res(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> |
256 | : binary_function<_T1, _T2, _Res> |
257 | { }; |
258 | |
259 | template<typename _Res, typename _T1, typename _T2> |
260 | struct _Reference_wrapper_base<_Res(_T1, _T2) const> |
261 | : binary_function<_T1, _T2, _Res> |
262 | { }; |
263 | |
264 | template<typename _Res, typename _T1, typename _T2> |
265 | struct _Reference_wrapper_base<_Res(_T1, _T2) volatile> |
266 | : binary_function<_T1, _T2, _Res> |
267 | { }; |
268 | |
269 | template<typename _Res, typename _T1, typename _T2> |
270 | struct _Reference_wrapper_base<_Res(_T1, _T2) const volatile> |
271 | : binary_function<_T1, _T2, _Res> |
272 | { }; |
273 | |
274 | // - a function pointer type (unary) |
275 | template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM> |
276 | struct _Reference_wrapper_base<_Res(*)(_T1) _GLIBCXX_NOEXCEPT_QUAL> |
277 | : unary_function<_T1, _Res> |
278 | { }; |
279 | |
280 | // - a function pointer type (binary) |
281 | template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM> |
282 | struct _Reference_wrapper_base<_Res(*)(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> |
283 | : binary_function<_T1, _T2, _Res> |
284 | { }; |
285 | |
286 | template<typename _Tp, bool = is_member_function_pointer<_Tp>::value> |
287 | struct _Reference_wrapper_base_memfun |
288 | : _Reference_wrapper_base<_Tp> |
289 | { }; |
290 | |
291 | template<typename _MemFunPtr> |
292 | struct _Reference_wrapper_base_memfun<_MemFunPtr, true> |
293 | : _Mem_fn_traits<_MemFunPtr>::__maybe_type |
294 | { |
295 | using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; |
296 | }; |
297 | #pragma GCC diagnostic pop |
298 | #endif // ! C++20 |
299 | |
300 | /// @endcond |
301 | |
302 | /** |
303 | * @brief Primary class template for reference_wrapper. |
304 | * @ingroup functors |
305 | */ |
306 | template<typename _Tp> |
307 | class reference_wrapper |
308 | #if __cplusplus <= 201703L |
309 | // In C++20 std::reference_wrapper<T> allows T to be incomplete, |
310 | // so checking for nested types could result in ODR violations. |
311 | : public _Reference_wrapper_base_memfun<typename remove_cv<_Tp>::type> |
312 | #endif |
313 | { |
314 | _Tp* _M_data; |
315 | |
316 | _GLIBCXX20_CONSTEXPR |
317 | static _Tp* _S_fun(_Tp& __r) noexcept { return std::__addressof(__r); } |
318 | |
319 | static void _S_fun(_Tp&&) = delete; |
320 | |
321 | template<typename _Up, typename _Up2 = __remove_cvref_t<_Up>> |
322 | using __not_same |
323 | = typename enable_if<!is_same<reference_wrapper, _Up2>::value>::type; |
324 | |
325 | public: |
326 | typedef _Tp type; |
327 | |
328 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
329 | // 2993. reference_wrapper<T> conversion from T&& |
330 | // 3041. Unnecessary decay in reference_wrapper |
331 | template<typename _Up, typename = __not_same<_Up>, typename |
332 | = decltype(reference_wrapper::_S_fun(std::declval<_Up>()))> |
333 | _GLIBCXX20_CONSTEXPR |
334 | reference_wrapper(_Up&& __uref) |
335 | noexcept(noexcept(reference_wrapper::_S_fun(std::declval<_Up>()))) |
336 | : _M_data(reference_wrapper::_S_fun(std::forward<_Up>(__uref))) |
337 | { } |
338 | |
339 | reference_wrapper(const reference_wrapper&) = default; |
340 | |
341 | reference_wrapper& |
342 | operator=(const reference_wrapper&) = default; |
343 | |
344 | _GLIBCXX20_CONSTEXPR |
345 | operator _Tp&() const noexcept |
346 | { return this->get(); } |
347 | |
348 | _GLIBCXX20_CONSTEXPR |
349 | _Tp& |
350 | get() const noexcept |
351 | { return *_M_data; } |
352 | |
353 | template<typename... _Args> |
354 | _GLIBCXX20_CONSTEXPR |
355 | typename __invoke_result<_Tp&, _Args...>::type |
356 | operator()(_Args&&... __args) const |
357 | noexcept(__is_nothrow_invocable<_Tp&, _Args...>::value) |
358 | { |
359 | #if __cplusplus > 201703L |
360 | if constexpr (is_object_v<type>) |
361 | static_assert(sizeof(type), "type must be complete" ); |
362 | #endif |
363 | return std::__invoke(get(), std::forward<_Args>(__args)...); |
364 | } |
365 | |
366 | #if __glibcxx_reference_wrapper >= 202403L // >= C++26 |
367 | // [refwrap.comparisons], comparisons |
368 | [[nodiscard]] |
369 | friend constexpr bool |
370 | operator==(reference_wrapper __x, reference_wrapper __y) |
371 | requires requires { { __x.get() == __y.get() } -> convertible_to<bool>; } |
372 | { return __x.get() == __y.get(); } |
373 | |
374 | [[nodiscard]] |
375 | friend constexpr bool |
376 | operator==(reference_wrapper __x, const _Tp& __y) |
377 | requires requires { { __x.get() == __y } -> convertible_to<bool>; } |
378 | { return __x.get() == __y; } |
379 | |
380 | [[nodiscard]] |
381 | friend constexpr bool |
382 | operator==(reference_wrapper __x, reference_wrapper<const _Tp> __y) |
383 | requires (!is_const_v<_Tp>) |
384 | && requires { { __x.get() == __y.get() } -> convertible_to<bool>; } |
385 | { return __x.get() == __y.get(); } |
386 | |
387 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
388 | // 4071. reference_wrapper comparisons are not SFINAE-friendly |
389 | |
390 | [[nodiscard]] |
391 | friend constexpr auto |
392 | operator<=>(reference_wrapper __x, reference_wrapper __y) |
393 | requires requires (const _Tp __t) { |
394 | { __t < __t } -> __detail::__boolean_testable; |
395 | } |
396 | { return __detail::__synth3way(__x.get(), __y.get()); } |
397 | |
398 | [[nodiscard]] |
399 | friend constexpr auto |
400 | operator<=>(reference_wrapper __x, const _Tp& __y) |
401 | requires requires { { __y < __y } -> __detail::__boolean_testable; } |
402 | { return __detail::__synth3way(__x.get(), __y); } |
403 | |
404 | [[nodiscard]] |
405 | friend constexpr auto |
406 | operator<=>(reference_wrapper __x, reference_wrapper<const _Tp> __y) |
407 | requires (!is_const_v<_Tp>) && requires (const _Tp __t) { |
408 | { __t < __t } -> __detail::__boolean_testable; |
409 | } |
410 | { return __detail::__synth3way(__x.get(), __y.get()); } |
411 | #endif |
412 | }; |
413 | |
414 | #if __cpp_deduction_guides |
415 | template<typename _Tp> |
416 | reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; |
417 | #endif |
418 | |
419 | /// @relates reference_wrapper @{ |
420 | |
421 | /// Denotes a reference should be taken to a variable. |
422 | template<typename _Tp> |
423 | _GLIBCXX20_CONSTEXPR |
424 | inline reference_wrapper<_Tp> |
425 | ref(_Tp& __t) noexcept |
426 | { return reference_wrapper<_Tp>(__t); } |
427 | |
428 | /// Denotes a const reference should be taken to a variable. |
429 | template<typename _Tp> |
430 | _GLIBCXX20_CONSTEXPR |
431 | inline reference_wrapper<const _Tp> |
432 | cref(const _Tp& __t) noexcept |
433 | { return reference_wrapper<const _Tp>(__t); } |
434 | |
435 | template<typename _Tp> |
436 | void ref(const _Tp&&) = delete; |
437 | |
438 | template<typename _Tp> |
439 | void cref(const _Tp&&) = delete; |
440 | |
441 | /// std::ref overload to prevent wrapping a reference_wrapper |
442 | template<typename _Tp> |
443 | _GLIBCXX20_CONSTEXPR |
444 | inline reference_wrapper<_Tp> |
445 | ref(reference_wrapper<_Tp> __t) noexcept |
446 | { return __t; } |
447 | |
448 | /// std::cref overload to prevent wrapping a reference_wrapper |
449 | template<typename _Tp> |
450 | _GLIBCXX20_CONSTEXPR |
451 | inline reference_wrapper<const _Tp> |
452 | cref(reference_wrapper<_Tp> __t) noexcept |
453 | { return { __t.get() }; } |
454 | |
455 | /// @} |
456 | |
457 | _GLIBCXX_END_NAMESPACE_VERSION |
458 | } // namespace std |
459 | |
460 | #endif // C++11 |
461 | |
462 | #endif // _GLIBCXX_REFWRAP_H |
463 | |