__functional_base_03 revision 302408
113978Smrkam// -*- C++ -*-
213978Smrkam//===----------------------------------------------------------------------===//
313978Smrkam//
413978Smrkam//                     The LLVM Compiler Infrastructure
513978Smrkam//
613978Smrkam// This file is dual licensed under the MIT and the University of Illinois Open
713978Smrkam// Source Licenses. See LICENSE.TXT for details.
813978Smrkam//
913978Smrkam//===----------------------------------------------------------------------===//
1013978Smrkam
1113978Smrkam#ifndef _LIBCPP_FUNCTIONAL_BASE_03
1213978Smrkam#define _LIBCPP_FUNCTIONAL_BASE_03
1313978Smrkam
1413978Smrkam// manual variadic expansion for <functional>
1513978Smrkam
1613978Smrkam// __invoke
1713978Smrkam
1813978Smrkamtemplate <class _Ret, class _T1, bool _IsFunc, bool _IsBase>
1913978Smrkamstruct __enable_invoke_imp;
2013978Smrkam
2113978Smrkamtemplate <class _Ret, class _T1>
2213978Smrkamstruct __enable_invoke_imp<_Ret, _T1, true, true> {
2313978Smrkam    typedef _Ret _Bullet1;
2414305Smrkam    typedef _Bullet1 type;
2513978Smrkam};
2613978Smrkam
2713978Smrkamtemplate <class _Ret, class _T1>
2813978Smrkamstruct __enable_invoke_imp<_Ret, _T1, true, false>  {
2913978Smrkam    typedef _Ret _Bullet2;
3013978Smrkam    typedef _Bullet2 type;
3113978Smrkam};
3213978Smrkam
3313978Smrkamtemplate <class _Ret, class _T1>
3414305Smrkamstruct __enable_invoke_imp<_Ret, _T1, false, true>  {
3513978Smrkam    typedef typename add_lvalue_reference<
3613978Smrkam                typename __apply_cv<_T1, _Ret>::type
3713978Smrkam            >::type _Bullet3;
3813978Smrkam    typedef _Bullet3 type;
3913978Smrkam};
4013978Smrkam
4113978Smrkamtemplate <class _Ret, class _T1>
4213978Smrkamstruct __enable_invoke_imp<_Ret, _T1, false, false>  {
4314305Smrkam    typedef typename add_lvalue_reference<
4413978Smrkam                typename __apply_cv<decltype(*_VSTD::declval<_T1>()), _Ret>::type
4514801Sprr            >::type _Bullet4;
4614801Sprr    typedef _Bullet4 type;
4713978Smrkam};
4813978Smrkam
4913978Smrkamtemplate <class _Ret, class _T1>
5013978Smrkamstruct __enable_invoke_imp<_Ret, _T1*, false, false>  {
5114305Smrkam    typedef typename add_lvalue_reference<
5213978Smrkam                typename __apply_cv<_T1, _Ret>::type
5313978Smrkam            >::type _Bullet4;
5413978Smrkam    typedef _Bullet4  type;
5513978Smrkam};
5613978Smrkam
5713978Smrkamtemplate <class _Fn, class _T1,
5813978Smrkam          class _Traits = __member_pointer_traits<_Fn>,
5914305Smrkam          class _Ret = typename _Traits::_ReturnType,
6013978Smrkam          class _Class = typename _Traits::_ClassType>
6114305Smrkamstruct __enable_invoke : __enable_invoke_imp<
6213978Smrkam    _Ret, _T1,
6314305Smrkam    is_member_function_pointer<_Fn>::value,
6414305Smrkam    is_base_of<_Class, typename remove_reference<_T1>::type>::value>
6514305Smrkam{
6614305Smrkam};
6713978Smrkam
6813978Smrkam__nat __invoke(__any, ...);
6913978Smrkam
7013978Smrkam// first bullet
7113978Smrkam
7213978Smrkamtemplate <class _Fn, class _T1>
7313978Smrkaminline _LIBCPP_INLINE_VISIBILITY
7413978Smrkamtypename __enable_invoke<_Fn, _T1>::_Bullet1
7513978Smrkam__invoke(_Fn __f, _T1& __t1) {
7613978Smrkam    return (__t1.*__f)();
7713978Smrkam}
7813978Smrkam
7913978Smrkamtemplate <class _Fn, class _T1, class _A0>
8013978Smrkaminline _LIBCPP_INLINE_VISIBILITY
8113978Smrkamtypename __enable_invoke<_Fn, _T1>::_Bullet1
8213978Smrkam__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
8313978Smrkam    return (__t1.*__f)(__a0);
8413978Smrkam}
8513978Smrkam
8613978Smrkamtemplate <class _Fn, class _T1, class _A0, class _A1>
8713978Smrkaminline _LIBCPP_INLINE_VISIBILITY
8813978Smrkamtypename __enable_invoke<_Fn, _T1>::_Bullet1
8913978Smrkam__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
9013978Smrkam    return (__t1.*__f)(__a0, __a1);
9113978Smrkam}
9213978Smrkam
9313978Smrkamtemplate <class _Fn, class _T1, class _A0, class _A1, class _A2>
9413978Smrkaminline _LIBCPP_INLINE_VISIBILITY
9513978Smrkamtypename __enable_invoke<_Fn, _T1>::_Bullet1
9613978Smrkam__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