1227825Stheraven// -*- C++ -*-
2227825Stheraven//===----------------------------------------------------------------------===//
3227825Stheraven//
4227825Stheraven//                     The LLVM Compiler Infrastructure
5227825Stheraven//
6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
7227825Stheraven// Source Licenses. See LICENSE.TXT for details.
8227825Stheraven//
9227825Stheraven//===----------------------------------------------------------------------===//
10227825Stheraven
11227825Stheraven#ifndef _LIBCPP_FUNCTIONAL_BASE_03
12227825Stheraven#define _LIBCPP_FUNCTIONAL_BASE_03
13227825Stheraven
14227825Stheraven// manual variadic expansion for <functional>
15227825Stheraven
16300770Sdim// __invoke
17227825Stheraven
18300770Sdimtemplate <class _Ret, class _T1, bool _IsFunc, bool _IsBase>
19300770Sdimstruct __enable_invoke_imp;
20227825Stheraven
21300770Sdimtemplate <class _Ret, class _T1>
22300770Sdimstruct __enable_invoke_imp<_Ret, _T1, true, true> {
23300770Sdim    typedef _Ret _Bullet1;
24300770Sdim    typedef _Bullet1 type;
25227825Stheraven};
26227825Stheraven
27300770Sdimtemplate <class _Ret, class _T1>
28300770Sdimstruct __enable_invoke_imp<_Ret, _T1, true, false>  {
29300770Sdim    typedef _Ret _Bullet2;
30300770Sdim    typedef _Bullet2 type;
31227825Stheraven};
32227825Stheraven
33300770Sdimtemplate <class _Ret, class _T1>
34300770Sdimstruct __enable_invoke_imp<_Ret, _T1, false, true>  {
35300770Sdim    typedef typename add_lvalue_reference<
36300770Sdim                typename __apply_cv<_T1, _Ret>::type
37300770Sdim            >::type _Bullet3;
38300770Sdim    typedef _Bullet3 type;
39227825Stheraven};
40227825Stheraven
41300770Sdimtemplate <class _Ret, class _T1>
42300770Sdimstruct __enable_invoke_imp<_Ret, _T1, false, false>  {
43300770Sdim    typedef typename add_lvalue_reference<
44300770Sdim                typename __apply_cv<decltype(*_VSTD::declval<_T1>()), _Ret>::type
45300770Sdim            >::type _Bullet4;
46300770Sdim    typedef _Bullet4 type;
47227825Stheraven};
48227825Stheraven
49300770Sdimtemplate <class _Ret, class _T1>
50300770Sdimstruct __enable_invoke_imp<_Ret, _T1*, false, false>  {
51300770Sdim    typedef typename add_lvalue_reference<
52300770Sdim                typename __apply_cv<_T1, _Ret>::type
53300770Sdim            >::type _Bullet4;
54300770Sdim    typedef _Bullet4  type;
55227825Stheraven};
56227825Stheraven
57300770Sdimtemplate <class _Fn, class _T1,
58300770Sdim          class _Traits = __member_pointer_traits<_Fn>,
59300770Sdim          class _Ret = typename _Traits::_ReturnType,
60300770Sdim          class _Class = typename _Traits::_ClassType>
61300770Sdimstruct __enable_invoke : __enable_invoke_imp<
62300770Sdim    _Ret, _T1,
63300770Sdim    is_member_function_pointer<_Fn>::value,
64300770Sdim    is_base_of<_Class, typename remove_reference<_T1>::type>::value>
65227825Stheraven{
66227825Stheraven};
67227825Stheraven
68300770Sdim__nat __invoke(__any, ...);
69227825Stheraven
70227825Stheraven// first bullet
71227825Stheraven
72300770Sdimtemplate <class _Fn, class _T1>
73227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
74300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet1
75300770Sdim__invoke(_Fn __f, _T1& __t1) {
76227825Stheraven    return (__t1.*__f)();
77227825Stheraven}
78227825Stheraven
79300770Sdimtemplate <class _Fn, class _T1, class _A0>
80227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
81300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet1
82300770Sdim__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
83227825Stheraven    return (__t1.*__f)(__a0);
84227825Stheraven}
85227825Stheraven
86300770Sdimtemplate <class _Fn, class _T1, class _A0, class _A1>
87227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
88300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet1
89300770Sdim__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
90227825Stheraven    return (__t1.*__f)(__a0, __a1);
91227825Stheraven}
92227825Stheraven
93300770Sdimtemplate <class _Fn, class _T1, class _A0, class _A1, class _A2>
94227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
95300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet1
96300770Sdim__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
97227825Stheraven    return (__t1.*__f)(__a0, __a1, __a2);
98227825Stheraven}
99227825Stheraven
100300770Sdimtemplate <class _Fn, class _T1>
101227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
102300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet2
103300770Sdim__invoke(_Fn __f, _T1& __t1) {
104227825Stheraven    return ((*__t1).*__f)();
105227825Stheraven}
106227825Stheraven
107300770Sdimtemplate <class _Fn, class _T1, class _A0>
108227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
109300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet2
110300770Sdim__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
111227825Stheraven    return ((*__t1).*__f)(__a0);
112227825Stheraven}
113227825Stheraven
114300770Sdimtemplate <class _Fn, class _T1, class _A0, class _A1>
115227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
116300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet2
117300770Sdim__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
118227825Stheraven    return ((*__t1).*__f)(__a0, __a1);
119227825Stheraven}
120227825Stheraven
121300770Sdimtemplate <class _Fn, class _T1, class _A0, class _A1, class _A2>
122227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
123300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet2
124300770Sdim__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
125227825Stheraven    return ((*__t1).*__f)(__a0, __a1, __a2);
126227825Stheraven}
127227825Stheraven
128300770Sdimtemplate <class _Fn, class _T1>
129227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
130300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet3
131300770Sdim__invoke(_Fn __f, _T1& __t1) {
132227825Stheraven    return __t1.*__f;
133227825Stheraven}
134227825Stheraven
135300770Sdimtemplate <class _Fn, class _T1>
136227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
137300770Sdimtypename __enable_invoke<_Fn, _T1>::_Bullet4
138300770Sdim__invoke(_Fn __f, _T1& __t1) {
139227825Stheraven    return (*__t1).*__f;
140227825Stheraven}
141227825Stheraven
142227825Stheraven// fifth bullet
143227825Stheraven
144232924Stheraventemplate <class _Fp>
145227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
146300770Sdimdecltype(_VSTD::declval<_Fp&>()())
147300770Sdim__invoke(_Fp& __f)
148227825Stheraven{
149227825Stheraven    return __f();
150227825Stheraven}
151227825Stheraven
152232924Stheraventemplate <class _Fp, class _A0>
153227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
154300770Sdimdecltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>()))
155300770Sdim__invoke(_Fp& __f, _A0& __a0)
156227825Stheraven{
157227825Stheraven    return __f(__a0);
158227825Stheraven}
159227825Stheraven
160232924Stheraventemplate <class _Fp, class _A0, class _A1>
161227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
162300770Sdimdecltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>()))
163300770Sdim__invoke(_Fp& __f, _A0& __a0, _A1& __a1)
164227825Stheraven{
165227825Stheraven    return __f(__a0, __a1);
166227825Stheraven}
167227825Stheraven
168232924Stheraventemplate <class _Fp, class _A0, class _A1, class _A2>
169227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
170300770Sdimdecltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>(), _VSTD::declval<_A2&>()))
171300770Sdim__invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2)
172227825Stheraven{
173227825Stheraven    return __f(__a0, __a1, __a2);
174227825Stheraven}
175227825Stheraven
176232924Stheraventemplate <class _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value>
177227825Stheravenstruct __invoke_return
178227825Stheraven{
179232924Stheraven    typedef typename __weak_result_type<_Fp>::result_type type;
180227825Stheraven};
181227825Stheraven
182232924Stheraventemplate <class _Fp>
183232924Stheravenstruct __invoke_return<_Fp, false>
184227825Stheraven{
185300770Sdim    typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type;
186227825Stheraven};
187227825Stheraven
188227825Stheraventemplate <class _Tp, class _A0>
189227825Stheravenstruct __invoke_return0
190227825Stheraven{
191300770Sdim    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type;
192227825Stheraven};
193227825Stheraven
194232924Stheraventemplate <class _Rp, class _Tp, class _A0>
195232924Stheravenstruct __invoke_return0<_Rp _Tp::*, _A0>
196227825Stheraven{
197300770Sdim    typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type;
198227825Stheraven};
199227825Stheraven
200227825Stheraventemplate <class _Tp, class _A0, class _A1>
201227825Stheravenstruct __invoke_return1
202227825Stheraven{
203300770Sdim    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
204300770Sdim                                                      _VSTD::declval<_A1&>())) type;
205227825Stheraven};
206227825Stheraven
207300770Sdimtemplate <class _Rp, class _Class, class _A0, class _A1>
208300770Sdimstruct __invoke_return1<_Rp _Class::*, _A0, _A1> {
209300770Sdim    typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type;
210300770Sdim};
211300770Sdim
212227825Stheraventemplate <class _Tp, class _A0, class _A1, class _A2>
213227825Stheravenstruct __invoke_return2
214227825Stheraven{
215300770Sdim    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
216300770Sdim                                                      _VSTD::declval<_A1&>(),
217300770Sdim                                                      _VSTD::declval<_A2&>())) type;
218227825Stheraven};
219227825Stheraven
220300770Sdimtemplate <class _Ret, class _Class, class _A0, class _A1, class _A2>
221300770Sdimstruct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> {
222300770Sdim    typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type;
223288943Sdim};
224227825Stheraven#endif  // _LIBCPP_FUNCTIONAL_BASE_03
225