comparison DEPENDENCIES/generic/include/boost/fusion/functional/invocation/invoke.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 /*=============================================================================
2 Copyright (c) 2005-2006 Joao Abecasis
3 Copyright (c) 2006-2007 Tobias Schwinger
4
5 Use modification and distribution are subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt).
8 ==============================================================================*/
9
10 #if !defined(BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_HPP_INCLUDED)
11 #if !defined(BOOST_PP_IS_ITERATING)
12
13 #include <boost/preprocessor/cat.hpp>
14 #include <boost/preprocessor/iteration/iterate.hpp>
15 #include <boost/preprocessor/arithmetic/dec.hpp>
16 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
17 #include <boost/preprocessor/repetition/enum.hpp>
18 #include <boost/preprocessor/repetition/enum_shifted.hpp>
19 #include <boost/preprocessor/repetition/enum_params.hpp>
20 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
21
22 #include <boost/mpl/if.hpp>
23 #include <boost/mpl/eval_if.hpp>
24 #include <boost/mpl/or.hpp>
25 #include <boost/mpl/front.hpp>
26 #include <boost/mpl/identity.hpp>
27
28 #include <boost/type_traits/add_const.hpp>
29 #include <boost/type_traits/remove_cv.hpp>
30 #include <boost/type_traits/add_reference.hpp>
31 #include <boost/type_traits/remove_reference.hpp>
32 #include <boost/type_traits/is_convertible.hpp>
33
34 #include <boost/function_types/is_function.hpp>
35 #include <boost/function_types/is_callable_builtin.hpp>
36 #include <boost/function_types/is_member_pointer.hpp>
37 #include <boost/function_types/is_member_function_pointer.hpp>
38 #include <boost/function_types/result_type.hpp>
39 #include <boost/function_types/parameter_types.hpp>
40
41 #include <boost/utility/result_of.hpp>
42
43 #include <boost/fusion/support/category_of.hpp>
44 #include <boost/fusion/sequence/intrinsic/at.hpp>
45 #include <boost/fusion/sequence/intrinsic/size.hpp>
46 #include <boost/fusion/sequence/intrinsic/front.hpp>
47 #include <boost/fusion/sequence/intrinsic/begin.hpp>
48 #include <boost/fusion/iterator/next.hpp>
49 #include <boost/fusion/iterator/deref.hpp>
50 #include <boost/fusion/functional/invocation/limits.hpp>
51 #include <boost/fusion/functional/invocation/detail/that_ptr.hpp>
52
53 namespace boost { namespace fusion
54 {
55 namespace result_of
56 {
57 template <typename Function, class Sequence> struct invoke;
58 }
59
60 //~ template <typename Function, class Sequence>
61 //~ inline typename result_of::invoke<Function, Sequence>::type
62 //~ invoke(Function, Sequence &);
63
64 //~ template <typename Function, class Sequence>
65 //~ inline typename result_of::invoke<Function, Sequence const>::type
66 //~ invoke(Function, Sequence const &);
67
68 //----- ---- --- -- - - - -
69
70 namespace detail
71 {
72 namespace ft = function_types;
73
74 template<
75 typename Function, class Sequence,
76 int N = result_of::size<Sequence>::value,
77 bool CBI = ft::is_callable_builtin<Function>::value,
78 bool RandomAccess = traits::is_random_access<Sequence>::value
79 >
80 struct invoke_impl;
81
82 template <class Sequence, int N>
83 struct invoke_param_types;
84
85 template <typename T, class Sequence>
86 struct invoke_data_member;
87
88 template <typename Function, class Sequence, int N, bool RandomAccess>
89 struct invoke_fn_ptr;
90
91 template <typename Function, class Sequence, int N, bool RandomAccess>
92 struct invoke_mem_fn;
93
94 #define BOOST_PP_FILENAME_1 <boost/fusion/functional/invocation/invoke.hpp>
95 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_FUSION_INVOKE_MAX_ARITY)
96 #include BOOST_PP_ITERATE()
97
98 template <typename F, class Sequence, int N, bool RandomAccess>
99 struct invoke_nonmember_builtin
100 // use same implementation as for function objects but...
101 : invoke_fn_ptr< // ...work around boost::result_of bugs
102 typename mpl::eval_if< ft::is_function<F>,
103 boost::add_reference<F>, boost::remove_cv<F> >::type,
104 Sequence, N, RandomAccess >
105 { };
106
107 template <typename Function, class Sequence, int N, bool RandomAccess>
108 struct invoke_impl<Function,Sequence,N,true,RandomAccess>
109 : mpl::if_< ft::is_member_function_pointer<Function>,
110 invoke_mem_fn<Function,Sequence,N,RandomAccess>,
111 invoke_nonmember_builtin<Function,Sequence,N,RandomAccess>
112 >::type
113 { };
114
115 template <typename Function, class Sequence, bool RandomAccess>
116 struct invoke_impl<Function,Sequence,1,true,RandomAccess>
117 : mpl::eval_if< ft::is_member_pointer<Function>,
118 mpl::if_< ft::is_member_function_pointer<Function>,
119 invoke_mem_fn<Function,Sequence,1,RandomAccess>,
120 invoke_data_member<Function, Sequence> >,
121 mpl::identity< invoke_nonmember_builtin<
122 Function,Sequence,1,RandomAccess> >
123 >::type
124 { };
125
126 template <typename T, class C, class Sequence>
127 struct invoke_data_member< T C::*, Sequence >
128 {
129 private:
130
131 typedef typename result_of::front<Sequence>::type that;
132
133 typedef mpl::or_< boost::is_convertible<that,C*>,
134 boost::is_convertible<that,C&>,
135 non_const_pointee<that> > non_const_cond;
136
137 typedef typename mpl::eval_if< non_const_cond,
138 mpl::identity<C>, add_const<C> >::type qualified_class;
139
140 typedef typename mpl::eval_if< non_const_cond,
141 mpl::identity<T>, add_const<T> >::type qualified_type;
142
143 public:
144
145 typedef typename boost::add_reference<qualified_type>::type
146 result_type;
147
148 static inline result_type call(T C::* f, Sequence & s)
149 {
150 typename result_of::front<Sequence>::type c = fusion::front(s);
151 return that_ptr<qualified_class>::get(c)->*f;
152 }
153 };
154 }
155
156 namespace result_of
157 {
158 template <typename Function, class Sequence> struct invoke
159 {
160 typedef typename detail::invoke_impl<
161 typename boost::remove_reference<Function>::type, Sequence
162 >::result_type type;
163 };
164 }
165
166 template <typename Function, class Sequence>
167 inline typename result_of::invoke<Function,Sequence>::type
168 invoke(Function f, Sequence & s)
169 {
170 return detail::invoke_impl<
171 typename boost::remove_reference<Function>::type,Sequence
172 >::call(f,s);
173 }
174
175 template <typename Function, class Sequence>
176 inline typename result_of::invoke<Function,Sequence const>::type
177 invoke(Function f, Sequence const & s)
178 {
179 return detail::invoke_impl<
180 typename boost::remove_reference<Function>::type,Sequence const
181 >::call(f,s);
182 }
183
184 }}
185
186 #define BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_HPP_INCLUDED
187 #else // defined(BOOST_PP_IS_ITERATING)
188 ///////////////////////////////////////////////////////////////////////////////
189 //
190 // Preprocessor vertical repetition code
191 //
192 ///////////////////////////////////////////////////////////////////////////////
193 #define N BOOST_PP_ITERATION()
194
195 template <typename Function, class Sequence>
196 struct invoke_impl<Function,Sequence,N,false,true>
197 {
198 public:
199
200 typedef typename boost::result_of<
201 #define M(z,j,data) typename result_of::at_c<Sequence,j>::type
202 Function(BOOST_PP_ENUM(N,M,~)) >::type result_type;
203 #undef M
204
205 #if N > 0
206
207 template <typename F>
208 static inline result_type
209 call(F & f, Sequence & s)
210 {
211 #define M(z,j,data) fusion::at_c<j>(s)
212 return f( BOOST_PP_ENUM(N,M,~) );
213 }
214
215 #else
216 template <typename F>
217 static inline result_type
218 call(F & f, Sequence & /*s*/)
219 {
220 return f();
221 }
222
223 #endif
224
225 };
226
227 template <typename Function, class Sequence>
228 struct invoke_fn_ptr<Function,Sequence,N,true>
229 {
230 public:
231
232 typedef typename ft::result_type<Function>::type result_type;
233
234 #if N > 0
235
236 template <typename F>
237 static inline result_type
238 call(F & f, Sequence & s)
239 {
240 #define M(z,j,data) fusion::at_c<j>(s)
241 return f( BOOST_PP_ENUM(N,M,~) );
242 }
243
244 #else
245 template <typename F>
246 static inline result_type
247 call(F & f, Sequence & /*s*/)
248 {
249 return f();
250 }
251
252 #endif
253
254 };
255
256
257 #if N > 0
258 template <typename Function, class Sequence>
259 struct invoke_mem_fn<Function,Sequence,N,true>
260 {
261 public:
262
263 typedef typename ft::result_type<Function>::type result_type;
264
265 template <typename F>
266 static inline result_type
267 call(F & f, Sequence & s)
268 {
269 return (that_ptr<typename mpl::front<
270 ft::parameter_types<Function> >::type
271 >::get(fusion::at_c<0>(s))->*f)(BOOST_PP_ENUM_SHIFTED(N,M,~));
272 }
273 };
274 #endif
275
276 #undef M
277
278 #define M(z,j,data) \
279 typename seq::I##j i##j = \
280 fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(j)));
281
282 template <typename Function, class Sequence>
283 struct invoke_impl<Function,Sequence,N,false,false>
284 {
285 private:
286 typedef invoke_param_types<Sequence,N> seq;
287 public:
288
289 typedef typename boost::result_of<
290 Function(BOOST_PP_ENUM_PARAMS(N,typename seq::T))
291 >::type result_type;
292
293 #if N > 0
294
295 template <typename F>
296 static inline result_type
297 call(F & f, Sequence & s)
298 {
299 typename seq::I0 i0 = fusion::begin(s);
300 BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
301 return f( BOOST_PP_ENUM_PARAMS(N,*i) );
302 }
303
304 #else
305
306 template <typename F>
307 static inline result_type
308 call(F & f, Sequence & /*s*/)
309 {
310 return f();
311 }
312
313 #endif
314
315 };
316
317 template <typename Function, class Sequence>
318 struct invoke_fn_ptr<Function,Sequence,N,false>
319 {
320 private:
321 typedef invoke_param_types<Sequence,N> seq;
322 public:
323
324 typedef typename ft::result_type<Function>::type result_type;
325
326 #if N > 0
327
328 template <typename F>
329 static inline result_type
330 call(F & f, Sequence & s)
331 {
332 typename seq::I0 i0 = fusion::begin(s);
333 BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
334 return f( BOOST_PP_ENUM_PARAMS(N,*i) );
335 }
336
337 #else
338
339 template <typename F>
340 static inline result_type
341 call(F & f, Sequence & /*s*/)
342 {
343 return f();
344 }
345
346 #endif
347
348 };
349
350 #if N > 0
351 template <typename Function, class Sequence>
352 struct invoke_mem_fn<Function,Sequence,N,false>
353 {
354 private:
355 typedef invoke_param_types<Sequence,N> seq;
356 public:
357
358 typedef typename ft::result_type<Function>::type result_type;
359
360 template <typename F>
361 static inline result_type
362 call(F & f, Sequence & s)
363 {
364 typename seq::I0 i0 = fusion::begin(s);
365 BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
366
367 return (that_ptr< typename mpl::front<
368 ft::parameter_types<Function> >::type
369 >::get(*i0)->*f)(BOOST_PP_ENUM_SHIFTED_PARAMS(N,*i));
370 }
371 };
372 #endif
373
374 #undef M
375
376 template <class Sequence> struct invoke_param_types<Sequence,N>
377 {
378 #if N > 0
379 typedef typename result_of::begin<Sequence>::type I0;
380 typedef typename result_of::deref<I0>::type T0;
381
382 #define M(z,i,data) \
383 typedef typename result_of::next< \
384 BOOST_PP_CAT(I,BOOST_PP_DEC(i))>::type I##i; \
385 typedef typename result_of::deref<I##i>::type T##i;
386
387 BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
388 #undef M
389 #endif
390 };
391
392
393 #undef N
394 #endif // defined(BOOST_PP_IS_ITERATING)
395 #endif
396