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_BASE_03
127a984708SDavid Chisnall#define _LIBCPP_FUNCTIONAL_BASE_03
137a984708SDavid Chisnall
147a984708SDavid Chisnall// manual variadic expansion for <functional>
157a984708SDavid Chisnall
167a984708SDavid Chisnall// __invoke
177a984708SDavid Chisnall
18*9729cf09SDimitry Andrictemplate <class _Ret, class _T1, bool _IsFunc, bool _IsBase>
19*9729cf09SDimitry Andricstruct __enable_invoke_imp;
20*9729cf09SDimitry Andric
21*9729cf09SDimitry Andrictemplate <class _Ret, class _T1>
22*9729cf09SDimitry Andricstruct __enable_invoke_imp<_Ret, _T1, true, true> {
23*9729cf09SDimitry Andric    typedef _Ret _Bullet1;
24*9729cf09SDimitry Andric    typedef _Bullet1 type;
25*9729cf09SDimitry Andric};
26*9729cf09SDimitry Andric
27*9729cf09SDimitry Andrictemplate <class _Ret, class _T1>
28*9729cf09SDimitry Andricstruct __enable_invoke_imp<_Ret, _T1, true, false>  {
29*9729cf09SDimitry Andric    typedef _Ret _Bullet2;
30*9729cf09SDimitry Andric    typedef _Bullet2 type;
31*9729cf09SDimitry Andric};
32*9729cf09SDimitry Andric
33*9729cf09SDimitry Andrictemplate <class _Ret, class _T1>
34*9729cf09SDimitry Andricstruct __enable_invoke_imp<_Ret, _T1, false, true>  {
35*9729cf09SDimitry Andric    typedef typename add_lvalue_reference<
36*9729cf09SDimitry Andric                typename __apply_cv<_T1, _Ret>::type
37*9729cf09SDimitry Andric            >::type _Bullet3;
38*9729cf09SDimitry Andric    typedef _Bullet3 type;
39*9729cf09SDimitry Andric};
40*9729cf09SDimitry Andric
41*9729cf09SDimitry Andrictemplate <class _Ret, class _T1>
42*9729cf09SDimitry Andricstruct __enable_invoke_imp<_Ret, _T1, false, false>  {
43*9729cf09SDimitry Andric    typedef typename add_lvalue_reference<
44*9729cf09SDimitry Andric                typename __apply_cv<decltype(*_VSTD::declval<_T1>()), _Ret>::type
45*9729cf09SDimitry Andric            >::type _Bullet4;
46*9729cf09SDimitry Andric    typedef _Bullet4 type;
47*9729cf09SDimitry Andric};
48*9729cf09SDimitry Andric
49*9729cf09SDimitry Andrictemplate <class _Ret, class _T1>
50*9729cf09SDimitry Andricstruct __enable_invoke_imp<_Ret, _T1*, false, false>  {
51*9729cf09SDimitry Andric    typedef typename add_lvalue_reference<
52*9729cf09SDimitry Andric                typename __apply_cv<_T1, _Ret>::type
53*9729cf09SDimitry Andric            >::type _Bullet4;
54*9729cf09SDimitry Andric    typedef _Bullet4  type;
55*9729cf09SDimitry Andric};
56*9729cf09SDimitry Andric
57*9729cf09SDimitry Andrictemplate <class _Fn, class _T1,
58*9729cf09SDimitry Andric          class _Traits = __member_pointer_traits<_Fn>,
59*9729cf09SDimitry Andric          class _Ret = typename _Traits::_ReturnType,
60*9729cf09SDimitry Andric          class _Class = typename _Traits::_ClassType>
61*9729cf09SDimitry Andricstruct __enable_invoke : __enable_invoke_imp<
62*9729cf09SDimitry Andric    _Ret, _T1,
63*9729cf09SDimitry Andric    is_member_function_pointer<_Fn>::value,
64*9729cf09SDimitry Andric    is_base_of<_Class, typename remove_reference<_T1>::type>::value>
65*9729cf09SDimitry Andric{
66*9729cf09SDimitry Andric};
67*9729cf09SDimitry Andric
68*9729cf09SDimitry Andric__nat __invoke(__any, ...);
697a984708SDavid Chisnall
707a984708SDavid Chisnall// first bullet
717a984708SDavid Chisnall
72*9729cf09SDimitry Andrictemplate <class _Fn, class _T1>
737a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
74*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet1
75*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1) {
767a984708SDavid Chisnall    return (__t1.*__f)();
777a984708SDavid Chisnall}
787a984708SDavid Chisnall
79*9729cf09SDimitry Andrictemplate <class _Fn, class _T1, class _A0>
807a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
81*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet1
82*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
837a984708SDavid Chisnall    return (__t1.*__f)(__a0);
847a984708SDavid Chisnall}
857a984708SDavid Chisnall
86*9729cf09SDimitry Andrictemplate <class _Fn, class _T1, class _A0, class _A1>
877a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
88*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet1
89*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
907a984708SDavid Chisnall    return (__t1.*__f)(__a0, __a1);
917a984708SDavid Chisnall}
927a984708SDavid Chisnall
93*9729cf09SDimitry Andrictemplate <class _Fn, class _T1, class _A0, class _A1, class _A2>
947a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
95*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet1
96*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
977a984708SDavid Chisnall    return (__t1.*__f)(__a0, __a1, __a2);
987a984708SDavid Chisnall}
997a984708SDavid Chisnall
100*9729cf09SDimitry Andrictemplate <class _Fn, class _T1>
1017a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
102*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet2
103*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1) {
1047a984708SDavid Chisnall    return ((*__t1).*__f)();
1057a984708SDavid Chisnall}
1067a984708SDavid Chisnall
107*9729cf09SDimitry Andrictemplate <class _Fn, class _T1, class _A0>
1087a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
109*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet2
110*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
1117a984708SDavid Chisnall    return ((*__t1).*__f)(__a0);
1127a984708SDavid Chisnall}
1137a984708SDavid Chisnall
114*9729cf09SDimitry Andrictemplate <class _Fn, class _T1, class _A0, class _A1>
1157a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
116*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet2
117*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
1187a984708SDavid Chisnall    return ((*__t1).*__f)(__a0, __a1);
1197a984708SDavid Chisnall}
1207a984708SDavid Chisnall
121*9729cf09SDimitry Andrictemplate <class _Fn, class _T1, class _A0, class _A1, class _A2>
1227a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
123*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet2
124*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
1257a984708SDavid Chisnall    return ((*__t1).*__f)(__a0, __a1, __a2);
1267a984708SDavid Chisnall}
1277a984708SDavid Chisnall
128*9729cf09SDimitry Andrictemplate <class _Fn, class _T1>
1297a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
130*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet3
131*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1) {
1327a984708SDavid Chisnall    return __t1.*__f;
1337a984708SDavid Chisnall}
1347a984708SDavid Chisnall
135*9729cf09SDimitry Andrictemplate <class _Fn, class _T1>
1367a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
137*9729cf09SDimitry Andrictypename __enable_invoke<_Fn, _T1>::_Bullet4
138*9729cf09SDimitry Andric__invoke(_Fn __f, _T1& __t1) {
1397a984708SDavid Chisnall    return (*__t1).*__f;
1407a984708SDavid Chisnall}
1417a984708SDavid Chisnall
1427a984708SDavid Chisnall// fifth bullet
1437a984708SDavid Chisnall
14494e3ee44SDavid Chisnalltemplate <class _Fp>
1457a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
146*9729cf09SDimitry Andricdecltype(_VSTD::declval<_Fp&>()())
147*9729cf09SDimitry Andric__invoke(_Fp& __f)
1487a984708SDavid Chisnall{
1497a984708SDavid Chisnall    return __f();
1507a984708SDavid Chisnall}
1517a984708SDavid Chisnall
15294e3ee44SDavid Chisnalltemplate <class _Fp, class _A0>
1537a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
154*9729cf09SDimitry Andricdecltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>()))
155*9729cf09SDimitry Andric__invoke(_Fp& __f, _A0& __a0)
1567a984708SDavid Chisnall{
1577a984708SDavid Chisnall    return __f(__a0);
1587a984708SDavid Chisnall}
1597a984708SDavid Chisnall
16094e3ee44SDavid Chisnalltemplate <class _Fp, class _A0, class _A1>
1617a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
162*9729cf09SDimitry Andricdecltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>()))
163*9729cf09SDimitry Andric__invoke(_Fp& __f, _A0& __a0, _A1& __a1)
1647a984708SDavid Chisnall{
1657a984708SDavid Chisnall    return __f(__a0, __a1);
1667a984708SDavid Chisnall}
1677a984708SDavid Chisnall
16894e3ee44SDavid Chisnalltemplate <class _Fp, class _A0, class _A1, class _A2>
1697a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
170*9729cf09SDimitry Andricdecltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>(), _VSTD::declval<_A2&>()))
171*9729cf09SDimitry Andric__invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2)
1727a984708SDavid Chisnall{
1737a984708SDavid Chisnall    return __f(__a0, __a1, __a2);
1747a984708SDavid Chisnall}
1757a984708SDavid Chisnall
17694e3ee44SDavid Chisnalltemplate <class _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value>
1777a984708SDavid Chisnallstruct __invoke_return
1787a984708SDavid Chisnall{
17994e3ee44SDavid Chisnall    typedef typename __weak_result_type<_Fp>::result_type type;
1807a984708SDavid Chisnall};
1817a984708SDavid Chisnall
18294e3ee44SDavid Chisnalltemplate <class _Fp>
18394e3ee44SDavid Chisnallstruct __invoke_return<_Fp, false>
1847a984708SDavid Chisnall{
185*9729cf09SDimitry Andric    typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type;
1867a984708SDavid Chisnall};
1877a984708SDavid Chisnall
1887a984708SDavid Chisnalltemplate <class _Tp, class _A0>
1897a984708SDavid Chisnallstruct __invoke_return0
1907a984708SDavid Chisnall{
191*9729cf09SDimitry Andric    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type;
1927a984708SDavid Chisnall};
1937a984708SDavid Chisnall
19494e3ee44SDavid Chisnalltemplate <class _Rp, class _Tp, class _A0>
19594e3ee44SDavid Chisnallstruct __invoke_return0<_Rp _Tp::*, _A0>
1967a984708SDavid Chisnall{
197*9729cf09SDimitry Andric    typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type;
1987a984708SDavid Chisnall};
1997a984708SDavid Chisnall
2007a984708SDavid Chisnalltemplate <class _Tp, class _A0, class _A1>
2017a984708SDavid Chisnallstruct __invoke_return1
2027a984708SDavid Chisnall{
203*9729cf09SDimitry Andric    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
204*9729cf09SDimitry Andric                                                      _VSTD::declval<_A1&>())) type;
205*9729cf09SDimitry Andric};
206*9729cf09SDimitry Andric
207*9729cf09SDimitry Andrictemplate <class _Rp, class _Class, class _A0, class _A1>
208*9729cf09SDimitry Andricstruct __invoke_return1<_Rp _Class::*, _A0, _A1> {
209*9729cf09SDimitry Andric    typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type;
2107a984708SDavid Chisnall};
2117a984708SDavid Chisnall
2127a984708SDavid Chisnalltemplate <class _Tp, class _A0, class _A1, class _A2>
2137a984708SDavid Chisnallstruct __invoke_return2
2147a984708SDavid Chisnall{
215*9729cf09SDimitry Andric    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
216*9729cf09SDimitry Andric                                                      _VSTD::declval<_A1&>(),
217*9729cf09SDimitry Andric                                                      _VSTD::declval<_A2&>())) type;
2187a984708SDavid Chisnall};
2197a984708SDavid Chisnall
220*9729cf09SDimitry Andrictemplate <class _Ret, class _Class, class _A0, class _A1, class _A2>
221*9729cf09SDimitry Andricstruct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> {
222*9729cf09SDimitry Andric    typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type;
223854fa44bSDimitry Andric};
2247a984708SDavid Chisnall#endif  // _LIBCPP_FUNCTIONAL_BASE_03
225