xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/bits/refwrap.h (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 // Implementation of std::reference_wrapper -*- C++ -*-
2 
3 // Copyright (C) 2004-2020 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 # include <bits/c++0x_warning.h>
37 #else
38 
39 #include <bits/move.h>
40 #include <bits/invoke.h>
41 #include <bits/stl_function.h> // for unary_function and binary_function
42 
_GLIBCXX_VISIBILITY(default)43 namespace std _GLIBCXX_VISIBILITY(default)
44 {
45 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 
47   /// @cond undocumented
48 
49   /**
50    * Derives from @c unary_function or @c binary_function, or perhaps
51    * nothing, depending on the number of arguments provided. The
52    * primary template is the basis case, which derives nothing.
53    */
54   template<typename _Res, typename... _ArgTypes>
55     struct _Maybe_unary_or_binary_function { };
56 
57   /// Derives from @c unary_function, as appropriate.
58   template<typename _Res, typename _T1>
59     struct _Maybe_unary_or_binary_function<_Res, _T1>
60     : std::unary_function<_T1, _Res> { };
61 
62   /// Derives from @c binary_function, as appropriate.
63   template<typename _Res, typename _T1, typename _T2>
64     struct _Maybe_unary_or_binary_function<_Res, _T1, _T2>
65     : std::binary_function<_T1, _T2, _Res> { };
66 
67   template<typename _Signature>
68     struct _Mem_fn_traits;
69 
70   template<typename _Res, typename _Class, typename... _ArgTypes>
71     struct _Mem_fn_traits_base
72     {
73       using __result_type = _Res;
74       using __maybe_type
75 	= _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>;
76       using __arity = integral_constant<size_t, sizeof...(_ArgTypes)>;
77     };
78 
79 #define _GLIBCXX_MEM_FN_TRAITS2(_CV, _REF, _LVAL, _RVAL)		\
80   template<typename _Res, typename _Class, typename... _ArgTypes>	\
81     struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF>	\
82     : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...>		\
83     {									\
84       using __vararg = false_type;					\
85     };									\
86   template<typename _Res, typename _Class, typename... _ArgTypes>	\
87     struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF>	\
88     : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...>		\
89     {									\
90       using __vararg = true_type;					\
91     };
92 
93 #define _GLIBCXX_MEM_FN_TRAITS(_REF, _LVAL, _RVAL)		\
94   _GLIBCXX_MEM_FN_TRAITS2(		, _REF, _LVAL, _RVAL)	\
95   _GLIBCXX_MEM_FN_TRAITS2(const		, _REF, _LVAL, _RVAL)	\
96   _GLIBCXX_MEM_FN_TRAITS2(volatile	, _REF, _LVAL, _RVAL)	\
97   _GLIBCXX_MEM_FN_TRAITS2(const volatile, _REF, _LVAL, _RVAL)
98 
99 _GLIBCXX_MEM_FN_TRAITS( , true_type, true_type)
100 _GLIBCXX_MEM_FN_TRAITS(&, true_type, false_type)
101 _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
102 
103 #if __cplusplus > 201402L
104 _GLIBCXX_MEM_FN_TRAITS(noexcept, true_type, true_type)
105 _GLIBCXX_MEM_FN_TRAITS(& noexcept, true_type, false_type)
106 _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
107 #endif
108 
109 #undef _GLIBCXX_MEM_FN_TRAITS
110 #undef _GLIBCXX_MEM_FN_TRAITS2
111 
112   /// If we have found a result_type, extract it.
113   template<typename _Functor, typename = __void_t<>>
114     struct _Maybe_get_result_type
115     { };
116 
117   template<typename _Functor>
118     struct _Maybe_get_result_type<_Functor,
119 				  __void_t<typename _Functor::result_type>>
120     { typedef typename _Functor::result_type result_type; };
121 
122   /**
123    *  Base class for any function object that has a weak result type, as
124    *  defined in 20.8.2 [func.require] of C++11.
125   */
126   template<typename _Functor>
127     struct _Weak_result_type_impl
128     : _Maybe_get_result_type<_Functor>
129     { };
130 
131   /// Retrieve the result type for a function type.
132   template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
133     struct _Weak_result_type_impl<_Res(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL>
134     { typedef _Res result_type; };
135 
136   /// Retrieve the result type for a varargs function type.
137   template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
138     struct _Weak_result_type_impl<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL>
139     { typedef _Res result_type; };
140 
141   /// Retrieve the result type for a function pointer.
142   template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
143     struct _Weak_result_type_impl<_Res(*)(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL>
144     { typedef _Res result_type; };
145 
146   /// Retrieve the result type for a varargs function pointer.
147   template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
148     struct
149     _Weak_result_type_impl<_Res(*)(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL>
150     { typedef _Res result_type; };
151 
152   // Let _Weak_result_type_impl perform the real work.
153   template<typename _Functor,
154 	   bool = is_member_function_pointer<_Functor>::value>
155     struct _Weak_result_type_memfun
156     : _Weak_result_type_impl<_Functor>
157     { };
158 
159   // A pointer to member function has a weak result type.
160   template<typename _MemFunPtr>
161     struct _Weak_result_type_memfun<_MemFunPtr, true>
162     {
163       using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type;
164     };
165 
166   // A pointer to data member doesn't have a weak result type.
167   template<typename _Func, typename _Class>
168     struct _Weak_result_type_memfun<_Func _Class::*, false>
169     { };
170 
171   /**
172    *  Strip top-level cv-qualifiers from the function object and let
173    *  _Weak_result_type_memfun perform the real work.
174   */
175   template<typename _Functor>
176     struct _Weak_result_type
177     : _Weak_result_type_memfun<typename remove_cv<_Functor>::type>
178     { };
179 
180 #if __cplusplus <= 201703L
181   // Detect nested argument_type.
182   template<typename _Tp, typename = __void_t<>>
183     struct _Refwrap_base_arg1
184     { };
185 
186   // Nested argument_type.
187   template<typename _Tp>
188     struct _Refwrap_base_arg1<_Tp,
189 			      __void_t<typename _Tp::argument_type>>
190     {
191       typedef typename _Tp::argument_type argument_type;
192     };
193 
194   // Detect nested first_argument_type and second_argument_type.
195   template<typename _Tp, typename = __void_t<>>
196     struct _Refwrap_base_arg2
197     { };
198 
199   // Nested first_argument_type and second_argument_type.
200   template<typename _Tp>
201     struct _Refwrap_base_arg2<_Tp,
202 			      __void_t<typename _Tp::first_argument_type,
203 				       typename _Tp::second_argument_type>>
204     {
205       typedef typename _Tp::first_argument_type first_argument_type;
206       typedef typename _Tp::second_argument_type second_argument_type;
207     };
208 
209   /**
210    *  Derives from unary_function or binary_function when it
211    *  can. Specializations handle all of the easy cases. The primary
212    *  template determines what to do with a class type, which may
213    *  derive from both unary_function and binary_function.
214   */
215   template<typename _Tp>
216     struct _Reference_wrapper_base
217     : _Weak_result_type<_Tp>, _Refwrap_base_arg1<_Tp>, _Refwrap_base_arg2<_Tp>
218     { };
219 
220   // - a function type (unary)
221   template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM>
222     struct _Reference_wrapper_base<_Res(_T1) _GLIBCXX_NOEXCEPT_QUAL>
223     : unary_function<_T1, _Res>
224     { };
225 
226   template<typename _Res, typename _T1>
227     struct _Reference_wrapper_base<_Res(_T1) const>
228     : unary_function<_T1, _Res>
229     { };
230 
231   template<typename _Res, typename _T1>
232     struct _Reference_wrapper_base<_Res(_T1) volatile>
233     : unary_function<_T1, _Res>
234     { };
235 
236   template<typename _Res, typename _T1>
237     struct _Reference_wrapper_base<_Res(_T1) const volatile>
238     : unary_function<_T1, _Res>
239     { };
240 
241   // - a function type (binary)
242   template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM>
243     struct _Reference_wrapper_base<_Res(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL>
244     : binary_function<_T1, _T2, _Res>
245     { };
246 
247   template<typename _Res, typename _T1, typename _T2>
248     struct _Reference_wrapper_base<_Res(_T1, _T2) const>
249     : binary_function<_T1, _T2, _Res>
250     { };
251 
252   template<typename _Res, typename _T1, typename _T2>
253     struct _Reference_wrapper_base<_Res(_T1, _T2) volatile>
254     : binary_function<_T1, _T2, _Res>
255     { };
256 
257   template<typename _Res, typename _T1, typename _T2>
258     struct _Reference_wrapper_base<_Res(_T1, _T2) const volatile>
259     : binary_function<_T1, _T2, _Res>
260     { };
261 
262   // - a function pointer type (unary)
263   template<typename _Res, typename _T1 _GLIBCXX_NOEXCEPT_PARM>
264     struct _Reference_wrapper_base<_Res(*)(_T1) _GLIBCXX_NOEXCEPT_QUAL>
265     : unary_function<_T1, _Res>
266     { };
267 
268   // - a function pointer type (binary)
269   template<typename _Res, typename _T1, typename _T2 _GLIBCXX_NOEXCEPT_PARM>
270     struct _Reference_wrapper_base<_Res(*)(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL>
271     : binary_function<_T1, _T2, _Res>
272     { };
273 
274   template<typename _Tp, bool = is_member_function_pointer<_Tp>::value>
275     struct _Reference_wrapper_base_memfun
276     : _Reference_wrapper_base<_Tp>
277     { };
278 
279   template<typename _MemFunPtr>
280     struct _Reference_wrapper_base_memfun<_MemFunPtr, true>
281     : _Mem_fn_traits<_MemFunPtr>::__maybe_type
282     {
283       using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type;
284     };
285 #endif // ! C++20
286 
287   /// @endcond
288 
289   /**
290    *  @brief Primary class template for reference_wrapper.
291    *  @ingroup functors
292    */
293   template<typename _Tp>
294     class reference_wrapper
295 #if __cplusplus <= 201703L
296     // In C++20 std::reference_wrapper<T> allows T to be incomplete,
297     // so checking for nested types could result in ODR violations.
298     : public _Reference_wrapper_base_memfun<typename remove_cv<_Tp>::type>
299 #endif
300     {
301       _Tp* _M_data;
302 
303       _GLIBCXX20_CONSTEXPR
304       static _Tp* _S_fun(_Tp& __r) noexcept { return std::__addressof(__r); }
305 
306       static void _S_fun(_Tp&&) = delete;
307 
308       template<typename _Up, typename _Up2 = __remove_cvref_t<_Up>>
309 	using __not_same
310 	  = typename enable_if<!is_same<reference_wrapper, _Up2>::value>::type;
311 
312     public:
313       typedef _Tp type;
314 
315       // _GLIBCXX_RESOLVE_LIB_DEFECTS
316       // 2993. reference_wrapper<T> conversion from T&&
317       // 3041. Unnecessary decay in reference_wrapper
318       template<typename _Up, typename = __not_same<_Up>, typename
319 		= decltype(reference_wrapper::_S_fun(std::declval<_Up>()))>
320 	_GLIBCXX20_CONSTEXPR
321 	reference_wrapper(_Up&& __uref)
322 	noexcept(noexcept(reference_wrapper::_S_fun(std::declval<_Up>())))
323 	: _M_data(reference_wrapper::_S_fun(std::forward<_Up>(__uref)))
324 	{ }
325 
326       reference_wrapper(const reference_wrapper&) = default;
327 
328       reference_wrapper&
329       operator=(const reference_wrapper&) = default;
330 
331       _GLIBCXX20_CONSTEXPR
332       operator _Tp&() const noexcept
333       { return this->get(); }
334 
335       _GLIBCXX20_CONSTEXPR
336       _Tp&
337       get() const noexcept
338       { return *_M_data; }
339 
340       template<typename... _Args>
341 	_GLIBCXX20_CONSTEXPR
342 	typename result_of<_Tp&(_Args&&...)>::type
343 	operator()(_Args&&... __args) const
344 	{
345 #if __cplusplus > 201703L
346 	  if constexpr (is_object_v<type>)
347 	    static_assert(sizeof(type), "type must be complete");
348 #endif
349 	  return std::__invoke(get(), std::forward<_Args>(__args)...);
350 	}
351     };
352 
353 #if __cpp_deduction_guides
354   template<typename _Tp>
355     reference_wrapper(_Tp&) -> reference_wrapper<_Tp>;
356 #endif
357 
358   /// @relates reference_wrapper @{
359 
360   /// Denotes a reference should be taken to a variable.
361   template<typename _Tp>
362     _GLIBCXX20_CONSTEXPR
363     inline reference_wrapper<_Tp>
364     ref(_Tp& __t) noexcept
365     { return reference_wrapper<_Tp>(__t); }
366 
367   /// Denotes a const reference should be taken to a variable.
368   template<typename _Tp>
369     _GLIBCXX20_CONSTEXPR
370     inline reference_wrapper<const _Tp>
371     cref(const _Tp& __t) noexcept
372     { return reference_wrapper<const _Tp>(__t); }
373 
374   template<typename _Tp>
375     void ref(const _Tp&&) = delete;
376 
377   template<typename _Tp>
378     void cref(const _Tp&&) = delete;
379 
380   /// std::ref overload to prevent wrapping a reference_wrapper
381   template<typename _Tp>
382     _GLIBCXX20_CONSTEXPR
383     inline reference_wrapper<_Tp>
384     ref(reference_wrapper<_Tp> __t) noexcept
385     { return __t; }
386 
387   /// std::cref overload to prevent wrapping a reference_wrapper
388   template<typename _Tp>
389     _GLIBCXX20_CONSTEXPR
390     inline reference_wrapper<const _Tp>
391     cref(reference_wrapper<_Tp> __t) noexcept
392     { return { __t.get() }; }
393 
394   /// @}
395 
396 _GLIBCXX_END_NAMESPACE_VERSION
397 } // namespace std
398 
399 #endif // C++11
400 
401 #endif // _GLIBCXX_REFWRAP_H
402