xref: /llvm-project/libcxx/include/__functional/function.h (revision 0fa05456a8dc468961c33bd8149b157194672c71)
1050b064fSChristopher Di Bella // -*- C++ -*-
2050b064fSChristopher Di Bella //===----------------------------------------------------------------------===//
3050b064fSChristopher Di Bella //
4050b064fSChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5050b064fSChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
6050b064fSChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7050b064fSChristopher Di Bella //
8050b064fSChristopher Di Bella //===----------------------------------------------------------------------===//
9050b064fSChristopher Di Bella 
10050b064fSChristopher Di Bella #ifndef _LIBCPP___FUNCTIONAL_FUNCTION_H
11050b064fSChristopher Di Bella #define _LIBCPP___FUNCTIONAL_FUNCTION_H
12050b064fSChristopher Di Bella 
13f87aa19bSLouis Dionne #include <__assert>
14050b064fSChristopher Di Bella #include <__config>
155acc4a3dSNikolas Klauser #include <__cstddef/nullptr_t.h>
16c9d36bd8SNikolas Klauser #include <__exception/exception.h>
17050b064fSChristopher Di Bella #include <__functional/binary_function.h>
18050b064fSChristopher Di Bella #include <__functional/invoke.h>
19050b064fSChristopher Di Bella #include <__functional/unary_function.h>
20050b064fSChristopher Di Bella #include <__iterator/iterator_traits.h>
21e24ddb60SLouis Dionne #include <__memory/addressof.h>
22d5e26775SNikolas Klauser #include <__memory/allocator.h>
2359ef4b36SNikolas Klauser #include <__memory/allocator_destructor.h>
24050b064fSChristopher Di Bella #include <__memory/allocator_traits.h>
25050b064fSChristopher Di Bella #include <__memory/compressed_pair.h>
26d5e26775SNikolas Klauser #include <__memory/unique_ptr.h>
270a4aa8a1SNikolas Klauser #include <__type_traits/aligned_storage.h>
2879702f7fSIan Anderson #include <__type_traits/decay.h>
2979702f7fSIan Anderson #include <__type_traits/is_core_convertible.h>
3079702f7fSIan Anderson #include <__type_traits/is_scalar.h>
31580f6048SNikolas Klauser #include <__type_traits/is_trivially_constructible.h>
320a4aa8a1SNikolas Klauser #include <__type_traits/is_trivially_destructible.h>
3379702f7fSIan Anderson #include <__type_traits/is_void.h>
343ec6c997SNikolas Klauser #include <__type_traits/strip_signature.h>
35ea2206d7SArthur O'Dwyer #include <__utility/forward.h>
36ea2206d7SArthur O'Dwyer #include <__utility/move.h>
37d5e26775SNikolas Klauser #include <__utility/piecewise_construct.h>
3852915d78SNikolas Klauser #include <__utility/swap.h>
3916d1b0e1SNikolas Klauser #include <__verbose_abort>
40d5e26775SNikolas Klauser #include <tuple>
41d5e26775SNikolas Klauser #include <typeinfo>
42050b064fSChristopher Di Bella 
43050b064fSChristopher Di Bella #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
44050b064fSChristopher Di Bella #  pragma GCC system_header
45050b064fSChristopher Di Bella #endif
46050b064fSChristopher Di Bella 
477b462251SLouis Dionne _LIBCPP_PUSH_MACROS
487b462251SLouis Dionne #include <__undef_macros>
497b462251SLouis Dionne 
50dbe60caaSNikolas Klauser #ifndef _LIBCPP_CXX03_LANG
51dbe60caaSNikolas Klauser 
52050b064fSChristopher Di Bella _LIBCPP_BEGIN_NAMESPACE_STD
53050b064fSChristopher Di Bella 
54050b064fSChristopher Di Bella // bad_function_call
55050b064fSChristopher Di Bella 
5655cb62f3SNikolas Klauser _LIBCPP_DIAGNOSTIC_PUSH
5722629bb2SLouis Dionne #  if !_LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_KEY_FUNCTION
5855cb62f3SNikolas Klauser _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables")
5922629bb2SLouis Dionne #  endif
609783f28cSLouis Dionne class _LIBCPP_EXPORTED_FROM_ABI bad_function_call : public exception {
61050b064fSChristopher Di Bella public:
6270248920SIgor Zhukov   _LIBCPP_HIDE_FROM_ABI bad_function_call() _NOEXCEPT                                    = default;
6370248920SIgor Zhukov   _LIBCPP_HIDE_FROM_ABI bad_function_call(const bad_function_call&) _NOEXCEPT            = default;
6470248920SIgor Zhukov   _LIBCPP_HIDE_FROM_ABI bad_function_call& operator=(const bad_function_call&) _NOEXCEPT = default;
65434dc0a5SKonstantin Varlamov // Note that when a key function is not used, every translation unit that uses
66434dc0a5SKonstantin Varlamov // bad_function_call will end up containing a weak definition of the vtable and
67434dc0a5SKonstantin Varlamov // typeinfo.
6822629bb2SLouis Dionne #  if _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_KEY_FUNCTION
694262b523SNikolas Klauser   ~bad_function_call() _NOEXCEPT override;
70434dc0a5SKonstantin Varlamov #  else
7183ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_function_call() _NOEXCEPT override {}
72434dc0a5SKonstantin Varlamov #  endif
73050b064fSChristopher Di Bella 
74434dc0a5SKonstantin Varlamov #  ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE
754262b523SNikolas Klauser   const char* what() const _NOEXCEPT override;
76050b064fSChristopher Di Bella #  endif
77050b064fSChristopher Di Bella };
7855cb62f3SNikolas Klauser _LIBCPP_DIAGNOSTIC_POP
79050b064fSChristopher Di Bella 
80748023dcSNikolas Klauser [[__noreturn__]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_function_call() {
81ba87515fSNikolas Klauser #  if _LIBCPP_HAS_EXCEPTIONS
82050b064fSChristopher Di Bella   throw bad_function_call();
83050b064fSChristopher Di Bella #  else
84308bcb3fSNikolas Klauser   _LIBCPP_VERBOSE_ABORT("bad_function_call was thrown in -fno-exceptions mode");
85050b064fSChristopher Di Bella #  endif
86050b064fSChristopher Di Bella }
87050b064fSChristopher Di Bella 
889783f28cSLouis Dionne template <class _Fp>
899783f28cSLouis Dionne class _LIBCPP_TEMPLATE_VIS function; // undefined
90050b064fSChristopher Di Bella 
919783f28cSLouis Dionne namespace __function {
92050b064fSChristopher Di Bella 
93050b064fSChristopher Di Bella template <class _Rp>
949783f28cSLouis Dionne struct __maybe_derive_from_unary_function {};
95050b064fSChristopher Di Bella 
96050b064fSChristopher Di Bella template <class _Rp, class _A1>
979783f28cSLouis Dionne struct __maybe_derive_from_unary_function<_Rp(_A1)> : public __unary_function<_A1, _Rp> {};
98050b064fSChristopher Di Bella 
99050b064fSChristopher Di Bella template <class _Rp>
1009783f28cSLouis Dionne struct __maybe_derive_from_binary_function {};
101050b064fSChristopher Di Bella 
102050b064fSChristopher Di Bella template <class _Rp, class _A1, class _A2>
1039783f28cSLouis Dionne struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)> : public __binary_function<_A1, _A2, _Rp> {};
104050b064fSChristopher Di Bella 
105050b064fSChristopher Di Bella template <class _Fp>
1069783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI bool __not_null(_Fp const&) {
1079783f28cSLouis Dionne   return true;
1089783f28cSLouis Dionne }
109050b064fSChristopher Di Bella 
110050b064fSChristopher Di Bella template <class _Fp>
1119783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI bool __not_null(_Fp* __ptr) {
1129783f28cSLouis Dionne   return __ptr;
1139783f28cSLouis Dionne }
114050b064fSChristopher Di Bella 
115050b064fSChristopher Di Bella template <class _Ret, class _Class>
1169783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI bool __not_null(_Ret _Class::*__ptr) {
1179783f28cSLouis Dionne   return __ptr;
1189783f28cSLouis Dionne }
119050b064fSChristopher Di Bella 
120050b064fSChristopher Di Bella template <class _Fp>
1219783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI bool __not_null(function<_Fp> const& __f) {
1229783f28cSLouis Dionne   return !!__f;
1239783f28cSLouis Dionne }
124050b064fSChristopher Di Bella 
125ba87515fSNikolas Klauser #  if _LIBCPP_HAS_EXTENSION_BLOCKS
126050b064fSChristopher Di Bella template <class _Rp, class... _Args>
1279783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) {
1289783f28cSLouis Dionne   return __p;
1299783f28cSLouis Dionne }
130050b064fSChristopher Di Bella #  endif
131050b064fSChristopher Di Bella 
132050b064fSChristopher Di Bella } // namespace __function
133050b064fSChristopher Di Bella 
134050b064fSChristopher Di Bella namespace __function {
135050b064fSChristopher Di Bella 
136050b064fSChristopher Di Bella // __alloc_func holds a functor and an allocator.
137050b064fSChristopher Di Bella 
1389783f28cSLouis Dionne template <class _Fp, class _Ap, class _FB>
1399783f28cSLouis Dionne class __alloc_func;
140050b064fSChristopher Di Bella template <class _Fp, class _FB>
141050b064fSChristopher Di Bella class __default_alloc_func;
142050b064fSChristopher Di Bella 
143050b064fSChristopher Di Bella template <class _Fp, class _Ap, class _Rp, class... _ArgTypes>
1449783f28cSLouis Dionne class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> {
14527c83382SNikolas Klauser   _LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Ap, __alloc_);
146050b064fSChristopher Di Bella 
147050b064fSChristopher Di Bella public:
1483b8faee6SNikolas Klauser   using _Target _LIBCPP_NODEBUG = _Fp;
1493b8faee6SNikolas Klauser   using _Alloc _LIBCPP_NODEBUG  = _Ap;
150050b064fSChristopher Di Bella 
15127c83382SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __func_; }
152050b064fSChristopher Di Bella 
153050b064fSChristopher Di Bella   // WIN32 APIs may define __allocator, so use __get_allocator instead.
15427c83382SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI const _Alloc& __get_allocator() const { return __alloc_; }
155050b064fSChristopher Di Bella 
15627c83382SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f) : __func_(std::move(__f)), __alloc_() {}
157050b064fSChristopher Di Bella 
15827c83382SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, const _Alloc& __a) : __func_(__f), __alloc_(__a) {}
159050b064fSChristopher Di Bella 
1609783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, _Alloc&& __a)
16127c83382SNikolas Klauser       : __func_(__f), __alloc_(std::move(__a)) {}
162050b064fSChristopher Di Bella 
1639783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f, _Alloc&& __a)
16427c83382SNikolas Klauser       : __func_(std::move(__f)), __alloc_(std::move(__a)) {}
165050b064fSChristopher Di Bella 
1669783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) {
167*0fa05456SNikolas Klauser     return std::__invoke_r<_Rp>(__func_, std::forward<_ArgTypes>(__arg)...);
168050b064fSChristopher Di Bella   }
169050b064fSChristopher Di Bella 
1709783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __alloc_func* __clone() const {
171050b064fSChristopher Di Bella     typedef allocator_traits<_Alloc> __alloc_traits;
172d7d586e5SNikolas Klauser     typedef __rebind_alloc<__alloc_traits, __alloc_func> _AA;
17327c83382SNikolas Klauser     _AA __a(__alloc_);
174050b064fSChristopher Di Bella     typedef __allocator_destructor<_AA> _Dp;
175050b064fSChristopher Di Bella     unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
17627c83382SNikolas Klauser     ::new ((void*)__hold.get()) __alloc_func(__func_, _Alloc(__a));
177050b064fSChristopher Di Bella     return __hold.release();
178050b064fSChristopher Di Bella   }
179050b064fSChristopher Di Bella 
18027c83382SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT {
18127c83382SNikolas Klauser     __func_.~_Fp();
18227c83382SNikolas Klauser     __alloc_.~_Alloc();
18327c83382SNikolas Klauser   }
184050b064fSChristopher Di Bella 
18583ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__alloc_func* __f) {
186050b064fSChristopher Di Bella     typedef allocator_traits<_Alloc> __alloc_traits;
187d7d586e5SNikolas Klauser     typedef __rebind_alloc<__alloc_traits, __alloc_func> _FunAlloc;
188050b064fSChristopher Di Bella     _FunAlloc __a(__f->__get_allocator());
189050b064fSChristopher Di Bella     __f->destroy();
190050b064fSChristopher Di Bella     __a.deallocate(__f, 1);
191050b064fSChristopher Di Bella   }
192050b064fSChristopher Di Bella };
193050b064fSChristopher Di Bella 
194cedb44afSLouis Dionne template <class _Tp>
195cedb44afSLouis Dionne struct __deallocating_deleter {
196cedb44afSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void operator()(void* __p) const {
197cedb44afSLouis Dionne     std::__libcpp_deallocate<_Tp>(static_cast<_Tp*>(__p), __element_count(1));
198cedb44afSLouis Dionne   }
199cedb44afSLouis Dionne };
200cedb44afSLouis Dionne 
201050b064fSChristopher Di Bella template <class _Fp, class _Rp, class... _ArgTypes>
202050b064fSChristopher Di Bella class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> {
203050b064fSChristopher Di Bella   _Fp __f_;
204050b064fSChristopher Di Bella 
205050b064fSChristopher Di Bella public:
2063b8faee6SNikolas Klauser   using _Target _LIBCPP_NODEBUG = _Fp;
207050b064fSChristopher Di Bella 
2089783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __f_; }
209050b064fSChristopher Di Bella 
2109783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(_Target&& __f) : __f_(std::move(__f)) {}
211050b064fSChristopher Di Bella 
2129783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(const _Target& __f) : __f_(__f) {}
213050b064fSChristopher Di Bella 
2149783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) {
215*0fa05456SNikolas Klauser     return std::__invoke_r<_Rp>(__f_, std::forward<_ArgTypes>(__arg)...);
216050b064fSChristopher Di Bella   }
217050b064fSChristopher Di Bella 
2189783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __default_alloc_func* __clone() const {
219cedb44afSLouis Dionne     using _Self = __default_alloc_func;
220cedb44afSLouis Dionne     unique_ptr<_Self, __deallocating_deleter<_Self>> __hold(std::__libcpp_allocate<_Self>(__element_count(1)));
221cedb44afSLouis Dionne     _Self* __res = ::new ((void*)__hold.get()) _Self(__f_);
222050b064fSChristopher Di Bella     (void)__hold.release();
223050b064fSChristopher Di Bella     return __res;
224050b064fSChristopher Di Bella   }
225050b064fSChristopher Di Bella 
2269783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT { __f_.~_Target(); }
227050b064fSChristopher Di Bella 
22883ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__default_alloc_func* __f) {
229050b064fSChristopher Di Bella     __f->destroy();
230cedb44afSLouis Dionne     std::__libcpp_deallocate<__default_alloc_func>(__f, __element_count(1));
231050b064fSChristopher Di Bella   }
232050b064fSChristopher Di Bella };
233050b064fSChristopher Di Bella 
234050b064fSChristopher Di Bella // __base provides an abstract interface for copyable functors.
235050b064fSChristopher Di Bella 
2369783f28cSLouis Dionne template <class _Fp>
2379783f28cSLouis Dionne class _LIBCPP_TEMPLATE_VIS __base;
238050b064fSChristopher Di Bella 
239050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
2409783f28cSLouis Dionne class __base<_Rp(_ArgTypes...)> {
241050b064fSChristopher Di Bella public:
242bbe4a806SNikolas Klauser   __base(const __base&)            = delete;
243bbe4a806SNikolas Klauser   __base& operator=(const __base&) = delete;
244bbe4a806SNikolas Klauser 
2454c198542SLouis Dionne   _LIBCPP_HIDE_FROM_ABI __base() {}
2465efc8116SLouis Dionne   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual ~__base() {}
247050b064fSChristopher Di Bella   virtual __base* __clone() const             = 0;
248050b064fSChristopher Di Bella   virtual void __clone(__base*) const         = 0;
249050b064fSChristopher Di Bella   virtual void destroy() _NOEXCEPT            = 0;
250050b064fSChristopher Di Bella   virtual void destroy_deallocate() _NOEXCEPT = 0;
251050b064fSChristopher Di Bella   virtual _Rp operator()(_ArgTypes&&...)      = 0;
252ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
253050b064fSChristopher Di Bella   virtual const void* target(const type_info&) const _NOEXCEPT = 0;
254050b064fSChristopher Di Bella   virtual const std::type_info& target_type() const _NOEXCEPT  = 0;
255ba87515fSNikolas Klauser #  endif // _LIBCPP_HAS_RTTI
256050b064fSChristopher Di Bella };
257050b064fSChristopher Di Bella 
258050b064fSChristopher Di Bella // __func implements __base for a given functor type.
259050b064fSChristopher Di Bella 
2609783f28cSLouis Dionne template <class _FD, class _Alloc, class _FB>
2619783f28cSLouis Dionne class __func;
262050b064fSChristopher Di Bella 
263050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
2649783f28cSLouis Dionne class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> {
265050b064fSChristopher Di Bella   __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_;
2669783f28cSLouis Dionne 
267050b064fSChristopher Di Bella public:
2689783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __func(_Fp&& __f) : __f_(std::move(__f)) {}
269050b064fSChristopher Di Bella 
2709783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __func(const _Fp& __f, const _Alloc& __a) : __f_(__f, __a) {}
271050b064fSChristopher Di Bella 
2729783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __func(const _Fp& __f, _Alloc&& __a) : __f_(__f, std::move(__a)) {}
273050b064fSChristopher Di Bella 
2749783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __func(_Fp&& __f, _Alloc&& __a) : __f_(std::move(__f), std::move(__a)) {}
275050b064fSChristopher Di Bella 
27683ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const;
27783ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __clone(__base<_Rp(_ArgTypes...)>*) const;
27883ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT;
27983ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate() _NOEXCEPT;
28083ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&&... __arg);
281ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
28283ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const void* target(const type_info&) const _NOEXCEPT;
28383ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const std::type_info& target_type() const _NOEXCEPT;
284ba87515fSNikolas Klauser #  endif // _LIBCPP_HAS_RTTI
285050b064fSChristopher Di Bella };
286050b064fSChristopher Di Bella 
287050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
2889783f28cSLouis Dionne __base<_Rp(_ArgTypes...)>* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const {
289050b064fSChristopher Di Bella   typedef allocator_traits<_Alloc> __alloc_traits;
290d7d586e5SNikolas Klauser   typedef __rebind_alloc<__alloc_traits, __func> _Ap;
291050b064fSChristopher Di Bella   _Ap __a(__f_.__get_allocator());
292050b064fSChristopher Di Bella   typedef __allocator_destructor<_Ap> _Dp;
293050b064fSChristopher Di Bella   unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
294050b064fSChristopher Di Bella   ::new ((void*)__hold.get()) __func(__f_.__target(), _Alloc(__a));
295050b064fSChristopher Di Bella   return __hold.release();
296050b064fSChristopher Di Bella }
297050b064fSChristopher Di Bella 
298050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
2999783f28cSLouis Dionne void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const {
300050b064fSChristopher Di Bella   ::new ((void*)__p) __func(__f_.__target(), __f_.__get_allocator());
301050b064fSChristopher Di Bella }
302050b064fSChristopher Di Bella 
303050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
3049783f28cSLouis Dionne void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPT {
305050b064fSChristopher Di Bella   __f_.destroy();
306050b064fSChristopher Di Bella }
307050b064fSChristopher Di Bella 
308050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
3099783f28cSLouis Dionne void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPT {
310050b064fSChristopher Di Bella   typedef allocator_traits<_Alloc> __alloc_traits;
311d7d586e5SNikolas Klauser   typedef __rebind_alloc<__alloc_traits, __func> _Ap;
312050b064fSChristopher Di Bella   _Ap __a(__f_.__get_allocator());
313050b064fSChristopher Di Bella   __f_.destroy();
314050b064fSChristopher Di Bella   __a.deallocate(this, 1);
315050b064fSChristopher Di Bella }
316050b064fSChristopher Di Bella 
317050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
3189783f28cSLouis Dionne _Rp __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&&... __arg) {
31977a00c0dSLouis Dionne   return __f_(std::forward<_ArgTypes>(__arg)...);
320050b064fSChristopher Di Bella }
321050b064fSChristopher Di Bella 
322ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
323050b064fSChristopher Di Bella 
324050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
3259783f28cSLouis Dionne const void* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT {
326050b064fSChristopher Di Bella   if (__ti == typeid(_Fp))
32777a00c0dSLouis Dionne     return std::addressof(__f_.__target());
328050b064fSChristopher Di Bella   return nullptr;
329050b064fSChristopher Di Bella }
330050b064fSChristopher Di Bella 
331050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
3329783f28cSLouis Dionne const std::type_info& __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT {
333050b064fSChristopher Di Bella   return typeid(_Fp);
334050b064fSChristopher Di Bella }
335050b064fSChristopher Di Bella 
336ba87515fSNikolas Klauser #  endif // _LIBCPP_HAS_RTTI
337050b064fSChristopher Di Bella 
338050b064fSChristopher Di Bella // __value_func creates a value-type from a __func.
339050b064fSChristopher Di Bella 
3409783f28cSLouis Dionne template <class _Fp>
3419783f28cSLouis Dionne class __value_func;
342050b064fSChristopher Di Bella 
3439783f28cSLouis Dionne template <class _Rp, class... _ArgTypes>
3449783f28cSLouis Dionne class __value_func<_Rp(_ArgTypes...)> {
345987f08feSNikolas Klauser   _LIBCPP_SUPPRESS_DEPRECATED_PUSH
346050b064fSChristopher Di Bella   typename aligned_storage<3 * sizeof(void*)>::type __buf_;
347987f08feSNikolas Klauser   _LIBCPP_SUPPRESS_DEPRECATED_POP
348050b064fSChristopher Di Bella 
349050b064fSChristopher Di Bella   typedef __base<_Rp(_ArgTypes...)> __func;
350050b064fSChristopher Di Bella   __func* __f_;
351050b064fSChristopher Di Bella 
3529783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI static __func* __as_base(void* __p) { return reinterpret_cast<__func*>(__p); }
353050b064fSChristopher Di Bella 
354050b064fSChristopher Di Bella public:
3559783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __value_func() _NOEXCEPT : __f_(nullptr) {}
356050b064fSChristopher Di Bella 
357050b064fSChristopher Di Bella   template <class _Fp, class _Alloc>
3589783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __value_func(_Fp&& __f, const _Alloc& __a) : __f_(nullptr) {
359050b064fSChristopher Di Bella     typedef allocator_traits<_Alloc> __alloc_traits;
360050b064fSChristopher Di Bella     typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun;
361d7d586e5SNikolas Klauser     typedef __rebind_alloc<__alloc_traits, _Fun> _FunAlloc;
362050b064fSChristopher Di Bella 
3639783f28cSLouis Dionne     if (__function::__not_null(__f)) {
364050b064fSChristopher Di Bella       _FunAlloc __af(__a);
3659783f28cSLouis Dionne       if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value &&
3669783f28cSLouis Dionne           is_nothrow_copy_constructible<_FunAlloc>::value) {
3679783f28cSLouis Dionne         __f_ = ::new ((void*)&__buf_) _Fun(std::move(__f), _Alloc(__af));
3689783f28cSLouis Dionne       } else {
369050b064fSChristopher Di Bella         typedef __allocator_destructor<_FunAlloc> _Dp;
370050b064fSChristopher Di Bella         unique_ptr<__func, _Dp> __hold(__af.allocate(1), _Dp(__af, 1));
37177a00c0dSLouis Dionne         ::new ((void*)__hold.get()) _Fun(std::move(__f), _Alloc(__a));
372050b064fSChristopher Di Bella         __f_ = __hold.release();
373050b064fSChristopher Di Bella       }
374050b064fSChristopher Di Bella     }
375050b064fSChristopher Di Bella   }
376050b064fSChristopher Di Bella 
3776256ccfdSNikolas Klauser   template <class _Fp, __enable_if_t<!is_same<__decay_t<_Fp>, __value_func>::value, int> = 0>
3789783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __value_func(_Fp&& __f) : __value_func(std::forward<_Fp>(__f), allocator<_Fp>()) {}
379050b064fSChristopher Di Bella 
3809783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __value_func(const __value_func& __f) {
381050b064fSChristopher Di Bella     if (__f.__f_ == nullptr)
382050b064fSChristopher Di Bella       __f_ = nullptr;
3839783f28cSLouis Dionne     else if ((void*)__f.__f_ == &__f.__buf_) {
384050b064fSChristopher Di Bella       __f_ = __as_base(&__buf_);
385050b064fSChristopher Di Bella       __f.__f_->__clone(__f_);
3869783f28cSLouis Dionne     } else
387050b064fSChristopher Di Bella       __f_ = __f.__f_->__clone();
388050b064fSChristopher Di Bella   }
389050b064fSChristopher Di Bella 
3909783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __value_func(__value_func&& __f) _NOEXCEPT {
391050b064fSChristopher Di Bella     if (__f.__f_ == nullptr)
392050b064fSChristopher Di Bella       __f_ = nullptr;
3939783f28cSLouis Dionne     else if ((void*)__f.__f_ == &__f.__buf_) {
394050b064fSChristopher Di Bella       __f_ = __as_base(&__buf_);
395050b064fSChristopher Di Bella       __f.__f_->__clone(__f_);
3969783f28cSLouis Dionne     } else {
397050b064fSChristopher Di Bella       __f_     = __f.__f_;
398050b064fSChristopher Di Bella       __f.__f_ = nullptr;
399050b064fSChristopher Di Bella     }
400050b064fSChristopher Di Bella   }
401050b064fSChristopher Di Bella 
4029783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI ~__value_func() {
403050b064fSChristopher Di Bella     if ((void*)__f_ == &__buf_)
404050b064fSChristopher Di Bella       __f_->destroy();
405050b064fSChristopher Di Bella     else if (__f_)
406050b064fSChristopher Di Bella       __f_->destroy_deallocate();
407050b064fSChristopher Di Bella   }
408050b064fSChristopher Di Bella 
4099783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __value_func& operator=(__value_func&& __f) {
410050b064fSChristopher Di Bella     *this = nullptr;
411050b064fSChristopher Di Bella     if (__f.__f_ == nullptr)
412050b064fSChristopher Di Bella       __f_ = nullptr;
4139783f28cSLouis Dionne     else if ((void*)__f.__f_ == &__f.__buf_) {
414050b064fSChristopher Di Bella       __f_ = __as_base(&__buf_);
415050b064fSChristopher Di Bella       __f.__f_->__clone(__f_);
4169783f28cSLouis Dionne     } else {
417050b064fSChristopher Di Bella       __f_     = __f.__f_;
418050b064fSChristopher Di Bella       __f.__f_ = nullptr;
419050b064fSChristopher Di Bella     }
420050b064fSChristopher Di Bella     return *this;
421050b064fSChristopher Di Bella   }
422050b064fSChristopher Di Bella 
4239783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __value_func& operator=(nullptr_t) {
424050b064fSChristopher Di Bella     __func* __f = __f_;
425050b064fSChristopher Di Bella     __f_        = nullptr;
426050b064fSChristopher Di Bella     if ((void*)__f == &__buf_)
427050b064fSChristopher Di Bella       __f->destroy();
428050b064fSChristopher Di Bella     else if (__f)
429050b064fSChristopher Di Bella       __f->destroy_deallocate();
430050b064fSChristopher Di Bella     return *this;
431050b064fSChristopher Di Bella   }
432050b064fSChristopher Di Bella 
4339783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __args) const {
434050b064fSChristopher Di Bella     if (__f_ == nullptr)
435050b064fSChristopher Di Bella       __throw_bad_function_call();
43677a00c0dSLouis Dionne     return (*__f_)(std::forward<_ArgTypes>(__args)...);
437050b064fSChristopher Di Bella   }
438050b064fSChristopher Di Bella 
4399783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void swap(__value_func& __f) _NOEXCEPT {
440050b064fSChristopher Di Bella     if (&__f == this)
441050b064fSChristopher Di Bella       return;
4429783f28cSLouis Dionne     if ((void*)__f_ == &__buf_ && (void*)__f.__f_ == &__f.__buf_) {
443987f08feSNikolas Klauser       _LIBCPP_SUPPRESS_DEPRECATED_PUSH
444050b064fSChristopher Di Bella       typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
445987f08feSNikolas Klauser       _LIBCPP_SUPPRESS_DEPRECATED_POP
446050b064fSChristopher Di Bella       __func* __t = __as_base(&__tempbuf);
447050b064fSChristopher Di Bella       __f_->__clone(__t);
448050b064fSChristopher Di Bella       __f_->destroy();
449050b064fSChristopher Di Bella       __f_ = nullptr;
450050b064fSChristopher Di Bella       __f.__f_->__clone(__as_base(&__buf_));
451050b064fSChristopher Di Bella       __f.__f_->destroy();
452050b064fSChristopher Di Bella       __f.__f_ = nullptr;
453050b064fSChristopher Di Bella       __f_     = __as_base(&__buf_);
454050b064fSChristopher Di Bella       __t->__clone(__as_base(&__f.__buf_));
455050b064fSChristopher Di Bella       __t->destroy();
456050b064fSChristopher Di Bella       __f.__f_ = __as_base(&__f.__buf_);
4579783f28cSLouis Dionne     } else if ((void*)__f_ == &__buf_) {
458050b064fSChristopher Di Bella       __f_->__clone(__as_base(&__f.__buf_));
459050b064fSChristopher Di Bella       __f_->destroy();
460050b064fSChristopher Di Bella       __f_     = __f.__f_;
461050b064fSChristopher Di Bella       __f.__f_ = __as_base(&__f.__buf_);
4629783f28cSLouis Dionne     } else if ((void*)__f.__f_ == &__f.__buf_) {
463050b064fSChristopher Di Bella       __f.__f_->__clone(__as_base(&__buf_));
464050b064fSChristopher Di Bella       __f.__f_->destroy();
465050b064fSChristopher Di Bella       __f.__f_ = __f_;
466050b064fSChristopher Di Bella       __f_     = __as_base(&__buf_);
4679783f28cSLouis Dionne     } else
46877a00c0dSLouis Dionne       std::swap(__f_, __f.__f_);
469050b064fSChristopher Di Bella   }
470050b064fSChristopher Di Bella 
4719783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __f_ != nullptr; }
472050b064fSChristopher Di Bella 
473ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
4749783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT {
475050b064fSChristopher Di Bella     if (__f_ == nullptr)
476050b064fSChristopher Di Bella       return typeid(void);
477050b064fSChristopher Di Bella     return __f_->target_type();
478050b064fSChristopher Di Bella   }
479050b064fSChristopher Di Bella 
480050b064fSChristopher Di Bella   template <typename _Tp>
4819783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT {
482050b064fSChristopher Di Bella     if (__f_ == nullptr)
483050b064fSChristopher Di Bella       return nullptr;
484050b064fSChristopher Di Bella     return (const _Tp*)__f_->target(typeid(_Tp));
485050b064fSChristopher Di Bella   }
486ba87515fSNikolas Klauser #  endif // _LIBCPP_HAS_RTTI
487050b064fSChristopher Di Bella };
488050b064fSChristopher Di Bella 
489050b064fSChristopher Di Bella // Storage for a functor object, to be used with __policy to manage copy and
490050b064fSChristopher Di Bella // destruction.
4919783f28cSLouis Dionne union __policy_storage {
492050b064fSChristopher Di Bella   mutable char __small[sizeof(void*) * 2];
493050b064fSChristopher Di Bella   void* __large;
494050b064fSChristopher Di Bella };
495050b064fSChristopher Di Bella 
496050b064fSChristopher Di Bella // True if _Fun can safely be held in __policy_storage.__small.
497050b064fSChristopher Di Bella template <typename _Fun>
498050b064fSChristopher Di Bella struct __use_small_storage
499050b064fSChristopher Di Bella     : public integral_constant<
5009783f28cSLouis Dionne           bool,
5019783f28cSLouis Dionne           sizeof(_Fun) <= sizeof(__policy_storage)&& _LIBCPP_ALIGNOF(_Fun) <= _LIBCPP_ALIGNOF(__policy_storage) &&
5029783f28cSLouis Dionne               is_trivially_copy_constructible<_Fun>::value && is_trivially_destructible<_Fun>::value> {};
503050b064fSChristopher Di Bella 
504050b064fSChristopher Di Bella // Policy contains information about how to copy, destroy, and move the
505050b064fSChristopher Di Bella // underlying functor. You can think of it as a vtable of sorts.
5069783f28cSLouis Dionne struct __policy {
507050b064fSChristopher Di Bella   // Used to copy or destroy __large values. null for trivial objects.
508050b064fSChristopher Di Bella   void* (*const __clone)(const void*);
509050b064fSChristopher Di Bella   void (*const __destroy)(void*);
510050b064fSChristopher Di Bella 
511050b064fSChristopher Di Bella   // True if this is the null policy (no value).
512050b064fSChristopher Di Bella   const bool __is_null;
513050b064fSChristopher Di Bella 
514050b064fSChristopher Di Bella   // The target type. May be null if RTTI is disabled.
515050b064fSChristopher Di Bella   const std::type_info* const __type_info;
516050b064fSChristopher Di Bella 
517050b064fSChristopher Di Bella   // Returns a pointer to a static policy object suitable for the functor
518050b064fSChristopher Di Bella   // type.
519050b064fSChristopher Di Bella   template <typename _Fun>
5209783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static const __policy* __create() {
521050b064fSChristopher Di Bella     return __choose_policy<_Fun>(__use_small_storage<_Fun>());
522050b064fSChristopher Di Bella   }
523050b064fSChristopher Di Bella 
5249783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static const __policy* __create_empty() {
5251f98ac09SNikolas Klauser     static constexpr __policy __policy = {
5269783f28cSLouis Dionne         nullptr,
5279783f28cSLouis Dionne         nullptr,
528050b064fSChristopher Di Bella         true,
529ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
530050b064fSChristopher Di Bella         &typeid(void)
531050b064fSChristopher Di Bella #  else
532050b064fSChristopher Di Bella         nullptr
533050b064fSChristopher Di Bella #  endif
534050b064fSChristopher Di Bella     };
535d05f8895SNikolas Klauser     return &__policy;
536050b064fSChristopher Di Bella   }
537050b064fSChristopher Di Bella 
538050b064fSChristopher Di Bella private:
53983ce1397SNikolas Klauser   template <typename _Fun>
5409783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static void* __large_clone(const void* __s) {
541050b064fSChristopher Di Bella     const _Fun* __f = static_cast<const _Fun*>(__s);
542050b064fSChristopher Di Bella     return __f->__clone();
543050b064fSChristopher Di Bella   }
544050b064fSChristopher Di Bella 
545050b064fSChristopher Di Bella   template <typename _Fun>
54683ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static void __large_destroy(void* __s) {
547050b064fSChristopher Di Bella     _Fun::__destroy_and_delete(static_cast<_Fun*>(__s));
548050b064fSChristopher Di Bella   }
549050b064fSChristopher Di Bella 
550050b064fSChristopher Di Bella   template <typename _Fun>
5519783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ false_type) {
5521f98ac09SNikolas Klauser     static constexpr __policy __policy = {
5539783f28cSLouis Dionne         &__large_clone<_Fun>,
5549783f28cSLouis Dionne         &__large_destroy<_Fun>,
5559783f28cSLouis Dionne         false,
556ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
557050b064fSChristopher Di Bella         &typeid(typename _Fun::_Target)
558050b064fSChristopher Di Bella #  else
559050b064fSChristopher Di Bella         nullptr
560050b064fSChristopher Di Bella #  endif
561050b064fSChristopher Di Bella     };
562d05f8895SNikolas Klauser     return &__policy;
563050b064fSChristopher Di Bella   }
564050b064fSChristopher Di Bella 
565050b064fSChristopher Di Bella   template <typename _Fun>
5669783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ true_type) {
5671f98ac09SNikolas Klauser     static constexpr __policy __policy = {
5689783f28cSLouis Dionne         nullptr,
5699783f28cSLouis Dionne         nullptr,
5709783f28cSLouis Dionne         false,
571ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
572050b064fSChristopher Di Bella         &typeid(typename _Fun::_Target)
573050b064fSChristopher Di Bella #  else
574050b064fSChristopher Di Bella         nullptr
575050b064fSChristopher Di Bella #  endif
576050b064fSChristopher Di Bella     };
577d05f8895SNikolas Klauser     return &__policy;
578050b064fSChristopher Di Bella   }
579050b064fSChristopher Di Bella };
580050b064fSChristopher Di Bella 
581050b064fSChristopher Di Bella // Used to choose between perfect forwarding or pass-by-value. Pass-by-value is
582050b064fSChristopher Di Bella // faster for types that can be passed in registers.
583050b064fSChristopher Di Bella template <typename _Tp>
584f6958523SNikolas Klauser using __fast_forward _LIBCPP_NODEBUG = __conditional_t<is_scalar<_Tp>::value, _Tp, _Tp&&>;
585050b064fSChristopher Di Bella 
586050b064fSChristopher Di Bella // __policy_invoker calls an instance of __alloc_func held in __policy_storage.
587050b064fSChristopher Di Bella 
5889783f28cSLouis Dionne template <class _Fp>
5899783f28cSLouis Dionne struct __policy_invoker;
590050b064fSChristopher Di Bella 
591050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
5929783f28cSLouis Dionne struct __policy_invoker<_Rp(_ArgTypes...)> {
5939783f28cSLouis Dionne   typedef _Rp (*__Call)(const __policy_storage*, __fast_forward<_ArgTypes>...);
594050b064fSChristopher Di Bella 
595050b064fSChristopher Di Bella   __Call __call_;
596050b064fSChristopher Di Bella 
597050b064fSChristopher Di Bella   // Creates an invoker that throws bad_function_call.
5989783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __policy_invoker() : __call_(&__call_empty) {}
599050b064fSChristopher Di Bella 
600050b064fSChristopher Di Bella   // Creates an invoker that calls the given instance of __func.
601050b064fSChristopher Di Bella   template <typename _Fun>
6029783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static __policy_invoker __create() {
603050b064fSChristopher Di Bella     return __policy_invoker(&__call_impl<_Fun>);
604050b064fSChristopher Di Bella   }
605050b064fSChristopher Di Bella 
606050b064fSChristopher Di Bella private:
6079783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __policy_invoker(__Call __c) : __call_(__c) {}
608050b064fSChristopher Di Bella 
6099783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static _Rp __call_empty(const __policy_storage*, __fast_forward<_ArgTypes>...) {
610050b064fSChristopher Di Bella     __throw_bad_function_call();
611050b064fSChristopher Di Bella   }
612050b064fSChristopher Di Bella 
613050b064fSChristopher Di Bella   template <typename _Fun>
6149783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static _Rp __call_impl(const __policy_storage* __buf, __fast_forward<_ArgTypes>... __args) {
6159783f28cSLouis Dionne     _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value ? &__buf->__small : __buf->__large);
61677a00c0dSLouis Dionne     return (*__f)(std::forward<_ArgTypes>(__args)...);
617050b064fSChristopher Di Bella   }
618050b064fSChristopher Di Bella };
619050b064fSChristopher Di Bella 
620050b064fSChristopher Di Bella // __policy_func uses a __policy and __policy_invoker to create a type-erased,
621050b064fSChristopher Di Bella // copyable functor.
622050b064fSChristopher Di Bella 
6239783f28cSLouis Dionne template <class _Fp>
6249783f28cSLouis Dionne class __policy_func;
625050b064fSChristopher Di Bella 
6269783f28cSLouis Dionne template <class _Rp, class... _ArgTypes>
6279783f28cSLouis Dionne class __policy_func<_Rp(_ArgTypes...)> {
628050b064fSChristopher Di Bella   // Inline storage for small objects.
629050b064fSChristopher Di Bella   __policy_storage __buf_;
630050b064fSChristopher Di Bella 
631050b064fSChristopher Di Bella   // Calls the value stored in __buf_. This could technically be part of
632050b064fSChristopher Di Bella   // policy, but storing it here eliminates a level of indirection inside
633050b064fSChristopher Di Bella   // operator().
634050b064fSChristopher Di Bella   typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker;
635050b064fSChristopher Di Bella   __invoker __invoker_;
636050b064fSChristopher Di Bella 
637050b064fSChristopher Di Bella   // The policy that describes how to move / copy / destroy __buf_. Never
638050b064fSChristopher Di Bella   // null, even if the function is empty.
639050b064fSChristopher Di Bella   const __policy* __policy_;
640050b064fSChristopher Di Bella 
641050b064fSChristopher Di Bella public:
6429783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __policy_func() : __policy_(__policy::__create_empty()) {}
643050b064fSChristopher Di Bella 
644050b064fSChristopher Di Bella   template <class _Fp, class _Alloc>
6459783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __policy_func(_Fp&& __f, const _Alloc& __a) : __policy_(__policy::__create_empty()) {
646050b064fSChristopher Di Bella     typedef __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun;
647050b064fSChristopher Di Bella     typedef allocator_traits<_Alloc> __alloc_traits;
648d7d586e5SNikolas Klauser     typedef __rebind_alloc<__alloc_traits, _Fun> _FunAlloc;
649050b064fSChristopher Di Bella 
6509783f28cSLouis Dionne     if (__function::__not_null(__f)) {
651050b064fSChristopher Di Bella       __invoker_ = __invoker::template __create<_Fun>();
652050b064fSChristopher Di Bella       __policy_  = __policy::__create<_Fun>();
653050b064fSChristopher Di Bella 
654050b064fSChristopher Di Bella       _FunAlloc __af(__a);
6559783f28cSLouis Dionne       if (__use_small_storage<_Fun>()) {
6569783f28cSLouis Dionne         ::new ((void*)&__buf_.__small) _Fun(std::move(__f), _Alloc(__af));
6579783f28cSLouis Dionne       } else {
658050b064fSChristopher Di Bella         typedef __allocator_destructor<_FunAlloc> _Dp;
659050b064fSChristopher Di Bella         unique_ptr<_Fun, _Dp> __hold(__af.allocate(1), _Dp(__af, 1));
6609783f28cSLouis Dionne         ::new ((void*)__hold.get()) _Fun(std::move(__f), _Alloc(__af));
661050b064fSChristopher Di Bella         __buf_.__large = __hold.release();
662050b064fSChristopher Di Bella       }
663050b064fSChristopher Di Bella     }
664050b064fSChristopher Di Bella   }
665050b064fSChristopher Di Bella 
6666256ccfdSNikolas Klauser   template <class _Fp, __enable_if_t<!is_same<__decay_t<_Fp>, __policy_func>::value, int> = 0>
6679783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __policy_func(_Fp&& __f) : __policy_(__policy::__create_empty()) {
668050b064fSChristopher Di Bella     typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun;
669050b064fSChristopher Di Bella 
670050b064fSChristopher Di Bella     if (__function::__not_null(__f)) {
671050b064fSChristopher Di Bella       __invoker_ = __invoker::template __create<_Fun>();
672050b064fSChristopher Di Bella       __policy_  = __policy::__create<_Fun>();
673050b064fSChristopher Di Bella       if (__use_small_storage<_Fun>()) {
67477a00c0dSLouis Dionne         ::new ((void*)&__buf_.__small) _Fun(std::move(__f));
675050b064fSChristopher Di Bella       } else {
676cedb44afSLouis Dionne         unique_ptr<_Fun, __deallocating_deleter<_Fun>> __hold(std::__libcpp_allocate<_Fun>(__element_count(1)));
67777a00c0dSLouis Dionne         __buf_.__large = ::new ((void*)__hold.get()) _Fun(std::move(__f));
678050b064fSChristopher Di Bella         (void)__hold.release();
679050b064fSChristopher Di Bella       }
680050b064fSChristopher Di Bella     }
681050b064fSChristopher Di Bella   }
682050b064fSChristopher Di Bella 
6839783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __policy_func(const __policy_func& __f)
6849783f28cSLouis Dionne       : __buf_(__f.__buf_), __invoker_(__f.__invoker_), __policy_(__f.__policy_) {
685050b064fSChristopher Di Bella     if (__policy_->__clone)
686050b064fSChristopher Di Bella       __buf_.__large = __policy_->__clone(__f.__buf_.__large);
687050b064fSChristopher Di Bella   }
688050b064fSChristopher Di Bella 
6899783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __policy_func(__policy_func&& __f)
6909783f28cSLouis Dionne       : __buf_(__f.__buf_), __invoker_(__f.__invoker_), __policy_(__f.__policy_) {
6919783f28cSLouis Dionne     if (__policy_->__destroy) {
692050b064fSChristopher Di Bella       __f.__policy_  = __policy::__create_empty();
693050b064fSChristopher Di Bella       __f.__invoker_ = __invoker();
694050b064fSChristopher Di Bella     }
695050b064fSChristopher Di Bella   }
696050b064fSChristopher Di Bella 
6979783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI ~__policy_func() {
698050b064fSChristopher Di Bella     if (__policy_->__destroy)
699050b064fSChristopher Di Bella       __policy_->__destroy(__buf_.__large);
700050b064fSChristopher Di Bella   }
701050b064fSChristopher Di Bella 
7029783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __policy_func& operator=(__policy_func&& __f) {
703050b064fSChristopher Di Bella     *this          = nullptr;
704050b064fSChristopher Di Bella     __buf_         = __f.__buf_;
705050b064fSChristopher Di Bella     __invoker_     = __f.__invoker_;
706050b064fSChristopher Di Bella     __policy_      = __f.__policy_;
707050b064fSChristopher Di Bella     __f.__policy_  = __policy::__create_empty();
708050b064fSChristopher Di Bella     __f.__invoker_ = __invoker();
709050b064fSChristopher Di Bella     return *this;
710050b064fSChristopher Di Bella   }
711050b064fSChristopher Di Bella 
7129783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI __policy_func& operator=(nullptr_t) {
713050b064fSChristopher Di Bella     const __policy* __p = __policy_;
714050b064fSChristopher Di Bella     __policy_           = __policy::__create_empty();
715050b064fSChristopher Di Bella     __invoker_          = __invoker();
716050b064fSChristopher Di Bella     if (__p->__destroy)
717050b064fSChristopher Di Bella       __p->__destroy(__buf_.__large);
718050b064fSChristopher Di Bella     return *this;
719050b064fSChristopher Di Bella   }
720050b064fSChristopher Di Bella 
7219783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __args) const {
7229783f28cSLouis Dionne     return __invoker_.__call_(std::addressof(__buf_), std::forward<_ArgTypes>(__args)...);
723050b064fSChristopher Di Bella   }
724050b064fSChristopher Di Bella 
7259783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void swap(__policy_func& __f) {
72677a00c0dSLouis Dionne     std::swap(__invoker_, __f.__invoker_);
72777a00c0dSLouis Dionne     std::swap(__policy_, __f.__policy_);
72877a00c0dSLouis Dionne     std::swap(__buf_, __f.__buf_);
729050b064fSChristopher Di Bella   }
730050b064fSChristopher Di Bella 
7319783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return !__policy_->__is_null; }
732050b064fSChristopher Di Bella 
733ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
7349783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT { return *__policy_->__type_info; }
735050b064fSChristopher Di Bella 
736050b064fSChristopher Di Bella   template <typename _Tp>
7379783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT {
738050b064fSChristopher Di Bella     if (__policy_->__is_null || typeid(_Tp) != *__policy_->__type_info)
739050b064fSChristopher Di Bella       return nullptr;
740050b064fSChristopher Di Bella     if (__policy_->__clone) // Out of line storage.
741050b064fSChristopher Di Bella       return reinterpret_cast<const _Tp*>(__buf_.__large);
742050b064fSChristopher Di Bella     else
743050b064fSChristopher Di Bella       return reinterpret_cast<const _Tp*>(&__buf_.__small);
744050b064fSChristopher Di Bella   }
745ba87515fSNikolas Klauser #  endif // _LIBCPP_HAS_RTTI
746050b064fSChristopher Di Bella };
747050b064fSChristopher Di Bella 
748ba87515fSNikolas Klauser #  if _LIBCPP_HAS_BLOCKS_RUNTIME
749050b064fSChristopher Di Bella 
750050b064fSChristopher Di Bella extern "C" void* _Block_copy(const void*);
751050b064fSChristopher Di Bella extern "C" void _Block_release(const void*);
752050b064fSChristopher Di Bella 
753050b064fSChristopher Di Bella template <class _Rp1, class... _ArgTypes1, class _Alloc, class _Rp, class... _ArgTypes>
7549783f28cSLouis Dionne class __func<_Rp1 (^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> {
755050b064fSChristopher Di Bella   typedef _Rp1 (^__block_type)(_ArgTypes1...);
756050b064fSChristopher Di Bella   __block_type __f_;
757050b064fSChristopher Di Bella 
758050b064fSChristopher Di Bella public:
7599783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __func(__block_type const& __f)
760ba87515fSNikolas Klauser #    if _LIBCPP_HAS_OBJC_ARC
7610e4802bfSLouis Dionne       : __f_(__f)
7620e4802bfSLouis Dionne #    else
763050b064fSChristopher Di Bella       : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr))
7640e4802bfSLouis Dionne #    endif
7659783f28cSLouis Dionne   {
7669783f28cSLouis Dionne   }
767050b064fSChristopher Di Bella 
768050b064fSChristopher Di Bella   // [TODO] add && to save on a retain
769050b064fSChristopher Di Bella 
7709783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit __func(__block_type __f, const _Alloc& /* unused */)
771ba87515fSNikolas Klauser #    if _LIBCPP_HAS_OBJC_ARC
7720e4802bfSLouis Dionne       : __f_(__f)
7730e4802bfSLouis Dionne #    else
774050b064fSChristopher Di Bella       : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr))
7750e4802bfSLouis Dionne #    endif
7769783f28cSLouis Dionne   {
7779783f28cSLouis Dionne   }
778050b064fSChristopher Di Bella 
7796cc8d54aSLouis Dionne   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const {
7809783f28cSLouis Dionne     _LIBCPP_ASSERT_INTERNAL(
7819783f28cSLouis Dionne         false,
782050b064fSChristopher Di Bella         "Block pointers are just pointers, so they should always fit into "
783050b064fSChristopher Di Bella         "std::function's small buffer optimization. This function should "
784050b064fSChristopher Di Bella         "never be invoked.");
785050b064fSChristopher Di Bella     return nullptr;
786050b064fSChristopher Di Bella   }
787050b064fSChristopher Di Bella 
7886cc8d54aSLouis Dionne   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __clone(__base<_Rp(_ArgTypes...)>* __p) const {
7896cc8d54aSLouis Dionne     ::new ((void*)__p) __func(__f_);
7906cc8d54aSLouis Dionne   }
791050b064fSChristopher Di Bella 
7926cc8d54aSLouis Dionne   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT {
793ba87515fSNikolas Klauser #    if !_LIBCPP_HAS_OBJC_ARC
794050b064fSChristopher Di Bella     if (__f_)
795050b064fSChristopher Di Bella       _Block_release(__f_);
7960e4802bfSLouis Dionne #    endif
797050b064fSChristopher Di Bella     __f_ = 0;
798050b064fSChristopher Di Bella   }
799050b064fSChristopher Di Bella 
8006cc8d54aSLouis Dionne   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate() _NOEXCEPT {
8019783f28cSLouis Dionne     _LIBCPP_ASSERT_INTERNAL(
8029783f28cSLouis Dionne         false,
803050b064fSChristopher Di Bella         "Block pointers are just pointers, so they should always fit into "
804050b064fSChristopher Di Bella         "std::function's small buffer optimization. This function should "
805050b064fSChristopher Di Bella         "never be invoked.");
806050b064fSChristopher Di Bella   }
807050b064fSChristopher Di Bella 
8086cc8d54aSLouis Dionne   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&&... __arg) {
8096cc8d54aSLouis Dionne     return std::__invoke(__f_, std::forward<_ArgTypes>(__arg)...);
8106cc8d54aSLouis Dionne   }
811050b064fSChristopher Di Bella 
812ba87515fSNikolas Klauser #    if _LIBCPP_HAS_RTTI
8136cc8d54aSLouis Dionne   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const void* target(type_info const& __ti) const _NOEXCEPT {
814050b064fSChristopher Di Bella     if (__ti == typeid(__func::__block_type))
815050b064fSChristopher Di Bella       return &__f_;
816050b064fSChristopher Di Bella     return (const void*)nullptr;
817050b064fSChristopher Di Bella   }
818050b064fSChristopher Di Bella 
8196cc8d54aSLouis Dionne   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const std::type_info& target_type() const _NOEXCEPT {
8206cc8d54aSLouis Dionne     return typeid(__func::__block_type);
8216cc8d54aSLouis Dionne   }
822ba87515fSNikolas Klauser #    endif // _LIBCPP_HAS_RTTI
823050b064fSChristopher Di Bella };
824050b064fSChristopher Di Bella 
8250e4802bfSLouis Dionne #  endif // _LIBCPP_HAS_EXTENSION_BLOCKS
826050b064fSChristopher Di Bella 
827d2b0df35SNikolas Klauser } // namespace __function
828050b064fSChristopher Di Bella 
829050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
830050b064fSChristopher Di Bella class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
831050b064fSChristopher Di Bella     : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>,
8329783f28cSLouis Dionne       public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)> {
833050b064fSChristopher Di Bella #  ifndef _LIBCPP_ABI_OPTIMIZED_FUNCTION
834050b064fSChristopher Di Bella   typedef __function::__value_func<_Rp(_ArgTypes...)> __func;
835050b064fSChristopher Di Bella #  else
836050b064fSChristopher Di Bella   typedef __function::__policy_func<_Rp(_ArgTypes...)> __func;
837050b064fSChristopher Di Bella #  endif
838050b064fSChristopher Di Bella 
839050b064fSChristopher Di Bella   __func __f_;
840050b064fSChristopher Di Bella 
8419783f28cSLouis Dionne   template <class _Fp,
842*0fa05456SNikolas Klauser             bool = _And<_IsNotSame<__remove_cvref_t<_Fp>, function>, __is_invocable<_Fp, _ArgTypes...> >::value>
843050b064fSChristopher Di Bella   struct __callable;
844050b064fSChristopher Di Bella   template <class _Fp>
8459783f28cSLouis Dionne   struct __callable<_Fp, true> {
8469783f28cSLouis Dionne     static const bool value =
847*0fa05456SNikolas Klauser         is_void<_Rp>::value || __is_core_convertible<__invoke_result_t<_Fp, _ArgTypes...>, _Rp>::value;
848050b064fSChristopher Di Bella   };
849050b064fSChristopher Di Bella   template <class _Fp>
8509783f28cSLouis Dionne   struct __callable<_Fp, false> {
851050b064fSChristopher Di Bella     static const bool value = false;
852050b064fSChristopher Di Bella   };
853050b064fSChristopher Di Bella 
854050b064fSChristopher Di Bella   template <class _Fp>
855f6958523SNikolas Klauser   using _EnableIfLValueCallable _LIBCPP_NODEBUG = __enable_if_t<__callable<_Fp&>::value>;
8569783f28cSLouis Dionne 
857050b064fSChristopher Di Bella public:
858050b064fSChristopher Di Bella   typedef _Rp result_type;
859050b064fSChristopher Di Bella 
860050b064fSChristopher Di Bella   // construct/copy/destroy:
8619783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI function() _NOEXCEPT {}
862dab6463eSLoS   _LIBCPP_HIDE_FROM_ABI function(nullptr_t) _NOEXCEPT {}
86383ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function(const function&);
86483ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function(function&&) _NOEXCEPT;
865050b064fSChristopher Di Bella   template <class _Fp, class = _EnableIfLValueCallable<_Fp>>
86683ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function(_Fp);
867050b064fSChristopher Di Bella 
868050b064fSChristopher Di Bella #  if _LIBCPP_STD_VER <= 14
869050b064fSChristopher Di Bella   template <class _Alloc>
8709783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc&) _NOEXCEPT {}
871050b064fSChristopher Di Bella   template <class _Alloc>
8729783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPT {}
873050b064fSChristopher Di Bella   template <class _Alloc>
87483ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc&, const function&);
875050b064fSChristopher Di Bella   template <class _Alloc>
87683ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc&, function&&);
877050b064fSChristopher Di Bella   template <class _Fp, class _Alloc, class = _EnableIfLValueCallable<_Fp>>
87883ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc& __a, _Fp __f);
879050b064fSChristopher Di Bella #  endif
880050b064fSChristopher Di Bella 
88183ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function& operator=(const function&);
88283ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function& operator=(function&&) _NOEXCEPT;
88383ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function& operator=(nullptr_t) _NOEXCEPT;
884173476eaSNikolas Klauser   template <class _Fp, class = _EnableIfLValueCallable<__decay_t<_Fp>>>
88583ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI function& operator=(_Fp&&);
886050b064fSChristopher Di Bella 
88783ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI ~function();
888050b064fSChristopher Di Bella 
889050b064fSChristopher Di Bella   // function modifiers:
89083ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void swap(function&) _NOEXCEPT;
891050b064fSChristopher Di Bella 
892050b064fSChristopher Di Bella #  if _LIBCPP_STD_VER <= 14
893050b064fSChristopher Di Bella   template <class _Fp, class _Alloc>
8949783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void assign(_Fp&& __f, const _Alloc& __a) {
8959783f28cSLouis Dionne     function(allocator_arg, __a, std::forward<_Fp>(__f)).swap(*this);
8969783f28cSLouis Dionne   }
897050b064fSChristopher Di Bella #  endif
898050b064fSChristopher Di Bella 
899050b064fSChristopher Di Bella   // function capacity:
9009783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return static_cast<bool>(__f_); }
901050b064fSChristopher Di Bella 
902050b064fSChristopher Di Bella   // deleted overloads close possible hole in the type system
903050b064fSChristopher Di Bella   template <class _R2, class... _ArgTypes2>
904050b064fSChristopher Di Bella   bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete;
9059a6ca673SHristo Hristov #  if _LIBCPP_STD_VER <= 17
906050b064fSChristopher Di Bella   template <class _R2, class... _ArgTypes2>
907050b064fSChristopher Di Bella   bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete;
9089a6ca673SHristo Hristov #  endif
9099783f28cSLouis Dionne 
910050b064fSChristopher Di Bella public:
911050b064fSChristopher Di Bella   // function invocation:
91283ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes...) const;
913050b064fSChristopher Di Bella 
914ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
915050b064fSChristopher Di Bella   // function target access:
91683ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT;
91783ce1397SNikolas Klauser   template <typename _Tp>
91883ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI _Tp* target() _NOEXCEPT;
91983ce1397SNikolas Klauser   template <typename _Tp>
92083ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT;
921ba87515fSNikolas Klauser #  endif // _LIBCPP_HAS_RTTI
922050b064fSChristopher Di Bella };
923050b064fSChristopher Di Bella 
92401666904SLouis Dionne #  if _LIBCPP_STD_VER >= 17
925050b064fSChristopher Di Bella template <class _Rp, class... _Ap>
926050b064fSChristopher Di Bella function(_Rp (*)(_Ap...)) -> function<_Rp(_Ap...)>;
927050b064fSChristopher Di Bella 
928050b064fSChristopher Di Bella template <class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type>
929050b064fSChristopher Di Bella function(_Fp) -> function<_Stripped>;
93001666904SLouis Dionne #  endif // _LIBCPP_STD_VER >= 17
931050b064fSChristopher Di Bella 
932050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
933050b064fSChristopher Di Bella function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {}
934050b064fSChristopher Di Bella 
935050b064fSChristopher Di Bella #  if _LIBCPP_STD_VER <= 14
936050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
937050b064fSChristopher Di Bella template <class _Alloc>
9389783f28cSLouis Dionne function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, const function& __f) : __f_(__f.__f_) {}
939050b064fSChristopher Di Bella #  endif
940050b064fSChristopher Di Bella 
941050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
9429783f28cSLouis Dionne function<_Rp(_ArgTypes...)>::function(function&& __f) _NOEXCEPT : __f_(std::move(__f.__f_)) {}
943050b064fSChristopher Di Bella 
944050b064fSChristopher Di Bella #  if _LIBCPP_STD_VER <= 14
945050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
946050b064fSChristopher Di Bella template <class _Alloc>
9479783f28cSLouis Dionne function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, function&& __f) : __f_(std::move(__f.__f_)) {}
948050b064fSChristopher Di Bella #  endif
949050b064fSChristopher Di Bella 
950050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
951050b064fSChristopher Di Bella template <class _Fp, class>
95277a00c0dSLouis Dionne function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(std::move(__f)) {}
953050b064fSChristopher Di Bella 
954050b064fSChristopher Di Bella #  if _LIBCPP_STD_VER <= 14
955050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
956050b064fSChristopher Di Bella template <class _Fp, class _Alloc, class>
9579783f28cSLouis Dionne function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, _Fp __f) : __f_(std::move(__f), __a) {}
958050b064fSChristopher Di Bella #  endif
959050b064fSChristopher Di Bella 
960050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
9619783f28cSLouis Dionne function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(const function& __f) {
962050b064fSChristopher Di Bella   function(__f).swap(*this);
963050b064fSChristopher Di Bella   return *this;
964050b064fSChristopher Di Bella }
965050b064fSChristopher Di Bella 
966050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
9679783f28cSLouis Dionne function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT {
96877a00c0dSLouis Dionne   __f_ = std::move(__f.__f_);
969050b064fSChristopher Di Bella   return *this;
970050b064fSChristopher Di Bella }
971050b064fSChristopher Di Bella 
972050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
9739783f28cSLouis Dionne function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT {
974050b064fSChristopher Di Bella   __f_ = nullptr;
975050b064fSChristopher Di Bella   return *this;
976050b064fSChristopher Di Bella }
977050b064fSChristopher Di Bella 
978050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
979050b064fSChristopher Di Bella template <class _Fp, class>
9809783f28cSLouis Dionne function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) {
98177a00c0dSLouis Dionne   function(std::forward<_Fp>(__f)).swap(*this);
982050b064fSChristopher Di Bella   return *this;
983050b064fSChristopher Di Bella }
984050b064fSChristopher Di Bella 
985050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
986050b064fSChristopher Di Bella function<_Rp(_ArgTypes...)>::~function() {}
987050b064fSChristopher Di Bella 
988050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
9899783f28cSLouis Dionne void function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT {
990050b064fSChristopher Di Bella   __f_.swap(__f.__f_);
991050b064fSChristopher Di Bella }
992050b064fSChristopher Di Bella 
993050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
9949783f28cSLouis Dionne _Rp function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const {
99577a00c0dSLouis Dionne   return __f_(std::forward<_ArgTypes>(__arg)...);
996050b064fSChristopher Di Bella }
997050b064fSChristopher Di Bella 
998ba87515fSNikolas Klauser #  if _LIBCPP_HAS_RTTI
999050b064fSChristopher Di Bella 
1000050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
10019783f28cSLouis Dionne const std::type_info& function<_Rp(_ArgTypes...)>::target_type() const _NOEXCEPT {
1002050b064fSChristopher Di Bella   return __f_.target_type();
1003050b064fSChristopher Di Bella }
1004050b064fSChristopher Di Bella 
1005050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
1006050b064fSChristopher Di Bella template <typename _Tp>
10079783f28cSLouis Dionne _Tp* function<_Rp(_ArgTypes...)>::target() _NOEXCEPT {
1008050b064fSChristopher Di Bella   return (_Tp*)(__f_.template target<_Tp>());
1009050b064fSChristopher Di Bella }
1010050b064fSChristopher Di Bella 
1011050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
1012050b064fSChristopher Di Bella template <typename _Tp>
10139783f28cSLouis Dionne const _Tp* function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT {
1014050b064fSChristopher Di Bella   return __f_.template target<_Tp>();
1015050b064fSChristopher Di Bella }
1016050b064fSChristopher Di Bella 
1017ba87515fSNikolas Klauser #  endif // _LIBCPP_HAS_RTTI
1018050b064fSChristopher Di Bella 
1019050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
10209783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI bool operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {
10219783f28cSLouis Dionne   return !__f;
10229783f28cSLouis Dionne }
1023050b064fSChristopher Di Bella 
10249a6ca673SHristo Hristov #  if _LIBCPP_STD_VER <= 17
10259a6ca673SHristo Hristov 
1026050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
10279783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI bool operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {
10289783f28cSLouis Dionne   return !__f;
10299783f28cSLouis Dionne }
1030050b064fSChristopher Di Bella 
1031050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
10329783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {
10339783f28cSLouis Dionne   return (bool)__f;
10349783f28cSLouis Dionne }
1035050b064fSChristopher Di Bella 
1036050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
10379783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI bool operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {
10389783f28cSLouis Dionne   return (bool)__f;
10399783f28cSLouis Dionne }
1040050b064fSChristopher Di Bella 
10419a6ca673SHristo Hristov #  endif // _LIBCPP_STD_VER <= 17
10429a6ca673SHristo Hristov 
1043050b064fSChristopher Di Bella template <class _Rp, class... _ArgTypes>
10449783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI void swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) _NOEXCEPT {
10459783f28cSLouis Dionne   return __x.swap(__y);
10469783f28cSLouis Dionne }
1047050b064fSChristopher Di Bella 
1048dbe60caaSNikolas Klauser _LIBCPP_END_NAMESPACE_STD
1049050b064fSChristopher Di Bella 
1050c475e31aSNikolas Klauser #endif // _LIBCPP_CXX03_LANG
1051050b064fSChristopher Di Bella 
10527b462251SLouis Dionne _LIBCPP_POP_MACROS
10537b462251SLouis Dionne 
1054050b064fSChristopher Di Bella #endif // _LIBCPP___FUNCTIONAL_FUNCTION_H
1055