1 // Implementation of std::reference_wrapper -*- C++ -*-
3 // Copyright (C) 2004-2024 Free Software Foundation, Inc.
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)
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.
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.
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/>.
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}
30 #ifndef _GLIBCXX_REFWRAP_H
31 #define _GLIBCXX_REFWRAP_H 1
33 #pragma GCC system_header
35 #if __cplusplus >= 201103L
37 #include <bits/move.h>
38 #include <bits/invoke.h>
39 #include <bits/stl_function.h> // for unary_function and binary_function
41 #if __glibcxx_reference_wrapper >= 202403L // >= C++26
45 namespace std
_GLIBCXX_VISIBILITY(default)
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49 /// @cond undocumented
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.
56 template<typename _Res
, typename
... _ArgTypes
>
57 struct _Maybe_unary_or_binary_function
{ };
59 // Ignore warnings about unary_function and binary_function.
60 #pragma GCC diagnostic push
61 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
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
> { };
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
> { };
73 #pragma GCC diagnostic pop
75 template<typename _Signature
>
76 struct _Mem_fn_traits
;
78 template<typename _Res
, typename _Class
, typename
... _ArgTypes
>
79 struct _Mem_fn_traits_base
81 using __result_type
= _Res
;
83 = _Maybe_unary_or_binary_function
<_Res
, _Class
*, _ArgTypes
...>;
84 using __arity
= integral_constant
<size_t, sizeof...(_ArgTypes
)>;
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...> \
92 using __vararg = false_type; \
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...> \
98 using __vararg = true_type; \
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)
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
)
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
)
117 #undef _GLIBCXX_MEM_FN_TRAITS
118 #undef _GLIBCXX_MEM_FN_TRAITS2
120 /// If we have found a result_type, extract it.
121 template<typename _Functor
, typename
= __void_t
<>>
122 struct _Maybe_get_result_type
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
; };
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.
134 template<typename _Functor
>
135 struct _Weak_result_type_impl
136 : _Maybe_get_result_type
<_Functor
>
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
; };
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
; };
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
; };
154 /// Retrieve the result type for a varargs function pointer.
155 template<typename _Res
, typename
... _ArgTypes _GLIBCXX_NOEXCEPT_PARM
>
157 _Weak_result_type_impl
<_Res(*)(_ArgTypes
......) _GLIBCXX_NOEXCEPT_QUAL
>
158 { typedef _Res result_type
; };
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
>
167 // A pointer to member function has a weak result type.
168 template<typename _MemFunPtr
>
169 struct _Weak_result_type_memfun
<_MemFunPtr
, true>
171 using result_type
= typename _Mem_fn_traits
<_MemFunPtr
>::__result_type
;
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>
180 * Strip top-level cv-qualifiers from the function object and let
181 * _Weak_result_type_memfun perform the real work.
183 template<typename _Functor
>
184 struct _Weak_result_type
185 : _Weak_result_type_memfun
<typename remove_cv
<_Functor
>::type
>
188 #if __cplusplus <= 201703L
189 // Detect nested argument_type.
190 template<typename _Tp
, typename
= __void_t
<>>
191 struct _Refwrap_base_arg1
194 // Nested argument_type.
195 template<typename _Tp
>
196 struct _Refwrap_base_arg1
<_Tp
,
197 __void_t
<typename
_Tp::argument_type
>>
199 typedef typename
_Tp::argument_type argument_type
;
202 // Detect nested first_argument_type and second_argument_type.
203 template<typename _Tp
, typename
= __void_t
<>>
204 struct _Refwrap_base_arg2
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
>>
213 typedef typename
_Tp::first_argument_type first_argument_type
;
214 typedef typename
_Tp::second_argument_type second_argument_type
;
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.
223 template<typename _Tp
>
224 struct _Reference_wrapper_base
225 : _Weak_result_type
<_Tp
>, _Refwrap_base_arg1
<_Tp
>, _Refwrap_base_arg2
<_Tp
>
228 // Ignore warnings about unary_function and binary_function.
229 #pragma GCC diagnostic push
230 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
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
>
238 template<typename _Res
, typename _T1
>
239 struct _Reference_wrapper_base
<_Res(_T1
) const>
240 : unary_function
<_T1
, _Res
>
243 template<typename _Res
, typename _T1
>
244 struct _Reference_wrapper_base
<_Res(_T1
) volatile>
245 : unary_function
<_T1
, _Res
>
248 template<typename _Res
, typename _T1
>
249 struct _Reference_wrapper_base
<_Res(_T1
) const volatile>
250 : unary_function
<_T1
, _Res
>
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
>
259 template<typename _Res
, typename _T1
, typename _T2
>
260 struct _Reference_wrapper_base
<_Res(_T1
, _T2
) const>
261 : binary_function
<_T1
, _T2
, _Res
>
264 template<typename _Res
, typename _T1
, typename _T2
>
265 struct _Reference_wrapper_base
<_Res(_T1
, _T2
) volatile>
266 : binary_function
<_T1
, _T2
, _Res
>
269 template<typename _Res
, typename _T1
, typename _T2
>
270 struct _Reference_wrapper_base
<_Res(_T1
, _T2
) const volatile>
271 : binary_function
<_T1
, _T2
, _Res
>
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
>
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
>
286 template<typename _Tp
, bool = is_member_function_pointer
<_Tp
>::value
>
287 struct _Reference_wrapper_base_memfun
288 : _Reference_wrapper_base
<_Tp
>
291 template<typename _MemFunPtr
>
292 struct _Reference_wrapper_base_memfun
<_MemFunPtr
, true>
293 : _Mem_fn_traits
<_MemFunPtr
>::__maybe_type
295 using result_type
= typename _Mem_fn_traits
<_MemFunPtr
>::__result_type
;
297 #pragma GCC diagnostic pop
303 * @brief Primary class template for reference_wrapper.
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
>
317 static _Tp
* _S_fun(_Tp
& __r
) noexcept
{ return std::__addressof(__r
); }
319 static void _S_fun(_Tp
&&) = delete;
321 template<typename _Up
, typename _Up2
= __remove_cvref_t
<_Up
>>
323 = typename enable_if
<!is_same
<reference_wrapper
, _Up2
>::value
>::type
;
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
>()))>
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
)))
339 reference_wrapper(const reference_wrapper
&) = default;
342 operator=(const reference_wrapper
&) = default;
345 operator _Tp
&() const noexcept
346 { return this->get(); }
353 template<typename
... _Args
>
355 typename __invoke_result
<_Tp
&, _Args
...>::type
356 operator()(_Args
&&... __args
) const
357 noexcept(__is_nothrow_invocable
<_Tp
&, _Args
...>::value
)
359 #if __cplusplus > 201703L
360 if constexpr (is_object_v
<type
>)
361 static_assert(sizeof(type
), "type must be complete");
363 return std::__invoke(get(), std::forward
<_Args
>(__args
)...);
366 #if __glibcxx_reference_wrapper >= 202403L // >= C++26
367 // [refwrap.comparisons], comparisons
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(); }
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
; }
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(); }
387 // _GLIBCXX_RESOLVE_LIB_DEFECTS
388 // 4071. reference_wrapper comparisons are not SFINAE-friendly
391 friend constexpr auto
392 operator<=>(reference_wrapper __x
, reference_wrapper __y
)
393 requires
requires (const _Tp __t
) {
394 { __t
< __t
} -> __detail::__boolean_testable
;
396 { return __detail::__synth3way(__x
.get(), __y
.get()); }
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
); }
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
;
410 { return __detail::__synth3way(__x
.get(), __y
.get()); }
414 #if __cpp_deduction_guides
415 template<typename _Tp
>
416 reference_wrapper(_Tp
&) -> reference_wrapper
<_Tp
>;
419 /// @relates reference_wrapper @{
421 /// Denotes a reference should be taken to a variable.
422 template<typename _Tp
>
424 inline reference_wrapper
<_Tp
>
425 ref(_Tp
& __t
) noexcept
426 { return reference_wrapper
<_Tp
>(__t
); }
428 /// Denotes a const reference should be taken to a variable.
429 template<typename _Tp
>
431 inline reference_wrapper
<const _Tp
>
432 cref(const _Tp
& __t
) noexcept
433 { return reference_wrapper
<const _Tp
>(__t
); }
435 template<typename _Tp
>
436 void ref(const _Tp
&&) = delete;
438 template<typename _Tp
>
439 void cref(const _Tp
&&) = delete;
441 /// std::ref overload to prevent wrapping a reference_wrapper
442 template<typename _Tp
>
444 inline reference_wrapper
<_Tp
>
445 ref(reference_wrapper
<_Tp
> __t
) noexcept
448 /// std::cref overload to prevent wrapping a reference_wrapper
449 template<typename _Tp
>
451 inline reference_wrapper
<const _Tp
>
452 cref(reference_wrapper
<_Tp
> __t
) noexcept
453 { return { __t
.get() }; }
457 _GLIBCXX_END_NAMESPACE_VERSION
462 #endif // _GLIBCXX_REFWRAP_H