libstdc++
refwrap.h
Go to the documentation of this file.
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
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
446  { return __t; }
447 
448  /// std::cref overload to prevent wrapping a reference_wrapper
449  template<typename _Tp>
450  _GLIBCXX20_CONSTEXPR
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
ISO C++ entities toplevel namespace is std.
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
Definition: invoke.h:90
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition: type_traits:114
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:71
constexpr reference_wrapper< const _Tp > cref(const _Tp &__t) noexcept
Denotes a const reference should be taken to a variable.
Definition: refwrap.h:432
Primary class template for reference_wrapper.
Definition: type_traits:70
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:111
constexpr reference_wrapper< _Tp > ref(reference_wrapper< _Tp > __t) noexcept
std::ref overload to prevent wrapping a reference_wrapper
Definition: refwrap.h:445
constexpr reference_wrapper< const _Tp > cref(reference_wrapper< _Tp > __t) noexcept
std::cref overload to prevent wrapping a reference_wrapper
Definition: refwrap.h:452
constexpr reference_wrapper< _Tp > ref(_Tp &__t) noexcept
Denotes a reference should be taken to a variable.
Definition: refwrap.h:425
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:51