17a984708SDavid Chisnall// -*- C++ -*-
27a984708SDavid Chisnall//===----------------------------------------------------------------------===//
37a984708SDavid Chisnall//
47a984708SDavid Chisnall//                     The LLVM Compiler Infrastructure
57a984708SDavid Chisnall//
67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open
77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details.
87a984708SDavid Chisnall//
97a984708SDavid Chisnall//===----------------------------------------------------------------------===//
107a984708SDavid Chisnall
117a984708SDavid Chisnall#ifndef _LIBCPP_FUNCTIONAL_03
127a984708SDavid Chisnall#define _LIBCPP_FUNCTIONAL_03
137a984708SDavid Chisnall
147a984708SDavid Chisnall// manual variadic expansion for <functional>
157a984708SDavid Chisnall
167a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
177a984708SDavid Chisnall#pragma GCC system_header
187a984708SDavid Chisnall#endif
197a984708SDavid Chisnall
209729cf09SDimitry Andricnamespace __function {
217a984708SDavid Chisnall
227a984708SDavid Chisnalltemplate<class _Fp> class __base;
237a984708SDavid Chisnall
2494e3ee44SDavid Chisnalltemplate<class _Rp>
2594e3ee44SDavid Chisnallclass __base<_Rp()>
267a984708SDavid Chisnall{
277a984708SDavid Chisnall    __base(const __base&);
287a984708SDavid Chisnall    __base& operator=(const __base&);
297a984708SDavid Chisnallpublic:
307a984708SDavid Chisnall    __base() {}
317a984708SDavid Chisnall    virtual ~__base() {}
327a984708SDavid Chisnall    virtual __base* __clone() const = 0;
337a984708SDavid Chisnall    virtual void __clone(__base*) const = 0;
347a984708SDavid Chisnall    virtual void destroy() = 0;
357a984708SDavid Chisnall    virtual void destroy_deallocate() = 0;
3694e3ee44SDavid Chisnall    virtual _Rp operator()() = 0;
377a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
387a984708SDavid Chisnall    virtual const void* target(const type_info&) const = 0;
397a984708SDavid Chisnall    virtual const std::type_info& target_type() const = 0;
407a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
417a984708SDavid Chisnall};
427a984708SDavid Chisnall
4394e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
4494e3ee44SDavid Chisnallclass __base<_Rp(_A0)>
457a984708SDavid Chisnall{
467a984708SDavid Chisnall    __base(const __base&);
477a984708SDavid Chisnall    __base& operator=(const __base&);
487a984708SDavid Chisnallpublic:
497a984708SDavid Chisnall    __base() {}
507a984708SDavid Chisnall    virtual ~__base() {}
517a984708SDavid Chisnall    virtual __base* __clone() const = 0;
527a984708SDavid Chisnall    virtual void __clone(__base*) const = 0;
537a984708SDavid Chisnall    virtual void destroy() = 0;
547a984708SDavid Chisnall    virtual void destroy_deallocate() = 0;
5594e3ee44SDavid Chisnall    virtual _Rp operator()(_A0) = 0;
567a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
577a984708SDavid Chisnall    virtual const void* target(const type_info&) const = 0;
587a984708SDavid Chisnall    virtual const std::type_info& target_type() const = 0;
597a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
607a984708SDavid Chisnall};
617a984708SDavid Chisnall
6294e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
6394e3ee44SDavid Chisnallclass __base<_Rp(_A0, _A1)>
647a984708SDavid Chisnall{
657a984708SDavid Chisnall    __base(const __base&);
667a984708SDavid Chisnall    __base& operator=(const __base&);
677a984708SDavid Chisnallpublic:
687a984708SDavid Chisnall    __base() {}
697a984708SDavid Chisnall    virtual ~__base() {}
707a984708SDavid Chisnall    virtual __base* __clone() const = 0;
717a984708SDavid Chisnall    virtual void __clone(__base*) const = 0;
727a984708SDavid Chisnall    virtual void destroy() = 0;
737a984708SDavid Chisnall    virtual void destroy_deallocate() = 0;
7494e3ee44SDavid Chisnall    virtual _Rp operator()(_A0, _A1) = 0;
757a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
767a984708SDavid Chisnall    virtual const void* target(const type_info&) const = 0;
777a984708SDavid Chisnall    virtual const std::type_info& target_type() const = 0;
787a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
797a984708SDavid Chisnall};
807a984708SDavid Chisnall
8194e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
8294e3ee44SDavid Chisnallclass __base<_Rp(_A0, _A1, _A2)>
837a984708SDavid Chisnall{
847a984708SDavid Chisnall    __base(const __base&);
857a984708SDavid Chisnall    __base& operator=(const __base&);
867a984708SDavid Chisnallpublic:
877a984708SDavid Chisnall    __base() {}
887a984708SDavid Chisnall    virtual ~__base() {}
897a984708SDavid Chisnall    virtual __base* __clone() const = 0;
907a984708SDavid Chisnall    virtual void __clone(__base*) const = 0;
917a984708SDavid Chisnall    virtual void destroy() = 0;
927a984708SDavid Chisnall    virtual void destroy_deallocate() = 0;
9394e3ee44SDavid Chisnall    virtual _Rp operator()(_A0, _A1, _A2) = 0;
947a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
957a984708SDavid Chisnall    virtual const void* target(const type_info&) const = 0;
967a984708SDavid Chisnall    virtual const std::type_info& target_type() const = 0;
977a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
987a984708SDavid Chisnall};
997a984708SDavid Chisnall
1007a984708SDavid Chisnalltemplate<class _FD, class _Alloc, class _FB> class __func;
1017a984708SDavid Chisnall
10294e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp>
10394e3ee44SDavid Chisnallclass __func<_Fp, _Alloc, _Rp()>
10494e3ee44SDavid Chisnall    : public  __base<_Rp()>
1057a984708SDavid Chisnall{
10694e3ee44SDavid Chisnall    __compressed_pair<_Fp, _Alloc> __f_;
1077a984708SDavid Chisnallpublic:
10894e3ee44SDavid Chisnall    explicit __func(_Fp __f) : __f_(_VSTD::move(__f)) {}
10994e3ee44SDavid Chisnall    explicit __func(_Fp __f, _Alloc __a) : __f_(_VSTD::move(__f), _VSTD::move(__a)) {}
11094e3ee44SDavid Chisnall    virtual __base<_Rp()>* __clone() const;
11194e3ee44SDavid Chisnall    virtual void __clone(__base<_Rp()>*) const;
1127a984708SDavid Chisnall    virtual void destroy();
1137a984708SDavid Chisnall    virtual void destroy_deallocate();
11494e3ee44SDavid Chisnall    virtual _Rp operator()();
1157a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
1167a984708SDavid Chisnall    virtual const void* target(const type_info&) const;
1177a984708SDavid Chisnall    virtual const std::type_info& target_type() const;
1187a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
1197a984708SDavid Chisnall};
1207a984708SDavid Chisnall
12194e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp>
12294e3ee44SDavid Chisnall__base<_Rp()>*
12394e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp()>::__clone() const
1247a984708SDavid Chisnall{
125854fa44bSDimitry Andric    typedef allocator_traits<_Alloc> __alloc_traits;
126854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
12794e3ee44SDavid Chisnall    _Ap __a(__f_.second());
12894e3ee44SDavid Chisnall    typedef __allocator_destructor<_Ap> _Dp;
12994e3ee44SDavid Chisnall    unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
1307a984708SDavid Chisnall    ::new (__hold.get()) __func(__f_.first(), _Alloc(__a));
1317a984708SDavid Chisnall    return __hold.release();
1327a984708SDavid Chisnall}
1337a984708SDavid Chisnall
13494e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp>
1357a984708SDavid Chisnallvoid
13694e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp()>::__clone(__base<_Rp()>* __p) const
1377a984708SDavid Chisnall{
1387a984708SDavid Chisnall    ::new (__p) __func(__f_.first(), __f_.second());
1397a984708SDavid Chisnall}
1407a984708SDavid Chisnall
14194e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp>
1427a984708SDavid Chisnallvoid
14394e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp()>::destroy()
1447a984708SDavid Chisnall{
14594e3ee44SDavid Chisnall    __f_.~__compressed_pair<_Fp, _Alloc>();
1467a984708SDavid Chisnall}
1477a984708SDavid Chisnall
14894e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp>
1497a984708SDavid Chisnallvoid
15094e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp()>::destroy_deallocate()
1517a984708SDavid Chisnall{
152854fa44bSDimitry Andric    typedef allocator_traits<_Alloc> __alloc_traits;
153854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
15494e3ee44SDavid Chisnall    _Ap __a(__f_.second());
15594e3ee44SDavid Chisnall    __f_.~__compressed_pair<_Fp, _Alloc>();
1567a984708SDavid Chisnall    __a.deallocate(this, 1);
1577a984708SDavid Chisnall}
1587a984708SDavid Chisnall
15994e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp>
16094e3ee44SDavid Chisnall_Rp
16194e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp()>::operator()()
1627a984708SDavid Chisnall{
163854fa44bSDimitry Andric    typedef __invoke_void_return_wrapper<_Rp> _Invoker;
164854fa44bSDimitry Andric    return _Invoker::__call(__f_.first());
1657a984708SDavid Chisnall}
1667a984708SDavid Chisnall
1677a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
1687a984708SDavid Chisnall
16994e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp>
1707a984708SDavid Chisnallconst void*
17194e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp()>::target(const type_info& __ti) const
1727a984708SDavid Chisnall{
17394e3ee44SDavid Chisnall    if (__ti == typeid(_Fp))
1747a984708SDavid Chisnall        return &__f_.first();
1757a984708SDavid Chisnall    return (const void*)0;
1767a984708SDavid Chisnall}
1777a984708SDavid Chisnall
17894e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp>
1797a984708SDavid Chisnallconst std::type_info&
18094e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp()>::target_type() const
1817a984708SDavid Chisnall{
18294e3ee44SDavid Chisnall    return typeid(_Fp);
1837a984708SDavid Chisnall}
1847a984708SDavid Chisnall
1857a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
1867a984708SDavid Chisnall
18794e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0>
18894e3ee44SDavid Chisnallclass __func<_Fp, _Alloc, _Rp(_A0)>
18994e3ee44SDavid Chisnall    : public  __base<_Rp(_A0)>
1907a984708SDavid Chisnall{
19194e3ee44SDavid Chisnall    __compressed_pair<_Fp, _Alloc> __f_;
1927a984708SDavid Chisnallpublic:
19394e3ee44SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f)) {}
19494e3ee44SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a)
1957a984708SDavid Chisnall        : __f_(_VSTD::move(__f), _VSTD::move(__a)) {}
19694e3ee44SDavid Chisnall    virtual __base<_Rp(_A0)>* __clone() const;
19794e3ee44SDavid Chisnall    virtual void __clone(__base<_Rp(_A0)>*) const;
1987a984708SDavid Chisnall    virtual void destroy();
1997a984708SDavid Chisnall    virtual void destroy_deallocate();
20094e3ee44SDavid Chisnall    virtual _Rp operator()(_A0);
2017a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
2027a984708SDavid Chisnall    virtual const void* target(const type_info&) const;
2037a984708SDavid Chisnall    virtual const std::type_info& target_type() const;
2047a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
2057a984708SDavid Chisnall};
2067a984708SDavid Chisnall
20794e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0>
20894e3ee44SDavid Chisnall__base<_Rp(_A0)>*
20994e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0)>::__clone() const
2107a984708SDavid Chisnall{
211854fa44bSDimitry Andric    typedef allocator_traits<_Alloc> __alloc_traits;
212854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
21394e3ee44SDavid Chisnall    _Ap __a(__f_.second());
21494e3ee44SDavid Chisnall    typedef __allocator_destructor<_Ap> _Dp;
21594e3ee44SDavid Chisnall    unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
2167a984708SDavid Chisnall    ::new (__hold.get()) __func(__f_.first(), _Alloc(__a));
2177a984708SDavid Chisnall    return __hold.release();
2187a984708SDavid Chisnall}
2197a984708SDavid Chisnall
22094e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0>
2217a984708SDavid Chisnallvoid
22294e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0)>::__clone(__base<_Rp(_A0)>* __p) const
2237a984708SDavid Chisnall{
2247a984708SDavid Chisnall    ::new (__p) __func(__f_.first(), __f_.second());
2257a984708SDavid Chisnall}
2267a984708SDavid Chisnall
22794e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0>
2287a984708SDavid Chisnallvoid
22994e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0)>::destroy()
2307a984708SDavid Chisnall{
23194e3ee44SDavid Chisnall    __f_.~__compressed_pair<_Fp, _Alloc>();
2327a984708SDavid Chisnall}
2337a984708SDavid Chisnall
23494e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0>
2357a984708SDavid Chisnallvoid
23694e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0)>::destroy_deallocate()
2377a984708SDavid Chisnall{
238854fa44bSDimitry Andric    typedef allocator_traits<_Alloc> __alloc_traits;
239854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
24094e3ee44SDavid Chisnall    _Ap __a(__f_.second());
24194e3ee44SDavid Chisnall    __f_.~__compressed_pair<_Fp, _Alloc>();
2427a984708SDavid Chisnall    __a.deallocate(this, 1);
2437a984708SDavid Chisnall}
2447a984708SDavid Chisnall
24594e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0>
24694e3ee44SDavid Chisnall_Rp
24794e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0)>::operator()(_A0 __a0)
2487a984708SDavid Chisnall{
249854fa44bSDimitry Andric    typedef __invoke_void_return_wrapper<_Rp> _Invoker;
250854fa44bSDimitry Andric    return _Invoker::__call(__f_.first(), __a0);
2517a984708SDavid Chisnall}
2527a984708SDavid Chisnall
2537a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
2547a984708SDavid Chisnall
25594e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0>
2567a984708SDavid Chisnallconst void*
25794e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0)>::target(const type_info& __ti) const
2587a984708SDavid Chisnall{
25994e3ee44SDavid Chisnall    if (__ti == typeid(_Fp))
2607a984708SDavid Chisnall        return &__f_.first();
2617a984708SDavid Chisnall    return (const void*)0;
2627a984708SDavid Chisnall}
2637a984708SDavid Chisnall
26494e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0>
2657a984708SDavid Chisnallconst std::type_info&
26694e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0)>::target_type() const
2677a984708SDavid Chisnall{
26894e3ee44SDavid Chisnall    return typeid(_Fp);
2697a984708SDavid Chisnall}
2707a984708SDavid Chisnall
2717a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
2727a984708SDavid Chisnall
27394e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
27494e3ee44SDavid Chisnallclass __func<_Fp, _Alloc, _Rp(_A0, _A1)>
27594e3ee44SDavid Chisnall    : public  __base<_Rp(_A0, _A1)>
2767a984708SDavid Chisnall{
27794e3ee44SDavid Chisnall    __compressed_pair<_Fp, _Alloc> __f_;
2787a984708SDavid Chisnallpublic:
27994e3ee44SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f)) {}
28094e3ee44SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a)
2817a984708SDavid Chisnall        : __f_(_VSTD::move(__f), _VSTD::move(__a)) {}
28294e3ee44SDavid Chisnall    virtual __base<_Rp(_A0, _A1)>* __clone() const;
28394e3ee44SDavid Chisnall    virtual void __clone(__base<_Rp(_A0, _A1)>*) const;
2847a984708SDavid Chisnall    virtual void destroy();
2857a984708SDavid Chisnall    virtual void destroy_deallocate();
28694e3ee44SDavid Chisnall    virtual _Rp operator()(_A0, _A1);
2877a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
2887a984708SDavid Chisnall    virtual const void* target(const type_info&) const;
2897a984708SDavid Chisnall    virtual const std::type_info& target_type() const;
2907a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
2917a984708SDavid Chisnall};
2927a984708SDavid Chisnall
29394e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
29494e3ee44SDavid Chisnall__base<_Rp(_A0, _A1)>*
29594e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone() const
2967a984708SDavid Chisnall{
297854fa44bSDimitry Andric    typedef allocator_traits<_Alloc> __alloc_traits;
298854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
29994e3ee44SDavid Chisnall    _Ap __a(__f_.second());
30094e3ee44SDavid Chisnall    typedef __allocator_destructor<_Ap> _Dp;
30194e3ee44SDavid Chisnall    unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
3027a984708SDavid Chisnall    ::new (__hold.get()) __func(__f_.first(), _Alloc(__a));
3037a984708SDavid Chisnall    return __hold.release();
3047a984708SDavid Chisnall}
3057a984708SDavid Chisnall
30694e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
3077a984708SDavid Chisnallvoid
30894e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone(__base<_Rp(_A0, _A1)>* __p) const
3097a984708SDavid Chisnall{
3107a984708SDavid Chisnall    ::new (__p) __func(__f_.first(), __f_.second());
3117a984708SDavid Chisnall}
3127a984708SDavid Chisnall
31394e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
3147a984708SDavid Chisnallvoid
31594e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy()
3167a984708SDavid Chisnall{
31794e3ee44SDavid Chisnall    __f_.~__compressed_pair<_Fp, _Alloc>();
3187a984708SDavid Chisnall}
3197a984708SDavid Chisnall
32094e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
3217a984708SDavid Chisnallvoid
32294e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy_deallocate()
3237a984708SDavid Chisnall{
324854fa44bSDimitry Andric    typedef allocator_traits<_Alloc> __alloc_traits;
325854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
32694e3ee44SDavid Chisnall    _Ap __a(__f_.second());
32794e3ee44SDavid Chisnall    __f_.~__compressed_pair<_Fp, _Alloc>();
3287a984708SDavid Chisnall    __a.deallocate(this, 1);
3297a984708SDavid Chisnall}
3307a984708SDavid Chisnall
33194e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
33294e3ee44SDavid Chisnall_Rp
33394e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1)
3347a984708SDavid Chisnall{
335854fa44bSDimitry Andric    typedef __invoke_void_return_wrapper<_Rp> _Invoker;
336854fa44bSDimitry Andric    return _Invoker::__call(__f_.first(), __a0, __a1);
3377a984708SDavid Chisnall}
3387a984708SDavid Chisnall
3397a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
3407a984708SDavid Chisnall
34194e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
3427a984708SDavid Chisnallconst void*
34394e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1)>::target(const type_info& __ti) const
3447a984708SDavid Chisnall{
34594e3ee44SDavid Chisnall    if (__ti == typeid(_Fp))
3467a984708SDavid Chisnall        return &__f_.first();
3477a984708SDavid Chisnall    return (const void*)0;
3487a984708SDavid Chisnall}
3497a984708SDavid Chisnall
35094e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
3517a984708SDavid Chisnallconst std::type_info&
35294e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1)>::target_type() const
3537a984708SDavid Chisnall{
35494e3ee44SDavid Chisnall    return typeid(_Fp);
3557a984708SDavid Chisnall}
3567a984708SDavid Chisnall
3577a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
3587a984708SDavid Chisnall
35994e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
36094e3ee44SDavid Chisnallclass __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>
36194e3ee44SDavid Chisnall    : public  __base<_Rp(_A0, _A1, _A2)>
3627a984708SDavid Chisnall{
36394e3ee44SDavid Chisnall    __compressed_pair<_Fp, _Alloc> __f_;
3647a984708SDavid Chisnallpublic:
36594e3ee44SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f)) {}
36694e3ee44SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a)
3677a984708SDavid Chisnall        : __f_(_VSTD::move(__f), _VSTD::move(__a)) {}
36894e3ee44SDavid Chisnall    virtual __base<_Rp(_A0, _A1, _A2)>* __clone() const;
36994e3ee44SDavid Chisnall    virtual void __clone(__base<_Rp(_A0, _A1, _A2)>*) const;
3707a984708SDavid Chisnall    virtual void destroy();
3717a984708SDavid Chisnall    virtual void destroy_deallocate();
37294e3ee44SDavid Chisnall    virtual _Rp operator()(_A0, _A1, _A2);
3737a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
3747a984708SDavid Chisnall    virtual const void* target(const type_info&) const;
3757a984708SDavid Chisnall    virtual const std::type_info& target_type() const;
3767a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
3777a984708SDavid Chisnall};
3787a984708SDavid Chisnall
37994e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
38094e3ee44SDavid Chisnall__base<_Rp(_A0, _A1, _A2)>*
38194e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone() const
3827a984708SDavid Chisnall{
383854fa44bSDimitry Andric    typedef allocator_traits<_Alloc> __alloc_traits;
384854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
38594e3ee44SDavid Chisnall    _Ap __a(__f_.second());
38694e3ee44SDavid Chisnall    typedef __allocator_destructor<_Ap> _Dp;
38794e3ee44SDavid Chisnall    unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
3887a984708SDavid Chisnall    ::new (__hold.get()) __func(__f_.first(), _Alloc(__a));
3897a984708SDavid Chisnall    return __hold.release();
3907a984708SDavid Chisnall}
3917a984708SDavid Chisnall
39294e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
3937a984708SDavid Chisnallvoid
39494e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone(__base<_Rp(_A0, _A1, _A2)>* __p) const
3957a984708SDavid Chisnall{
3967a984708SDavid Chisnall    ::new (__p) __func(__f_.first(), __f_.second());
3977a984708SDavid Chisnall}
3987a984708SDavid Chisnall
39994e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
4007a984708SDavid Chisnallvoid
40194e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy()
4027a984708SDavid Chisnall{
40394e3ee44SDavid Chisnall    __f_.~__compressed_pair<_Fp, _Alloc>();
4047a984708SDavid Chisnall}
4057a984708SDavid Chisnall
40694e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
4077a984708SDavid Chisnallvoid
40894e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy_deallocate()
4097a984708SDavid Chisnall{
410854fa44bSDimitry Andric    typedef allocator_traits<_Alloc> __alloc_traits;
411854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
41294e3ee44SDavid Chisnall    _Ap __a(__f_.second());
41394e3ee44SDavid Chisnall    __f_.~__compressed_pair<_Fp, _Alloc>();
4147a984708SDavid Chisnall    __a.deallocate(this, 1);
4157a984708SDavid Chisnall}
4167a984708SDavid Chisnall
41794e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
41894e3ee44SDavid Chisnall_Rp
41994e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2)
4207a984708SDavid Chisnall{
421854fa44bSDimitry Andric    typedef __invoke_void_return_wrapper<_Rp> _Invoker;
422854fa44bSDimitry Andric    return _Invoker::__call(__f_.first(), __a0, __a1, __a2);
4237a984708SDavid Chisnall}
4247a984708SDavid Chisnall
4257a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
4267a984708SDavid Chisnall
42794e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
4287a984708SDavid Chisnallconst void*
42994e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target(const type_info& __ti) const
4307a984708SDavid Chisnall{
43194e3ee44SDavid Chisnall    if (__ti == typeid(_Fp))
4327a984708SDavid Chisnall        return &__f_.first();
4337a984708SDavid Chisnall    return (const void*)0;
4347a984708SDavid Chisnall}
4357a984708SDavid Chisnall
43694e3ee44SDavid Chisnalltemplate<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
4377a984708SDavid Chisnallconst std::type_info&
43894e3ee44SDavid Chisnall__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target_type() const
4397a984708SDavid Chisnall{
44094e3ee44SDavid Chisnall    return typeid(_Fp);
4417a984708SDavid Chisnall}
4427a984708SDavid Chisnall
4437a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
4447a984708SDavid Chisnall
4457a984708SDavid Chisnall}  // __function
4467a984708SDavid Chisnall
44794e3ee44SDavid Chisnalltemplate<class _Rp>
448aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS function<_Rp()>
4497a984708SDavid Chisnall{
45094e3ee44SDavid Chisnall    typedef __function::__base<_Rp()> __base;
4517a984708SDavid Chisnall    aligned_storage<3*sizeof(void*)>::type __buf_;
4527a984708SDavid Chisnall    __base* __f_;
4537a984708SDavid Chisnall
4547a984708SDavid Chisnallpublic:
45594e3ee44SDavid Chisnall    typedef _Rp result_type;
4567a984708SDavid Chisnall
4577a984708SDavid Chisnall    // 20.7.16.2.1, construct/copy/destroy:
4587a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {}
4597a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {}
4607a984708SDavid Chisnall    function(const function&);
46194e3ee44SDavid Chisnall    template<class _Fp>
46294e3ee44SDavid Chisnall      function(_Fp,
46394e3ee44SDavid Chisnall               typename enable_if<!is_integral<_Fp>::value>::type* = 0);
4647a984708SDavid Chisnall
4657a984708SDavid Chisnall    template<class _Alloc>
4667a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
4677a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
4687a984708SDavid Chisnall    template<class _Alloc>
4697a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
4707a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
4717a984708SDavid Chisnall    template<class _Alloc>
4727a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&, const function&);
47394e3ee44SDavid Chisnall    template<class _Fp, class _Alloc>
47494e3ee44SDavid Chisnall      function(allocator_arg_t, const _Alloc& __a, _Fp __f,
47594e3ee44SDavid Chisnall               typename enable_if<!is_integral<_Fp>::value>::type* = 0);
4767a984708SDavid Chisnall
4777a984708SDavid Chisnall    function& operator=(const function&);
4787a984708SDavid Chisnall    function& operator=(nullptr_t);
47994e3ee44SDavid Chisnall    template<class _Fp>
4807a984708SDavid Chisnall      typename enable_if
4817a984708SDavid Chisnall      <
48294e3ee44SDavid Chisnall        !is_integral<_Fp>::value,
4837a984708SDavid Chisnall        function&
4847a984708SDavid Chisnall      >::type
48594e3ee44SDavid Chisnall      operator=(_Fp);
4867a984708SDavid Chisnall
4877a984708SDavid Chisnall    ~function();
4887a984708SDavid Chisnall
4897a984708SDavid Chisnall    // 20.7.16.2.2, function modifiers:
4907a984708SDavid Chisnall    void swap(function&);
49194e3ee44SDavid Chisnall    template<class _Fp, class _Alloc>
4927a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
49394e3ee44SDavid Chisnall      void assign(_Fp __f, const _Alloc& __a)
4947a984708SDavid Chisnall        {function(allocator_arg, __a, __f).swap(*this);}
4957a984708SDavid Chisnall
4967a984708SDavid Chisnall    // 20.7.16.2.3, function capacity:
4977a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;}
4987a984708SDavid Chisnall
4997a984708SDavid Chisnallprivate:
5007a984708SDavid Chisnall    // deleted overloads close possible hole in the type system
5017a984708SDavid Chisnall    template<class _R2>
5027a984708SDavid Chisnall      bool operator==(const function<_R2()>&) const;// = delete;
5037a984708SDavid Chisnall    template<class _R2>
5047a984708SDavid Chisnall      bool operator!=(const function<_R2()>&) const;// = delete;
5057a984708SDavid Chisnallpublic:
5067a984708SDavid Chisnall    // 20.7.16.2.4, function invocation:
50794e3ee44SDavid Chisnall    _Rp operator()() const;
5087a984708SDavid Chisnall
5097a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
5107a984708SDavid Chisnall    // 20.7.16.2.5, function target access:
5117a984708SDavid Chisnall    const std::type_info& target_type() const;
51294e3ee44SDavid Chisnall    template <typename _Tp> _Tp* target();
51394e3ee44SDavid Chisnall    template <typename _Tp> const _Tp* target() const;
5147a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
5157a984708SDavid Chisnall};
5167a984708SDavid Chisnall
51794e3ee44SDavid Chisnalltemplate<class _Rp>
51894e3ee44SDavid Chisnallfunction<_Rp()>::function(const function& __f)
5197a984708SDavid Chisnall{
5207a984708SDavid Chisnall    if (__f.__f_ == 0)
5217a984708SDavid Chisnall        __f_ = 0;
5227a984708SDavid Chisnall    else if (__f.__f_ == (const __base*)&__f.__buf_)
5237a984708SDavid Chisnall    {
5247a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
5257a984708SDavid Chisnall        __f.__f_->__clone(__f_);
5267a984708SDavid Chisnall    }
5277a984708SDavid Chisnall    else
5287a984708SDavid Chisnall        __f_ = __f.__f_->__clone();
5297a984708SDavid Chisnall}
5307a984708SDavid Chisnall
53194e3ee44SDavid Chisnalltemplate<class _Rp>
5327a984708SDavid Chisnalltemplate<class _Alloc>
53394e3ee44SDavid Chisnallfunction<_Rp()>::function(allocator_arg_t, const _Alloc&, const function& __f)
5347a984708SDavid Chisnall{
5357a984708SDavid Chisnall    if (__f.__f_ == 0)
5367a984708SDavid Chisnall        __f_ = 0;
5377a984708SDavid Chisnall    else if (__f.__f_ == (const __base*)&__f.__buf_)
5387a984708SDavid Chisnall    {
5397a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
5407a984708SDavid Chisnall        __f.__f_->__clone(__f_);
5417a984708SDavid Chisnall    }
5427a984708SDavid Chisnall    else
5437a984708SDavid Chisnall        __f_ = __f.__f_->__clone();
5447a984708SDavid Chisnall}
5457a984708SDavid Chisnall
54694e3ee44SDavid Chisnalltemplate<class _Rp>
54794e3ee44SDavid Chisnalltemplate <class _Fp>
54894e3ee44SDavid Chisnallfunction<_Rp()>::function(_Fp __f,
54994e3ee44SDavid Chisnall                                     typename enable_if<!is_integral<_Fp>::value>::type*)
5507a984708SDavid Chisnall    : __f_(0)
5517a984708SDavid Chisnall{
5529729cf09SDimitry Andric    if (__function::__not_null(__f))
5537a984708SDavid Chisnall    {
55494e3ee44SDavid Chisnall        typedef __function::__func<_Fp, allocator<_Fp>, _Rp()> _FF;
5557a984708SDavid Chisnall        if (sizeof(_FF) <= sizeof(__buf_))
5567a984708SDavid Chisnall        {
5577a984708SDavid Chisnall            __f_ = (__base*)&__buf_;
5587a984708SDavid Chisnall            ::new (__f_) _FF(__f);
5597a984708SDavid Chisnall        }
5607a984708SDavid Chisnall        else
5617a984708SDavid Chisnall        {
56294e3ee44SDavid Chisnall            typedef allocator<_FF> _Ap;
56394e3ee44SDavid Chisnall            _Ap __a;
56494e3ee44SDavid Chisnall            typedef __allocator_destructor<_Ap> _Dp;
56594e3ee44SDavid Chisnall            unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
56694e3ee44SDavid Chisnall            ::new (__hold.get()) _FF(__f, allocator<_Fp>(__a));
5677a984708SDavid Chisnall            __f_ = __hold.release();
5687a984708SDavid Chisnall        }
5697a984708SDavid Chisnall    }
5707a984708SDavid Chisnall}
5717a984708SDavid Chisnall
57294e3ee44SDavid Chisnalltemplate<class _Rp>
57394e3ee44SDavid Chisnalltemplate <class _Fp, class _Alloc>
57494e3ee44SDavid Chisnallfunction<_Rp()>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f,
57594e3ee44SDavid Chisnall                                     typename enable_if<!is_integral<_Fp>::value>::type*)
5767a984708SDavid Chisnall    : __f_(0)
5777a984708SDavid Chisnall{
5787a984708SDavid Chisnall    typedef allocator_traits<_Alloc> __alloc_traits;
5799729cf09SDimitry Andric    if (__function::__not_null(__f))
5807a984708SDavid Chisnall    {
58194e3ee44SDavid Chisnall        typedef __function::__func<_Fp, _Alloc, _Rp()> _FF;
5827a984708SDavid Chisnall        if (sizeof(_FF) <= sizeof(__buf_))
5837a984708SDavid Chisnall        {
5847a984708SDavid Chisnall            __f_ = (__base*)&__buf_;
585854fa44bSDimitry Andric            ::new (__f_) _FF(__f, __a0);
5867a984708SDavid Chisnall        }
5877a984708SDavid Chisnall        else
5887a984708SDavid Chisnall        {
589854fa44bSDimitry Andric            typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
59094e3ee44SDavid Chisnall            _Ap __a(__a0);
59194e3ee44SDavid Chisnall            typedef __allocator_destructor<_Ap> _Dp;
59294e3ee44SDavid Chisnall            unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
5937a984708SDavid Chisnall            ::new (__hold.get()) _FF(__f, _Alloc(__a));
5947a984708SDavid Chisnall            __f_ = __hold.release();
5957a984708SDavid Chisnall        }
5967a984708SDavid Chisnall    }
5977a984708SDavid Chisnall}
5987a984708SDavid Chisnall
59994e3ee44SDavid Chisnalltemplate<class _Rp>
60094e3ee44SDavid Chisnallfunction<_Rp()>&
60194e3ee44SDavid Chisnallfunction<_Rp()>::operator=(const function& __f)
6027a984708SDavid Chisnall{
603*4ba319b5SDimitry Andric    if (__f)
6047a984708SDavid Chisnall        function(__f).swap(*this);
605*4ba319b5SDimitry Andric    else
606*4ba319b5SDimitry Andric        *this = nullptr;
6077a984708SDavid Chisnall    return *this;
6087a984708SDavid Chisnall}
6097a984708SDavid Chisnall
61094e3ee44SDavid Chisnalltemplate<class _Rp>
61194e3ee44SDavid Chisnallfunction<_Rp()>&
61294e3ee44SDavid Chisnallfunction<_Rp()>::operator=(nullptr_t)
6137a984708SDavid Chisnall{
614*4ba319b5SDimitry Andric    __base* __t = __f_;
6157a984708SDavid Chisnall    __f_ = 0;
616*4ba319b5SDimitry Andric    if (__t == (__base*)&__buf_)
617*4ba319b5SDimitry Andric        __t->destroy();
618*4ba319b5SDimitry Andric    else if (__t)
619*4ba319b5SDimitry Andric        __t->destroy_deallocate();
620854fa44bSDimitry Andric    return *this;
6217a984708SDavid Chisnall}
6227a984708SDavid Chisnall
62394e3ee44SDavid Chisnalltemplate<class _Rp>
62494e3ee44SDavid Chisnalltemplate <class _Fp>
6257a984708SDavid Chisnalltypename enable_if
6267a984708SDavid Chisnall<
62794e3ee44SDavid Chisnall    !is_integral<_Fp>::value,
62894e3ee44SDavid Chisnall    function<_Rp()>&
6297a984708SDavid Chisnall>::type
63094e3ee44SDavid Chisnallfunction<_Rp()>::operator=(_Fp __f)
6317a984708SDavid Chisnall{
6327a984708SDavid Chisnall    function(_VSTD::move(__f)).swap(*this);
6337a984708SDavid Chisnall    return *this;
6347a984708SDavid Chisnall}
6357a984708SDavid Chisnall
63694e3ee44SDavid Chisnalltemplate<class _Rp>
63794e3ee44SDavid Chisnallfunction<_Rp()>::~function()
6387a984708SDavid Chisnall{
6397a984708SDavid Chisnall    if (__f_ == (__base*)&__buf_)
6407a984708SDavid Chisnall        __f_->destroy();
6417a984708SDavid Chisnall    else if (__f_)
6427a984708SDavid Chisnall        __f_->destroy_deallocate();
6437a984708SDavid Chisnall}
6447a984708SDavid Chisnall
64594e3ee44SDavid Chisnalltemplate<class _Rp>
6467a984708SDavid Chisnallvoid
64794e3ee44SDavid Chisnallfunction<_Rp()>::swap(function& __f)
6487a984708SDavid Chisnall{
649aed8d94eSDimitry Andric    if (_VSTD::addressof(__f) == this)
650aed8d94eSDimitry Andric      return;
6517a984708SDavid Chisnall    if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
6527a984708SDavid Chisnall    {
6537a984708SDavid Chisnall        typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
6547a984708SDavid Chisnall        __base* __t = (__base*)&__tempbuf;
6557a984708SDavid Chisnall        __f_->__clone(__t);
6567a984708SDavid Chisnall        __f_->destroy();
6577a984708SDavid Chisnall        __f_ = 0;
6587a984708SDavid Chisnall        __f.__f_->__clone((__base*)&__buf_);
6597a984708SDavid Chisnall        __f.__f_->destroy();
6607a984708SDavid Chisnall        __f.__f_ = 0;
6617a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
6627a984708SDavid Chisnall        __t->__clone((__base*)&__f.__buf_);
6637a984708SDavid Chisnall        __t->destroy();
6647a984708SDavid Chisnall        __f.__f_ = (__base*)&__f.__buf_;
6657a984708SDavid Chisnall    }
6667a984708SDavid Chisnall    else if (__f_ == (__base*)&__buf_)
6677a984708SDavid Chisnall    {
6687a984708SDavid Chisnall        __f_->__clone((__base*)&__f.__buf_);
6697a984708SDavid Chisnall        __f_->destroy();
6707a984708SDavid Chisnall        __f_ = __f.__f_;
6717a984708SDavid Chisnall        __f.__f_ = (__base*)&__f.__buf_;
6727a984708SDavid Chisnall    }
6737a984708SDavid Chisnall    else if (__f.__f_ == (__base*)&__f.__buf_)
6747a984708SDavid Chisnall    {
6757a984708SDavid Chisnall        __f.__f_->__clone((__base*)&__buf_);
6767a984708SDavid Chisnall        __f.__f_->destroy();
6777a984708SDavid Chisnall        __f.__f_ = __f_;
6787a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
6797a984708SDavid Chisnall    }
6807a984708SDavid Chisnall    else
6817a984708SDavid Chisnall        _VSTD::swap(__f_, __f.__f_);
6827a984708SDavid Chisnall}
6837a984708SDavid Chisnall
68494e3ee44SDavid Chisnalltemplate<class _Rp>
68594e3ee44SDavid Chisnall_Rp
68694e3ee44SDavid Chisnallfunction<_Rp()>::operator()() const
6877a984708SDavid Chisnall{
6887a984708SDavid Chisnall    if (__f_ == 0)
689aed8d94eSDimitry Andric        __throw_bad_function_call();
6907a984708SDavid Chisnall    return (*__f_)();
6917a984708SDavid Chisnall}
6927a984708SDavid Chisnall
6937a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
6947a984708SDavid Chisnall
69594e3ee44SDavid Chisnalltemplate<class _Rp>
6967a984708SDavid Chisnallconst std::type_info&
69794e3ee44SDavid Chisnallfunction<_Rp()>::target_type() const
6987a984708SDavid Chisnall{
6997a984708SDavid Chisnall    if (__f_ == 0)
7007a984708SDavid Chisnall        return typeid(void);
7017a984708SDavid Chisnall    return __f_->target_type();
7027a984708SDavid Chisnall}
7037a984708SDavid Chisnall
70494e3ee44SDavid Chisnalltemplate<class _Rp>
70594e3ee44SDavid Chisnalltemplate <typename _Tp>
70694e3ee44SDavid Chisnall_Tp*
70794e3ee44SDavid Chisnallfunction<_Rp()>::target()
7087a984708SDavid Chisnall{
7097a984708SDavid Chisnall    if (__f_ == 0)
71094e3ee44SDavid Chisnall        return (_Tp*)0;
71124d58133SDimitry Andric    return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
7127a984708SDavid Chisnall}
7137a984708SDavid Chisnall
71494e3ee44SDavid Chisnalltemplate<class _Rp>
71594e3ee44SDavid Chisnalltemplate <typename _Tp>
71694e3ee44SDavid Chisnallconst _Tp*
71794e3ee44SDavid Chisnallfunction<_Rp()>::target() const
7187a984708SDavid Chisnall{
7197a984708SDavid Chisnall    if (__f_ == 0)
72094e3ee44SDavid Chisnall        return (const _Tp*)0;
72194e3ee44SDavid Chisnall    return (const _Tp*)__f_->target(typeid(_Tp));
7227a984708SDavid Chisnall}
7237a984708SDavid Chisnall
7247a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
7257a984708SDavid Chisnall
72694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
727aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS function<_Rp(_A0)>
72894e3ee44SDavid Chisnall    : public unary_function<_A0, _Rp>
7297a984708SDavid Chisnall{
73094e3ee44SDavid Chisnall    typedef __function::__base<_Rp(_A0)> __base;
7317a984708SDavid Chisnall    aligned_storage<3*sizeof(void*)>::type __buf_;
7327a984708SDavid Chisnall    __base* __f_;
7337a984708SDavid Chisnall
7347a984708SDavid Chisnallpublic:
73594e3ee44SDavid Chisnall    typedef _Rp result_type;
7367a984708SDavid Chisnall
7377a984708SDavid Chisnall    // 20.7.16.2.1, construct/copy/destroy:
7387a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {}
7397a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {}
7407a984708SDavid Chisnall    function(const function&);
74194e3ee44SDavid Chisnall    template<class _Fp>
74294e3ee44SDavid Chisnall      function(_Fp,
74394e3ee44SDavid Chisnall               typename enable_if<!is_integral<_Fp>::value>::type* = 0);
7447a984708SDavid Chisnall
7457a984708SDavid Chisnall    template<class _Alloc>
7467a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
7477a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
7487a984708SDavid Chisnall    template<class _Alloc>
7497a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
7507a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
7517a984708SDavid Chisnall    template<class _Alloc>
7527a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&, const function&);
75394e3ee44SDavid Chisnall    template<class _Fp, class _Alloc>
75494e3ee44SDavid Chisnall      function(allocator_arg_t, const _Alloc& __a, _Fp __f,
75594e3ee44SDavid Chisnall               typename enable_if<!is_integral<_Fp>::value>::type* = 0);
7567a984708SDavid Chisnall
7577a984708SDavid Chisnall    function& operator=(const function&);
7587a984708SDavid Chisnall    function& operator=(nullptr_t);
75994e3ee44SDavid Chisnall    template<class _Fp>
7607a984708SDavid Chisnall      typename enable_if
7617a984708SDavid Chisnall      <
76294e3ee44SDavid Chisnall        !is_integral<_Fp>::value,
7637a984708SDavid Chisnall        function&
7647a984708SDavid Chisnall      >::type
76594e3ee44SDavid Chisnall      operator=(_Fp);
7667a984708SDavid Chisnall
7677a984708SDavid Chisnall    ~function();
7687a984708SDavid Chisnall
7697a984708SDavid Chisnall    // 20.7.16.2.2, function modifiers:
7707a984708SDavid Chisnall    void swap(function&);
77194e3ee44SDavid Chisnall    template<class _Fp, class _Alloc>
7727a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
77394e3ee44SDavid Chisnall      void assign(_Fp __f, const _Alloc& __a)
7747a984708SDavid Chisnall        {function(allocator_arg, __a, __f).swap(*this);}
7757a984708SDavid Chisnall
7767a984708SDavid Chisnall    // 20.7.16.2.3, function capacity:
7777a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;}
7787a984708SDavid Chisnall
7797a984708SDavid Chisnallprivate:
7807a984708SDavid Chisnall    // deleted overloads close possible hole in the type system
7817a984708SDavid Chisnall    template<class _R2, class _B0>
7827a984708SDavid Chisnall      bool operator==(const function<_R2(_B0)>&) const;// = delete;
7837a984708SDavid Chisnall    template<class _R2, class _B0>
7847a984708SDavid Chisnall      bool operator!=(const function<_R2(_B0)>&) const;// = delete;
7857a984708SDavid Chisnallpublic:
7867a984708SDavid Chisnall    // 20.7.16.2.4, function invocation:
78794e3ee44SDavid Chisnall    _Rp operator()(_A0) const;
7887a984708SDavid Chisnall
7897a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
7907a984708SDavid Chisnall    // 20.7.16.2.5, function target access:
7917a984708SDavid Chisnall    const std::type_info& target_type() const;
79294e3ee44SDavid Chisnall    template <typename _Tp> _Tp* target();
79394e3ee44SDavid Chisnall    template <typename _Tp> const _Tp* target() const;
7947a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
7957a984708SDavid Chisnall};
7967a984708SDavid Chisnall
79794e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
79894e3ee44SDavid Chisnallfunction<_Rp(_A0)>::function(const function& __f)
7997a984708SDavid Chisnall{
8007a984708SDavid Chisnall    if (__f.__f_ == 0)
8017a984708SDavid Chisnall        __f_ = 0;
8027a984708SDavid Chisnall    else if (__f.__f_ == (const __base*)&__f.__buf_)
8037a984708SDavid Chisnall    {
8047a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
8057a984708SDavid Chisnall        __f.__f_->__clone(__f_);
8067a984708SDavid Chisnall    }
8077a984708SDavid Chisnall    else
8087a984708SDavid Chisnall        __f_ = __f.__f_->__clone();
8097a984708SDavid Chisnall}
8107a984708SDavid Chisnall
81194e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
8127a984708SDavid Chisnalltemplate<class _Alloc>
81394e3ee44SDavid Chisnallfunction<_Rp(_A0)>::function(allocator_arg_t, const _Alloc&, const function& __f)
8147a984708SDavid Chisnall{
8157a984708SDavid Chisnall    if (__f.__f_ == 0)
8167a984708SDavid Chisnall        __f_ = 0;
8177a984708SDavid Chisnall    else if (__f.__f_ == (const __base*)&__f.__buf_)
8187a984708SDavid Chisnall    {
8197a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
8207a984708SDavid Chisnall        __f.__f_->__clone(__f_);
8217a984708SDavid Chisnall    }
8227a984708SDavid Chisnall    else
8237a984708SDavid Chisnall        __f_ = __f.__f_->__clone();
8247a984708SDavid Chisnall}
8257a984708SDavid Chisnall
82694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
82794e3ee44SDavid Chisnalltemplate <class _Fp>
82894e3ee44SDavid Chisnallfunction<_Rp(_A0)>::function(_Fp __f,
82994e3ee44SDavid Chisnall                                     typename enable_if<!is_integral<_Fp>::value>::type*)
8307a984708SDavid Chisnall    : __f_(0)
8317a984708SDavid Chisnall{
8329729cf09SDimitry Andric    if (__function::__not_null(__f))
8337a984708SDavid Chisnall    {
83494e3ee44SDavid Chisnall        typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0)> _FF;
8357a984708SDavid Chisnall        if (sizeof(_FF) <= sizeof(__buf_))
8367a984708SDavid Chisnall        {
8377a984708SDavid Chisnall            __f_ = (__base*)&__buf_;
8387a984708SDavid Chisnall            ::new (__f_) _FF(__f);
8397a984708SDavid Chisnall        }
8407a984708SDavid Chisnall        else
8417a984708SDavid Chisnall        {
84294e3ee44SDavid Chisnall            typedef allocator<_FF> _Ap;
84394e3ee44SDavid Chisnall            _Ap __a;
84494e3ee44SDavid Chisnall            typedef __allocator_destructor<_Ap> _Dp;
84594e3ee44SDavid Chisnall            unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
84694e3ee44SDavid Chisnall            ::new (__hold.get()) _FF(__f, allocator<_Fp>(__a));
8477a984708SDavid Chisnall            __f_ = __hold.release();
8487a984708SDavid Chisnall        }
8497a984708SDavid Chisnall    }
8507a984708SDavid Chisnall}
8517a984708SDavid Chisnall
85294e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
85394e3ee44SDavid Chisnalltemplate <class _Fp, class _Alloc>
85494e3ee44SDavid Chisnallfunction<_Rp(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f,
85594e3ee44SDavid Chisnall                                     typename enable_if<!is_integral<_Fp>::value>::type*)
8567a984708SDavid Chisnall    : __f_(0)
8577a984708SDavid Chisnall{
8587a984708SDavid Chisnall    typedef allocator_traits<_Alloc> __alloc_traits;
8599729cf09SDimitry Andric    if (__function::__not_null(__f))
8607a984708SDavid Chisnall    {
86194e3ee44SDavid Chisnall        typedef __function::__func<_Fp, _Alloc, _Rp(_A0)> _FF;
8627a984708SDavid Chisnall        if (sizeof(_FF) <= sizeof(__buf_))
8637a984708SDavid Chisnall        {
8647a984708SDavid Chisnall            __f_ = (__base*)&__buf_;
865854fa44bSDimitry Andric            ::new (__f_) _FF(__f, __a0);
8667a984708SDavid Chisnall        }
8677a984708SDavid Chisnall        else
8687a984708SDavid Chisnall        {
869854fa44bSDimitry Andric            typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
87094e3ee44SDavid Chisnall            _Ap __a(__a0);
87194e3ee44SDavid Chisnall            typedef __allocator_destructor<_Ap> _Dp;
87294e3ee44SDavid Chisnall            unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
8737a984708SDavid Chisnall            ::new (__hold.get()) _FF(__f, _Alloc(__a));
8747a984708SDavid Chisnall            __f_ = __hold.release();
8757a984708SDavid Chisnall        }
8767a984708SDavid Chisnall    }
8777a984708SDavid Chisnall}
8787a984708SDavid Chisnall
87994e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
88094e3ee44SDavid Chisnallfunction<_Rp(_A0)>&
88194e3ee44SDavid Chisnallfunction<_Rp(_A0)>::operator=(const function& __f)
8827a984708SDavid Chisnall{
883*4ba319b5SDimitry Andric    if (__f)
8847a984708SDavid Chisnall        function(__f).swap(*this);
885*4ba319b5SDimitry Andric    else
886*4ba319b5SDimitry Andric        *this = nullptr;
8877a984708SDavid Chisnall    return *this;
8887a984708SDavid Chisnall}
8897a984708SDavid Chisnall
89094e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
89194e3ee44SDavid Chisnallfunction<_Rp(_A0)>&
89294e3ee44SDavid Chisnallfunction<_Rp(_A0)>::operator=(nullptr_t)
8937a984708SDavid Chisnall{
894*4ba319b5SDimitry Andric    __base* __t = __f_;
8957a984708SDavid Chisnall    __f_ = 0;
896*4ba319b5SDimitry Andric    if (__t == (__base*)&__buf_)
897*4ba319b5SDimitry Andric        __t->destroy();
898*4ba319b5SDimitry Andric    else if (__t)
899*4ba319b5SDimitry Andric        __t->destroy_deallocate();
900854fa44bSDimitry Andric    return *this;
9017a984708SDavid Chisnall}
9027a984708SDavid Chisnall
90394e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
90494e3ee44SDavid Chisnalltemplate <class _Fp>
9057a984708SDavid Chisnalltypename enable_if
9067a984708SDavid Chisnall<
90794e3ee44SDavid Chisnall    !is_integral<_Fp>::value,
90894e3ee44SDavid Chisnall    function<_Rp(_A0)>&
9097a984708SDavid Chisnall>::type
91094e3ee44SDavid Chisnallfunction<_Rp(_A0)>::operator=(_Fp __f)
9117a984708SDavid Chisnall{
9127a984708SDavid Chisnall    function(_VSTD::move(__f)).swap(*this);
9137a984708SDavid Chisnall    return *this;
9147a984708SDavid Chisnall}
9157a984708SDavid Chisnall
91694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
91794e3ee44SDavid Chisnallfunction<_Rp(_A0)>::~function()
9187a984708SDavid Chisnall{
9197a984708SDavid Chisnall    if (__f_ == (__base*)&__buf_)
9207a984708SDavid Chisnall        __f_->destroy();
9217a984708SDavid Chisnall    else if (__f_)
9227a984708SDavid Chisnall        __f_->destroy_deallocate();
9237a984708SDavid Chisnall}
9247a984708SDavid Chisnall
92594e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
9267a984708SDavid Chisnallvoid
92794e3ee44SDavid Chisnallfunction<_Rp(_A0)>::swap(function& __f)
9287a984708SDavid Chisnall{
929aed8d94eSDimitry Andric    if (_VSTD::addressof(__f) == this)
930aed8d94eSDimitry Andric      return;
9317a984708SDavid Chisnall    if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
9327a984708SDavid Chisnall    {
9337a984708SDavid Chisnall        typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
9347a984708SDavid Chisnall        __base* __t = (__base*)&__tempbuf;
9357a984708SDavid Chisnall        __f_->__clone(__t);
9367a984708SDavid Chisnall        __f_->destroy();
9377a984708SDavid Chisnall        __f_ = 0;
9387a984708SDavid Chisnall        __f.__f_->__clone((__base*)&__buf_);
9397a984708SDavid Chisnall        __f.__f_->destroy();
9407a984708SDavid Chisnall        __f.__f_ = 0;
9417a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
9427a984708SDavid Chisnall        __t->__clone((__base*)&__f.__buf_);
9437a984708SDavid Chisnall        __t->destroy();
9447a984708SDavid Chisnall        __f.__f_ = (__base*)&__f.__buf_;
9457a984708SDavid Chisnall    }
9467a984708SDavid Chisnall    else if (__f_ == (__base*)&__buf_)
9477a984708SDavid Chisnall    {
9487a984708SDavid Chisnall        __f_->__clone((__base*)&__f.__buf_);
9497a984708SDavid Chisnall        __f_->destroy();
9507a984708SDavid Chisnall        __f_ = __f.__f_;
9517a984708SDavid Chisnall        __f.__f_ = (__base*)&__f.__buf_;
9527a984708SDavid Chisnall    }
9537a984708SDavid Chisnall    else if (__f.__f_ == (__base*)&__f.__buf_)
9547a984708SDavid Chisnall    {
9557a984708SDavid Chisnall        __f.__f_->__clone((__base*)&__buf_);
9567a984708SDavid Chisnall        __f.__f_->destroy();
9577a984708SDavid Chisnall        __f.__f_ = __f_;
9587a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
9597a984708SDavid Chisnall    }
9607a984708SDavid Chisnall    else
9617a984708SDavid Chisnall        _VSTD::swap(__f_, __f.__f_);
9627a984708SDavid Chisnall}
9637a984708SDavid Chisnall
96494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
96594e3ee44SDavid Chisnall_Rp
96694e3ee44SDavid Chisnallfunction<_Rp(_A0)>::operator()(_A0 __a0) const
9677a984708SDavid Chisnall{
9687a984708SDavid Chisnall    if (__f_ == 0)
969aed8d94eSDimitry Andric        __throw_bad_function_call();
9707a984708SDavid Chisnall    return (*__f_)(__a0);
9717a984708SDavid Chisnall}
9727a984708SDavid Chisnall
9737a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
9747a984708SDavid Chisnall
97594e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
9767a984708SDavid Chisnallconst std::type_info&
97794e3ee44SDavid Chisnallfunction<_Rp(_A0)>::target_type() const
9787a984708SDavid Chisnall{
9797a984708SDavid Chisnall    if (__f_ == 0)
9807a984708SDavid Chisnall        return typeid(void);
9817a984708SDavid Chisnall    return __f_->target_type();
9827a984708SDavid Chisnall}
9837a984708SDavid Chisnall
98494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
98594e3ee44SDavid Chisnalltemplate <typename _Tp>
98694e3ee44SDavid Chisnall_Tp*
98794e3ee44SDavid Chisnallfunction<_Rp(_A0)>::target()
9887a984708SDavid Chisnall{
9897a984708SDavid Chisnall    if (__f_ == 0)
99094e3ee44SDavid Chisnall        return (_Tp*)0;
99124d58133SDimitry Andric    return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
9927a984708SDavid Chisnall}
9937a984708SDavid Chisnall
99494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0>
99594e3ee44SDavid Chisnalltemplate <typename _Tp>
99694e3ee44SDavid Chisnallconst _Tp*
99794e3ee44SDavid Chisnallfunction<_Rp(_A0)>::target() const
9987a984708SDavid Chisnall{
9997a984708SDavid Chisnall    if (__f_ == 0)
100094e3ee44SDavid Chisnall        return (const _Tp*)0;
100194e3ee44SDavid Chisnall    return (const _Tp*)__f_->target(typeid(_Tp));
10027a984708SDavid Chisnall}
10037a984708SDavid Chisnall
10047a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
10057a984708SDavid Chisnall
100694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
1007aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS function<_Rp(_A0, _A1)>
100894e3ee44SDavid Chisnall    : public binary_function<_A0, _A1, _Rp>
10097a984708SDavid Chisnall{
101094e3ee44SDavid Chisnall    typedef __function::__base<_Rp(_A0, _A1)> __base;
10117a984708SDavid Chisnall    aligned_storage<3*sizeof(void*)>::type __buf_;
10127a984708SDavid Chisnall    __base* __f_;
10137a984708SDavid Chisnall
10147a984708SDavid Chisnallpublic:
101594e3ee44SDavid Chisnall    typedef _Rp result_type;
10167a984708SDavid Chisnall
10177a984708SDavid Chisnall    // 20.7.16.2.1, construct/copy/destroy:
10187a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {}
10197a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {}
10207a984708SDavid Chisnall    function(const function&);
102194e3ee44SDavid Chisnall    template<class _Fp>
102294e3ee44SDavid Chisnall      function(_Fp,
102394e3ee44SDavid Chisnall               typename enable_if<!is_integral<_Fp>::value>::type* = 0);
10247a984708SDavid Chisnall
10257a984708SDavid Chisnall    template<class _Alloc>
10267a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
10277a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
10287a984708SDavid Chisnall    template<class _Alloc>
10297a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
10307a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
10317a984708SDavid Chisnall    template<class _Alloc>
10327a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&, const function&);
103394e3ee44SDavid Chisnall    template<class _Fp, class _Alloc>
103494e3ee44SDavid Chisnall      function(allocator_arg_t, const _Alloc& __a, _Fp __f,
103594e3ee44SDavid Chisnall               typename enable_if<!is_integral<_Fp>::value>::type* = 0);
10367a984708SDavid Chisnall
10377a984708SDavid Chisnall    function& operator=(const function&);
10387a984708SDavid Chisnall    function& operator=(nullptr_t);
103994e3ee44SDavid Chisnall    template<class _Fp>
10407a984708SDavid Chisnall      typename enable_if
10417a984708SDavid Chisnall      <
104294e3ee44SDavid Chisnall        !is_integral<_Fp>::value,
10437a984708SDavid Chisnall        function&
10447a984708SDavid Chisnall      >::type
104594e3ee44SDavid Chisnall      operator=(_Fp);
10467a984708SDavid Chisnall
10477a984708SDavid Chisnall    ~function();
10487a984708SDavid Chisnall
10497a984708SDavid Chisnall    // 20.7.16.2.2, function modifiers:
10507a984708SDavid Chisnall    void swap(function&);
105194e3ee44SDavid Chisnall    template<class _Fp, class _Alloc>
10527a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
105394e3ee44SDavid Chisnall      void assign(_Fp __f, const _Alloc& __a)
10547a984708SDavid Chisnall        {function(allocator_arg, __a, __f).swap(*this);}
10557a984708SDavid Chisnall
10567a984708SDavid Chisnall    // 20.7.16.2.3, function capacity:
10577a984708SDavid Chisnall    operator bool() const {return __f_;}
10587a984708SDavid Chisnall
10597a984708SDavid Chisnallprivate:
10607a984708SDavid Chisnall    // deleted overloads close possible hole in the type system
10617a984708SDavid Chisnall    template<class _R2, class _B0, class _B1>
10627a984708SDavid Chisnall      bool operator==(const function<_R2(_B0, _B1)>&) const;// = delete;
10637a984708SDavid Chisnall    template<class _R2, class _B0, class _B1>
10647a984708SDavid Chisnall      bool operator!=(const function<_R2(_B0, _B1)>&) const;// = delete;
10657a984708SDavid Chisnallpublic:
10667a984708SDavid Chisnall    // 20.7.16.2.4, function invocation:
106794e3ee44SDavid Chisnall    _Rp operator()(_A0, _A1) const;
10687a984708SDavid Chisnall
10697a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
10707a984708SDavid Chisnall    // 20.7.16.2.5, function target access:
10717a984708SDavid Chisnall    const std::type_info& target_type() const;
107294e3ee44SDavid Chisnall    template <typename _Tp> _Tp* target();
107394e3ee44SDavid Chisnall    template <typename _Tp> const _Tp* target() const;
10747a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
10757a984708SDavid Chisnall};
10767a984708SDavid Chisnall
107794e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
107894e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::function(const function& __f)
10797a984708SDavid Chisnall{
10807a984708SDavid Chisnall    if (__f.__f_ == 0)
10817a984708SDavid Chisnall        __f_ = 0;
10827a984708SDavid Chisnall    else if (__f.__f_ == (const __base*)&__f.__buf_)
10837a984708SDavid Chisnall    {
10847a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
10857a984708SDavid Chisnall        __f.__f_->__clone(__f_);
10867a984708SDavid Chisnall    }
10877a984708SDavid Chisnall    else
10887a984708SDavid Chisnall        __f_ = __f.__f_->__clone();
10897a984708SDavid Chisnall}
10907a984708SDavid Chisnall
109194e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
10927a984708SDavid Chisnalltemplate<class _Alloc>
109394e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc&, const function& __f)
10947a984708SDavid Chisnall{
10957a984708SDavid Chisnall    if (__f.__f_ == 0)
10967a984708SDavid Chisnall        __f_ = 0;
10977a984708SDavid Chisnall    else if (__f.__f_ == (const __base*)&__f.__buf_)
10987a984708SDavid Chisnall    {
10997a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
11007a984708SDavid Chisnall        __f.__f_->__clone(__f_);
11017a984708SDavid Chisnall    }
11027a984708SDavid Chisnall    else
11037a984708SDavid Chisnall        __f_ = __f.__f_->__clone();
11047a984708SDavid Chisnall}
11057a984708SDavid Chisnall
110694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
110794e3ee44SDavid Chisnalltemplate <class _Fp>
110894e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::function(_Fp __f,
110994e3ee44SDavid Chisnall                                 typename enable_if<!is_integral<_Fp>::value>::type*)
11107a984708SDavid Chisnall    : __f_(0)
11117a984708SDavid Chisnall{
11129729cf09SDimitry Andric    if (__function::__not_null(__f))
11137a984708SDavid Chisnall    {
111494e3ee44SDavid Chisnall        typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1)> _FF;
11157a984708SDavid Chisnall        if (sizeof(_FF) <= sizeof(__buf_))
11167a984708SDavid Chisnall        {
11177a984708SDavid Chisnall            __f_ = (__base*)&__buf_;
11187a984708SDavid Chisnall            ::new (__f_) _FF(__f);
11197a984708SDavid Chisnall        }
11207a984708SDavid Chisnall        else
11217a984708SDavid Chisnall        {
112294e3ee44SDavid Chisnall            typedef allocator<_FF> _Ap;
112394e3ee44SDavid Chisnall            _Ap __a;
112494e3ee44SDavid Chisnall            typedef __allocator_destructor<_Ap> _Dp;
112594e3ee44SDavid Chisnall            unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
112694e3ee44SDavid Chisnall            ::new (__hold.get()) _FF(__f, allocator<_Fp>(__a));
11277a984708SDavid Chisnall            __f_ = __hold.release();
11287a984708SDavid Chisnall        }
11297a984708SDavid Chisnall    }
11307a984708SDavid Chisnall}
11317a984708SDavid Chisnall
113294e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
113394e3ee44SDavid Chisnalltemplate <class _Fp, class _Alloc>
113494e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f,
113594e3ee44SDavid Chisnall                                 typename enable_if<!is_integral<_Fp>::value>::type*)
11367a984708SDavid Chisnall    : __f_(0)
11377a984708SDavid Chisnall{
11387a984708SDavid Chisnall    typedef allocator_traits<_Alloc> __alloc_traits;
11399729cf09SDimitry Andric    if (__function::__not_null(__f))
11407a984708SDavid Chisnall    {
114194e3ee44SDavid Chisnall        typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1)> _FF;
11427a984708SDavid Chisnall        if (sizeof(_FF) <= sizeof(__buf_))
11437a984708SDavid Chisnall        {
11447a984708SDavid Chisnall            __f_ = (__base*)&__buf_;
1145854fa44bSDimitry Andric            ::new (__f_) _FF(__f, __a0);
11467a984708SDavid Chisnall        }
11477a984708SDavid Chisnall        else
11487a984708SDavid Chisnall        {
1149854fa44bSDimitry Andric            typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
115094e3ee44SDavid Chisnall            _Ap __a(__a0);
115194e3ee44SDavid Chisnall            typedef __allocator_destructor<_Ap> _Dp;
115294e3ee44SDavid Chisnall            unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
11537a984708SDavid Chisnall            ::new (__hold.get()) _FF(__f, _Alloc(__a));
11547a984708SDavid Chisnall            __f_ = __hold.release();
11557a984708SDavid Chisnall        }
11567a984708SDavid Chisnall    }
11577a984708SDavid Chisnall}
11587a984708SDavid Chisnall
115994e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
116094e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>&
116194e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::operator=(const function& __f)
11627a984708SDavid Chisnall{
1163*4ba319b5SDimitry Andric    if (__f)
11647a984708SDavid Chisnall        function(__f).swap(*this);
1165*4ba319b5SDimitry Andric    else
1166*4ba319b5SDimitry Andric        *this = nullptr;
11677a984708SDavid Chisnall    return *this;
11687a984708SDavid Chisnall}
11697a984708SDavid Chisnall
117094e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
117194e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>&
117294e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::operator=(nullptr_t)
11737a984708SDavid Chisnall{
1174*4ba319b5SDimitry Andric    __base* __t = __f_;
11757a984708SDavid Chisnall    __f_ = 0;
1176*4ba319b5SDimitry Andric    if (__t == (__base*)&__buf_)
1177*4ba319b5SDimitry Andric        __t->destroy();
1178*4ba319b5SDimitry Andric    else if (__t)
1179*4ba319b5SDimitry Andric        __t->destroy_deallocate();
1180854fa44bSDimitry Andric    return *this;
11817a984708SDavid Chisnall}
11827a984708SDavid Chisnall
118394e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
118494e3ee44SDavid Chisnalltemplate <class _Fp>
11857a984708SDavid Chisnalltypename enable_if
11867a984708SDavid Chisnall<
118794e3ee44SDavid Chisnall    !is_integral<_Fp>::value,
118894e3ee44SDavid Chisnall    function<_Rp(_A0, _A1)>&
11897a984708SDavid Chisnall>::type
119094e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::operator=(_Fp __f)
11917a984708SDavid Chisnall{
11927a984708SDavid Chisnall    function(_VSTD::move(__f)).swap(*this);
11937a984708SDavid Chisnall    return *this;
11947a984708SDavid Chisnall}
11957a984708SDavid Chisnall
119694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
119794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::~function()
11987a984708SDavid Chisnall{
11997a984708SDavid Chisnall    if (__f_ == (__base*)&__buf_)
12007a984708SDavid Chisnall        __f_->destroy();
12017a984708SDavid Chisnall    else if (__f_)
12027a984708SDavid Chisnall        __f_->destroy_deallocate();
12037a984708SDavid Chisnall}
12047a984708SDavid Chisnall
120594e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
12067a984708SDavid Chisnallvoid
120794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::swap(function& __f)
12087a984708SDavid Chisnall{
1209aed8d94eSDimitry Andric    if (_VSTD::addressof(__f) == this)
1210aed8d94eSDimitry Andric      return;
12117a984708SDavid Chisnall    if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
12127a984708SDavid Chisnall    {
12137a984708SDavid Chisnall        typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
12147a984708SDavid Chisnall        __base* __t = (__base*)&__tempbuf;
12157a984708SDavid Chisnall        __f_->__clone(__t);
12167a984708SDavid Chisnall        __f_->destroy();
12177a984708SDavid Chisnall        __f_ = 0;
12187a984708SDavid Chisnall        __f.__f_->__clone((__base*)&__buf_);
12197a984708SDavid Chisnall        __f.__f_->destroy();
12207a984708SDavid Chisnall        __f.__f_ = 0;
12217a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
12227a984708SDavid Chisnall        __t->__clone((__base*)&__f.__buf_);
12237a984708SDavid Chisnall        __t->destroy();
12247a984708SDavid Chisnall        __f.__f_ = (__base*)&__f.__buf_;
12257a984708SDavid Chisnall    }
12267a984708SDavid Chisnall    else if (__f_ == (__base*)&__buf_)
12277a984708SDavid Chisnall    {
12287a984708SDavid Chisnall        __f_->__clone((__base*)&__f.__buf_);
12297a984708SDavid Chisnall        __f_->destroy();
12307a984708SDavid Chisnall        __f_ = __f.__f_;
12317a984708SDavid Chisnall        __f.__f_ = (__base*)&__f.__buf_;
12327a984708SDavid Chisnall    }
12337a984708SDavid Chisnall    else if (__f.__f_ == (__base*)&__f.__buf_)
12347a984708SDavid Chisnall    {
12357a984708SDavid Chisnall        __f.__f_->__clone((__base*)&__buf_);
12367a984708SDavid Chisnall        __f.__f_->destroy();
12377a984708SDavid Chisnall        __f.__f_ = __f_;
12387a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
12397a984708SDavid Chisnall    }
12407a984708SDavid Chisnall    else
12417a984708SDavid Chisnall        _VSTD::swap(__f_, __f.__f_);
12427a984708SDavid Chisnall}
12437a984708SDavid Chisnall
124494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
124594e3ee44SDavid Chisnall_Rp
124694e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) const
12477a984708SDavid Chisnall{
12487a984708SDavid Chisnall    if (__f_ == 0)
1249aed8d94eSDimitry Andric        __throw_bad_function_call();
12507a984708SDavid Chisnall    return (*__f_)(__a0, __a1);
12517a984708SDavid Chisnall}
12527a984708SDavid Chisnall
12537a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
12547a984708SDavid Chisnall
125594e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
12567a984708SDavid Chisnallconst std::type_info&
125794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::target_type() const
12587a984708SDavid Chisnall{
12597a984708SDavid Chisnall    if (__f_ == 0)
12607a984708SDavid Chisnall        return typeid(void);
12617a984708SDavid Chisnall    return __f_->target_type();
12627a984708SDavid Chisnall}
12637a984708SDavid Chisnall
126494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
126594e3ee44SDavid Chisnalltemplate <typename _Tp>
126694e3ee44SDavid Chisnall_Tp*
126794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::target()
12687a984708SDavid Chisnall{
12697a984708SDavid Chisnall    if (__f_ == 0)
127094e3ee44SDavid Chisnall        return (_Tp*)0;
127124d58133SDimitry Andric    return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
12727a984708SDavid Chisnall}
12737a984708SDavid Chisnall
127494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1>
127594e3ee44SDavid Chisnalltemplate <typename _Tp>
127694e3ee44SDavid Chisnallconst _Tp*
127794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1)>::target() const
12787a984708SDavid Chisnall{
12797a984708SDavid Chisnall    if (__f_ == 0)
128094e3ee44SDavid Chisnall        return (const _Tp*)0;
128194e3ee44SDavid Chisnall    return (const _Tp*)__f_->target(typeid(_Tp));
12827a984708SDavid Chisnall}
12837a984708SDavid Chisnall
12847a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
12857a984708SDavid Chisnall
128694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
1287aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS function<_Rp(_A0, _A1, _A2)>
12887a984708SDavid Chisnall{
128994e3ee44SDavid Chisnall    typedef __function::__base<_Rp(_A0, _A1, _A2)> __base;
12907a984708SDavid Chisnall    aligned_storage<3*sizeof(void*)>::type __buf_;
12917a984708SDavid Chisnall    __base* __f_;
12927a984708SDavid Chisnall
12937a984708SDavid Chisnallpublic:
129494e3ee44SDavid Chisnall    typedef _Rp result_type;
12957a984708SDavid Chisnall
12967a984708SDavid Chisnall    // 20.7.16.2.1, construct/copy/destroy:
12977a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {}
12987a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {}
12997a984708SDavid Chisnall    function(const function&);
130094e3ee44SDavid Chisnall    template<class _Fp>
130194e3ee44SDavid Chisnall      function(_Fp,
130294e3ee44SDavid Chisnall               typename enable_if<!is_integral<_Fp>::value>::type* = 0);
13037a984708SDavid Chisnall
13047a984708SDavid Chisnall    template<class _Alloc>
13057a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
13067a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
13077a984708SDavid Chisnall    template<class _Alloc>
13087a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
13097a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
13107a984708SDavid Chisnall    template<class _Alloc>
13117a984708SDavid Chisnall      function(allocator_arg_t, const _Alloc&, const function&);
131294e3ee44SDavid Chisnall    template<class _Fp, class _Alloc>
131394e3ee44SDavid Chisnall      function(allocator_arg_t, const _Alloc& __a, _Fp __f,
131494e3ee44SDavid Chisnall               typename enable_if<!is_integral<_Fp>::value>::type* = 0);
13157a984708SDavid Chisnall
13167a984708SDavid Chisnall    function& operator=(const function&);
13177a984708SDavid Chisnall    function& operator=(nullptr_t);
131894e3ee44SDavid Chisnall    template<class _Fp>
13197a984708SDavid Chisnall      typename enable_if
13207a984708SDavid Chisnall      <
132194e3ee44SDavid Chisnall        !is_integral<_Fp>::value,
13227a984708SDavid Chisnall        function&
13237a984708SDavid Chisnall      >::type
132494e3ee44SDavid Chisnall      operator=(_Fp);
13257a984708SDavid Chisnall
13267a984708SDavid Chisnall    ~function();
13277a984708SDavid Chisnall
13287a984708SDavid Chisnall    // 20.7.16.2.2, function modifiers:
13297a984708SDavid Chisnall    void swap(function&);
133094e3ee44SDavid Chisnall    template<class _Fp, class _Alloc>
13317a984708SDavid Chisnall      _LIBCPP_INLINE_VISIBILITY
133294e3ee44SDavid Chisnall      void assign(_Fp __f, const _Alloc& __a)
13337a984708SDavid Chisnall        {function(allocator_arg, __a, __f).swap(*this);}
13347a984708SDavid Chisnall
13357a984708SDavid Chisnall    // 20.7.16.2.3, function capacity:
13367a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;}
13377a984708SDavid Chisnall
13387a984708SDavid Chisnallprivate:
13397a984708SDavid Chisnall    // deleted overloads close possible hole in the type system
13407a984708SDavid Chisnall    template<class _R2, class _B0, class _B1, class _B2>
13417a984708SDavid Chisnall      bool operator==(const function<_R2(_B0, _B1, _B2)>&) const;// = delete;
13427a984708SDavid Chisnall    template<class _R2, class _B0, class _B1, class _B2>
13437a984708SDavid Chisnall      bool operator!=(const function<_R2(_B0, _B1, _B2)>&) const;// = delete;
13447a984708SDavid Chisnallpublic:
13457a984708SDavid Chisnall    // 20.7.16.2.4, function invocation:
134694e3ee44SDavid Chisnall    _Rp operator()(_A0, _A1, _A2) const;
13477a984708SDavid Chisnall
13487a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
13497a984708SDavid Chisnall    // 20.7.16.2.5, function target access:
13507a984708SDavid Chisnall    const std::type_info& target_type() const;
135194e3ee44SDavid Chisnall    template <typename _Tp> _Tp* target();
135294e3ee44SDavid Chisnall    template <typename _Tp> const _Tp* target() const;
13537a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
13547a984708SDavid Chisnall};
13557a984708SDavid Chisnall
135694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
135794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::function(const function& __f)
13587a984708SDavid Chisnall{
13597a984708SDavid Chisnall    if (__f.__f_ == 0)
13607a984708SDavid Chisnall        __f_ = 0;
13617a984708SDavid Chisnall    else if (__f.__f_ == (const __base*)&__f.__buf_)
13627a984708SDavid Chisnall    {
13637a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
13647a984708SDavid Chisnall        __f.__f_->__clone(__f_);
13657a984708SDavid Chisnall    }
13667a984708SDavid Chisnall    else
13677a984708SDavid Chisnall        __f_ = __f.__f_->__clone();
13687a984708SDavid Chisnall}
13697a984708SDavid Chisnall
137094e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
13717a984708SDavid Chisnalltemplate<class _Alloc>
137294e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc&,
13737a984708SDavid Chisnall                                      const function& __f)
13747a984708SDavid Chisnall{
13757a984708SDavid Chisnall    if (__f.__f_ == 0)
13767a984708SDavid Chisnall        __f_ = 0;
13777a984708SDavid Chisnall    else if (__f.__f_ == (const __base*)&__f.__buf_)
13787a984708SDavid Chisnall    {
13797a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
13807a984708SDavid Chisnall        __f.__f_->__clone(__f_);
13817a984708SDavid Chisnall    }
13827a984708SDavid Chisnall    else
13837a984708SDavid Chisnall        __f_ = __f.__f_->__clone();
13847a984708SDavid Chisnall}
13857a984708SDavid Chisnall
138694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
138794e3ee44SDavid Chisnalltemplate <class _Fp>
138894e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::function(_Fp __f,
138994e3ee44SDavid Chisnall                                     typename enable_if<!is_integral<_Fp>::value>::type*)
13907a984708SDavid Chisnall    : __f_(0)
13917a984708SDavid Chisnall{
13929729cf09SDimitry Andric    if (__function::__not_null(__f))
13937a984708SDavid Chisnall    {
139494e3ee44SDavid Chisnall        typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1, _A2)> _FF;
13957a984708SDavid Chisnall        if (sizeof(_FF) <= sizeof(__buf_))
13967a984708SDavid Chisnall        {
13977a984708SDavid Chisnall            __f_ = (__base*)&__buf_;
13987a984708SDavid Chisnall            ::new (__f_) _FF(__f);
13997a984708SDavid Chisnall        }
14007a984708SDavid Chisnall        else
14017a984708SDavid Chisnall        {
140294e3ee44SDavid Chisnall            typedef allocator<_FF> _Ap;
140394e3ee44SDavid Chisnall            _Ap __a;
140494e3ee44SDavid Chisnall            typedef __allocator_destructor<_Ap> _Dp;
140594e3ee44SDavid Chisnall            unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
140694e3ee44SDavid Chisnall            ::new (__hold.get()) _FF(__f, allocator<_Fp>(__a));
14077a984708SDavid Chisnall            __f_ = __hold.release();
14087a984708SDavid Chisnall        }
14097a984708SDavid Chisnall    }
14107a984708SDavid Chisnall}
14117a984708SDavid Chisnall
141294e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
141394e3ee44SDavid Chisnalltemplate <class _Fp, class _Alloc>
141494e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f,
141594e3ee44SDavid Chisnall                                     typename enable_if<!is_integral<_Fp>::value>::type*)
14167a984708SDavid Chisnall    : __f_(0)
14177a984708SDavid Chisnall{
14187a984708SDavid Chisnall    typedef allocator_traits<_Alloc> __alloc_traits;
14199729cf09SDimitry Andric    if (__function::__not_null(__f))
14207a984708SDavid Chisnall    {
142194e3ee44SDavid Chisnall        typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> _FF;
14227a984708SDavid Chisnall        if (sizeof(_FF) <= sizeof(__buf_))
14237a984708SDavid Chisnall        {
14247a984708SDavid Chisnall            __f_ = (__base*)&__buf_;
1425854fa44bSDimitry Andric            ::new (__f_) _FF(__f, __a0);
14267a984708SDavid Chisnall        }
14277a984708SDavid Chisnall        else
14287a984708SDavid Chisnall        {
1429854fa44bSDimitry Andric            typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
143094e3ee44SDavid Chisnall            _Ap __a(__a0);
143194e3ee44SDavid Chisnall            typedef __allocator_destructor<_Ap> _Dp;
143294e3ee44SDavid Chisnall            unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
14337a984708SDavid Chisnall            ::new (__hold.get()) _FF(__f, _Alloc(__a));
14347a984708SDavid Chisnall            __f_ = __hold.release();
14357a984708SDavid Chisnall        }
14367a984708SDavid Chisnall    }
14377a984708SDavid Chisnall}
14387a984708SDavid Chisnall
143994e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
144094e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>&
144194e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::operator=(const function& __f)
14427a984708SDavid Chisnall{
1443*4ba319b5SDimitry Andric    if (__f)
14447a984708SDavid Chisnall        function(__f).swap(*this);
1445*4ba319b5SDimitry Andric    else
1446*4ba319b5SDimitry Andric        *this = nullptr;
14477a984708SDavid Chisnall    return *this;
14487a984708SDavid Chisnall}
14497a984708SDavid Chisnall
145094e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
145194e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>&
145294e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::operator=(nullptr_t)
14537a984708SDavid Chisnall{
1454*4ba319b5SDimitry Andric    __base* __t = __f_;
14557a984708SDavid Chisnall    __f_ = 0;
1456*4ba319b5SDimitry Andric    if (__t == (__base*)&__buf_)
1457*4ba319b5SDimitry Andric        __t->destroy();
1458*4ba319b5SDimitry Andric    else if (__t)
1459*4ba319b5SDimitry Andric        __t->destroy_deallocate();
1460854fa44bSDimitry Andric    return *this;
14617a984708SDavid Chisnall}
14627a984708SDavid Chisnall
146394e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
146494e3ee44SDavid Chisnalltemplate <class _Fp>
14657a984708SDavid Chisnalltypename enable_if
14667a984708SDavid Chisnall<
146794e3ee44SDavid Chisnall    !is_integral<_Fp>::value,
146894e3ee44SDavid Chisnall    function<_Rp(_A0, _A1, _A2)>&
14697a984708SDavid Chisnall>::type
147094e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::operator=(_Fp __f)
14717a984708SDavid Chisnall{
14727a984708SDavid Chisnall    function(_VSTD::move(__f)).swap(*this);
14737a984708SDavid Chisnall    return *this;
14747a984708SDavid Chisnall}
14757a984708SDavid Chisnall
147694e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
147794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::~function()
14787a984708SDavid Chisnall{
14797a984708SDavid Chisnall    if (__f_ == (__base*)&__buf_)
14807a984708SDavid Chisnall        __f_->destroy();
14817a984708SDavid Chisnall    else if (__f_)
14827a984708SDavid Chisnall        __f_->destroy_deallocate();
14837a984708SDavid Chisnall}
14847a984708SDavid Chisnall
148594e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
14867a984708SDavid Chisnallvoid
148794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::swap(function& __f)
14887a984708SDavid Chisnall{
1489aed8d94eSDimitry Andric    if (_VSTD::addressof(__f) == this)
1490aed8d94eSDimitry Andric      return;
14917a984708SDavid Chisnall    if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
14927a984708SDavid Chisnall    {
14937a984708SDavid Chisnall        typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
14947a984708SDavid Chisnall        __base* __t = (__base*)&__tempbuf;
14957a984708SDavid Chisnall        __f_->__clone(__t);
14967a984708SDavid Chisnall        __f_->destroy();
14977a984708SDavid Chisnall        __f_ = 0;
14987a984708SDavid Chisnall        __f.__f_->__clone((__base*)&__buf_);
14997a984708SDavid Chisnall        __f.__f_->destroy();
15007a984708SDavid Chisnall        __f.__f_ = 0;
15017a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
15027a984708SDavid Chisnall        __t->__clone((__base*)&__f.__buf_);
15037a984708SDavid Chisnall        __t->destroy();
15047a984708SDavid Chisnall        __f.__f_ = (__base*)&__f.__buf_;
15057a984708SDavid Chisnall    }
15067a984708SDavid Chisnall    else if (__f_ == (__base*)&__buf_)
15077a984708SDavid Chisnall    {
15087a984708SDavid Chisnall        __f_->__clone((__base*)&__f.__buf_);
15097a984708SDavid Chisnall        __f_->destroy();
15107a984708SDavid Chisnall        __f_ = __f.__f_;
15117a984708SDavid Chisnall        __f.__f_ = (__base*)&__f.__buf_;
15127a984708SDavid Chisnall    }
15137a984708SDavid Chisnall    else if (__f.__f_ == (__base*)&__f.__buf_)
15147a984708SDavid Chisnall    {
15157a984708SDavid Chisnall        __f.__f_->__clone((__base*)&__buf_);
15167a984708SDavid Chisnall        __f.__f_->destroy();
15177a984708SDavid Chisnall        __f.__f_ = __f_;
15187a984708SDavid Chisnall        __f_ = (__base*)&__buf_;
15197a984708SDavid Chisnall    }
15207a984708SDavid Chisnall    else
15217a984708SDavid Chisnall        _VSTD::swap(__f_, __f.__f_);
15227a984708SDavid Chisnall}
15237a984708SDavid Chisnall
152494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
152594e3ee44SDavid Chisnall_Rp
152694e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) const
15277a984708SDavid Chisnall{
15287a984708SDavid Chisnall    if (__f_ == 0)
1529aed8d94eSDimitry Andric        __throw_bad_function_call();
15307a984708SDavid Chisnall    return (*__f_)(__a0, __a1, __a2);
15317a984708SDavid Chisnall}
15327a984708SDavid Chisnall
15337a984708SDavid Chisnall#ifndef _LIBCPP_NO_RTTI
15347a984708SDavid Chisnall
153594e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
15367a984708SDavid Chisnallconst std::type_info&
153794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::target_type() const
15387a984708SDavid Chisnall{
15397a984708SDavid Chisnall    if (__f_ == 0)
15407a984708SDavid Chisnall        return typeid(void);
15417a984708SDavid Chisnall    return __f_->target_type();
15427a984708SDavid Chisnall}
15437a984708SDavid Chisnall
154494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
154594e3ee44SDavid Chisnalltemplate <typename _Tp>
154694e3ee44SDavid Chisnall_Tp*
154794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::target()
15487a984708SDavid Chisnall{
15497a984708SDavid Chisnall    if (__f_ == 0)
155094e3ee44SDavid Chisnall        return (_Tp*)0;
155124d58133SDimitry Andric    return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
15527a984708SDavid Chisnall}
15537a984708SDavid Chisnall
155494e3ee44SDavid Chisnalltemplate<class _Rp, class _A0, class _A1, class _A2>
155594e3ee44SDavid Chisnalltemplate <typename _Tp>
155694e3ee44SDavid Chisnallconst _Tp*
155794e3ee44SDavid Chisnallfunction<_Rp(_A0, _A1, _A2)>::target() const
15587a984708SDavid Chisnall{
15597a984708SDavid Chisnall    if (__f_ == 0)
156094e3ee44SDavid Chisnall        return (const _Tp*)0;
156194e3ee44SDavid Chisnall    return (const _Tp*)__f_->target(typeid(_Tp));
15627a984708SDavid Chisnall}
15637a984708SDavid Chisnall
15647a984708SDavid Chisnall#endif  // _LIBCPP_NO_RTTI
15657a984708SDavid Chisnall
156694e3ee44SDavid Chisnalltemplate <class _Fp>
15677a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
15687a984708SDavid Chisnallbool
156994e3ee44SDavid Chisnalloperator==(const function<_Fp>& __f, nullptr_t) {return !__f;}
15707a984708SDavid Chisnall
157194e3ee44SDavid Chisnalltemplate <class _Fp>
15727a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
15737a984708SDavid Chisnallbool
157494e3ee44SDavid Chisnalloperator==(nullptr_t, const function<_Fp>& __f) {return !__f;}
15757a984708SDavid Chisnall
157694e3ee44SDavid Chisnalltemplate <class _Fp>
15777a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
15787a984708SDavid Chisnallbool
157994e3ee44SDavid Chisnalloperator!=(const function<_Fp>& __f, nullptr_t) {return (bool)__f;}
15807a984708SDavid Chisnall
158194e3ee44SDavid Chisnalltemplate <class _Fp>
15827a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
15837a984708SDavid Chisnallbool
158494e3ee44SDavid Chisnalloperator!=(nullptr_t, const function<_Fp>& __f) {return (bool)__f;}
15857a984708SDavid Chisnall
158694e3ee44SDavid Chisnalltemplate <class _Fp>
15877a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
15887a984708SDavid Chisnallvoid
158994e3ee44SDavid Chisnallswap(function<_Fp>& __x, function<_Fp>& __y)
15907a984708SDavid Chisnall{return __x.swap(__y);}
15917a984708SDavid Chisnall
15927a984708SDavid Chisnall#endif  // _LIBCPP_FUNCTIONAL_03
1593