1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4//                     The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_FUNCTIONAL_BASE_03
12#define _LIBCPP_FUNCTIONAL_BASE_03
13
14// manual variadic expansion for <functional>
15
16// __invoke
17
18template <class _Ret, class _T1, bool _IsFunc, bool _IsBase>
19struct __enable_invoke_imp;
20
21template <class _Ret, class _T1>
22struct __enable_invoke_imp<_Ret, _T1, true, true> {
23    typedef _Ret _Bullet1;
24    typedef _Bullet1 type;
25};
26
27template <class _Ret, class _T1>
28struct __enable_invoke_imp<_Ret, _T1, true, false>  {
29    typedef _Ret _Bullet2;
30    typedef _Bullet2 type;
31};
32
33template <class _Ret, class _T1>
34struct __enable_invoke_imp<_Ret, _T1, false, true>  {
35    typedef typename add_lvalue_reference<
36                typename __apply_cv<_T1, _Ret>::type
37            >::type _Bullet3;
38    typedef _Bullet3 type;
39};
40
41template <class _Ret, class _T1>
42struct __enable_invoke_imp<_Ret, _T1, false, false>  {
43    typedef typename add_lvalue_reference<
44                typename __apply_cv<decltype(*_VSTD::declval<_T1>()), _Ret>::type
45            >::type _Bullet4;
46    typedef _Bullet4 type;
47};
48
49template <class _Ret, class _T1>
50struct __enable_invoke_imp<_Ret, _T1*, false, false>  {
51    typedef typename add_lvalue_reference<
52                typename __apply_cv<_T1, _Ret>::type
53            >::type _Bullet4;
54    typedef _Bullet4  type;
55};
56
57template <class _Fn, class _T1,
58          class _Traits = __member_pointer_traits<_Fn>,
59          class _Ret = typename _Traits::_ReturnType,
60          class _Class = typename _Traits::_ClassType>
61struct __enable_invoke : __enable_invoke_imp<
62    _Ret, _T1,
63    is_member_function_pointer<_Fn>::value,
64    is_base_of<_Class, typename remove_reference<_T1>::type>::value>
65{
66};
67
68__nat __invoke(__any, ...);
69
70// first bullet
71
72template <class _Fn, class _T1>
73inline _LIBCPP_INLINE_VISIBILITY
74typename __enable_invoke<_Fn, _T1>::_Bullet1
75__invoke(_Fn __f, _T1& __t1) {
76    return (__t1.*__f)();
77}
78
79template <class _Fn, class _T1, class _A0>
80inline _LIBCPP_INLINE_VISIBILITY
81typename __enable_invoke<_Fn, _T1>::_Bullet1
82__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
83    return (__t1.*__f)(__a0);
84}
85
86template <class _Fn, class _T1, class _A0, class _A1>
87inline _LIBCPP_INLINE_VISIBILITY
88typename __enable_invoke<_Fn, _T1>::_Bullet1
89__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
90    return (__t1.*__f)(__a0, __a1);
91}
92
93template <class _Fn, class _T1, class _A0, class _A1, class _A2>
94inline _LIBCPP_INLINE_VISIBILITY
95typename __enable_invoke<_Fn, _T1>::_Bullet1
96__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
97    return (__t1.*__f)(__a0, __a1, __a2);
98}
99
100template <class _Fn, class _T1>
101inline _LIBCPP_INLINE_VISIBILITY
102typename __enable_invoke<_Fn, _T1>::_Bullet2
103__invoke(_Fn __f, _T1& __t1) {
104    return ((*__t1).*__f)();
105}
106
107template <class _Fn, class _T1, class _A0>
108inline _LIBCPP_INLINE_VISIBILITY
109typename __enable_invoke<_Fn, _T1>::_Bullet2
110__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
111    return ((*__t1).*__f)(__a0);
112}
113
114template <class _Fn, class _T1, class _A0, class _A1>
115inline _LIBCPP_INLINE_VISIBILITY
116typename __enable_invoke<_Fn, _T1>::_Bullet2
117__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
118    return ((*__t1).*__f)(__a0, __a1);
119}
120
121template <class _Fn, class _T1, class _A0, class _A1, class _A2>
122inline _LIBCPP_INLINE_VISIBILITY
123typename __enable_invoke<_Fn, _T1>::_Bullet2
124__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
125    return ((*__t1).*__f)(__a0, __a1, __a2);
126}
127
128template <class _Fn, class _T1>
129inline _LIBCPP_INLINE_VISIBILITY
130typename __enable_invoke<_Fn, _T1>::_Bullet3
131__invoke(_Fn __f, _T1& __t1) {
132    return __t1.*__f;
133}
134
135template <class _Fn, class _T1>
136inline _LIBCPP_INLINE_VISIBILITY
137typename __enable_invoke<_Fn, _T1>::_Bullet4
138__invoke(_Fn __f, _T1& __t1) {
139    return (*__t1).*__f;
140}
141
142// fifth bullet
143
144template <class _Fp>
145inline _LIBCPP_INLINE_VISIBILITY
146decltype(_VSTD::declval<_Fp&>()())
147__invoke(_Fp& __f)
148{
149    return __f();
150}
151
152template <class _Fp, class _A0>
153inline _LIBCPP_INLINE_VISIBILITY
154decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>()))
155__invoke(_Fp& __f, _A0& __a0)
156{
157    return __f(__a0);
158}
159
160template <class _Fp, class _A0, class _A1>
161inline _LIBCPP_INLINE_VISIBILITY
162decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>()))
163__invoke(_Fp& __f, _A0& __a0, _A1& __a1)
164{
165    return __f(__a0, __a1);
166}
167
168template <class _Fp, class _A0, class _A1, class _A2>
169inline _LIBCPP_INLINE_VISIBILITY
170decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>(), _VSTD::declval<_A2&>()))
171__invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2)
172{
173    return __f(__a0, __a1, __a2);
174}
175
176template <class _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value>
177struct __invoke_return
178{
179    typedef typename __weak_result_type<_Fp>::result_type type;
180};
181
182template <class _Fp>
183struct __invoke_return<_Fp, false>
184{
185    typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type;
186};
187
188template <class _Tp, class _A0>
189struct __invoke_return0
190{
191    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type;
192};
193
194template <class _Rp, class _Tp, class _A0>
195struct __invoke_return0<_Rp _Tp::*, _A0>
196{
197    typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type;
198};
199
200template <class _Tp, class _A0, class _A1>
201struct __invoke_return1
202{
203    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
204                                                      _VSTD::declval<_A1&>())) type;
205};
206
207template <class _Rp, class _Class, class _A0, class _A1>
208struct __invoke_return1<_Rp _Class::*, _A0, _A1> {
209    typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type;
210};
211
212template <class _Tp, class _A0, class _A1, class _A2>
213struct __invoke_return2
214{
215    typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
216                                                      _VSTD::declval<_A1&>(),
217                                                      _VSTD::declval<_A2&>())) type;
218};
219
220template <class _Ret, class _Class, class _A0, class _A1, class _A2>
221struct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> {
222    typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type;
223};
224#endif  // _LIBCPP_FUNCTIONAL_BASE_03
225