• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_FUNCTION_OBJECT_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_params.hpp>
19 
20 #include <boost/utility/result_of.hpp>
21 #include <boost/core/enable_if.hpp>
22 
23 #include <boost/type_traits/remove_reference.hpp>
24 #include <boost/type_traits/remove_const.hpp>
25 
26 #include <boost/fusion/support/category_of.hpp>
27 #include <boost/fusion/sequence/intrinsic/size.hpp>
28 #include <boost/fusion/sequence/intrinsic/at.hpp>
29 #include <boost/fusion/sequence/intrinsic/begin.hpp>
30 #include <boost/fusion/iterator/next.hpp>
31 #include <boost/fusion/iterator/deref.hpp>
32 #include <boost/fusion/functional/invocation/limits.hpp>
33 
34 namespace boost { namespace fusion
35 {
36     namespace detail
37     {
38         template<
39             class Function, class Sequence,
40             int N = result_of::size<Sequence>::value,
41             bool RandomAccess = traits::is_random_access<Sequence>::value,
42             typename Enable = void
43             >
44         struct invoke_function_object_impl;
45 
46         template <class Sequence, int N>
47         struct invoke_function_object_param_types;
48 
49         #define  BOOST_PP_FILENAME_1 \
50             <boost/fusion/functional/invocation/invoke_function_object.hpp>
51         #define  BOOST_PP_ITERATION_LIMITS \
52             (0, BOOST_FUSION_INVOKE_FUNCTION_OBJECT_MAX_ARITY)
53         #include BOOST_PP_ITERATE()
54     }
55 
56     namespace result_of
57     {
58         template <class Function, class Sequence, class Enable = void>
59         struct invoke_function_object;
60 
61         template <class Function, class Sequence>
62         struct invoke_function_object<Function, Sequence,
63             typename enable_if_has_type<
64                 typename detail::invoke_function_object_impl<
65                     typename boost::remove_reference<Function>::type, Sequence
66                 >::result_type
67             >::type>
68         {
69             typedef typename detail::invoke_function_object_impl<
70                 typename boost::remove_reference<Function>::type, Sequence
71                 >::result_type type;
72         };
73     }
74 
75     template <class Function, class Sequence>
76     BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
77     inline typename result_of::invoke_function_object<Function,Sequence>::type
invoke_function_object(Function f,Sequence & s)78     invoke_function_object(Function f, Sequence & s)
79     {
80         return detail::invoke_function_object_impl<
81                 typename boost::remove_reference<Function>::type,Sequence
82             >::call(f,s);
83     }
84 
85     template <class Function, class Sequence>
86     BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
87     inline typename result_of::invoke_function_object<Function,Sequence const>::type
invoke_function_object(Function f,Sequence const & s)88     invoke_function_object(Function f, Sequence const & s)
89     {
90         return detail::invoke_function_object_impl<
91                 typename boost::remove_reference<Function>::type,Sequence const
92             >::call(f,s);
93     }
94 
95 }}
96 
97 #define BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_FUNCTION_OBJECT_HPP_INCLUDED
98 #else // defined(BOOST_PP_IS_ITERATING)
99 ///////////////////////////////////////////////////////////////////////////////
100 //
101 //  Preprocessor vertical repetition code
102 //
103 ///////////////////////////////////////////////////////////////////////////////
104 #define N BOOST_PP_ITERATION()
105 
106 #define M(z,j,data)                                                             \
107         typename result_of::at_c<Sequence,j>::type
108 
109         template <class Function, class Sequence>
110         struct invoke_function_object_impl<Function,Sequence,N,true,
111             typename enable_if_has_type<
112                 typename boost::result_of<Function (BOOST_PP_ENUM(N,M,~)) >::type
113             >::type>
114         {
115         public:
116 
117             typedef typename boost::result_of<
118                 Function (BOOST_PP_ENUM(N,M,~)) >::type result_type;
119 #undef M
120 
121 #if N > 0
122 
123             template <class F>
124             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
125             static inline result_type
callinvoke_function_object_impl126             call(F & f, Sequence & s)
127             {
128 #define M(z,j,data) fusion::at_c<j>(s)
129                 return f( BOOST_PP_ENUM(N,M,~) );
130 #undef M
131             }
132 
133 #else
134 
135             template <class F>
136             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
137             static inline result_type
callinvoke_function_object_impl138             call(F & f, Sequence & /*s*/)
139             {
140                 return f();
141             }
142 
143 #endif
144 
145         };
146 
147 #define M(z,j,data)                                                             \
148             typename invoke_function_object_param_types<Sequence,N>::T ## j
149 
150         template <class Function, class Sequence>
151         struct invoke_function_object_impl<Function,Sequence,N,false,
152             typename enable_if_has_type<
153                 typename boost::result_of<Function (BOOST_PP_ENUM(N,M,~)) >::type
154             >::type>
155 #undef M
156         {
157         private:
158             typedef invoke_function_object_param_types<Sequence,N> seq;
159         public:
160             typedef typename boost::result_of<
161                 Function (BOOST_PP_ENUM_PARAMS(N,typename seq::T))
162                 >::type result_type;
163 
164 #if N > 0
165 
166             template <class F>
167             BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
168             static inline result_type
callinvoke_function_object_impl169             call(F & f, Sequence & s)
170             {
171                 typename seq::I0 i0 = fusion::begin(s);
172 #define M(z,j,data)                                                             \
173             typename seq::I##j i##j =                                          \
174                 fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(j)));
175                 BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
176 #undef M
177                 return f( BOOST_PP_ENUM_PARAMS(N,*i) );
178             }
179 
180 #else
181 
182             template <class F>
183             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
184             static inline result_type
callinvoke_function_object_impl185             call(F & f, Sequence & /*s*/)
186             {
187                 return f();
188             }
189 
190 #endif
191 
192         };
193 
194         template <class Sequence>
195         struct invoke_function_object_param_types<Sequence,N>
196         {
197 #if N > 0
198             typedef typename result_of::begin<Sequence>::type I0;
199             typedef typename result_of::deref<I0>::type T0;
200 
201 #define M(z,i,data)                                                             \
202             typedef typename result_of::next<                                  \
203                 BOOST_PP_CAT(I,BOOST_PP_DEC(i))>::type I##i;                   \
204             typedef typename result_of::deref<I##i>::type T##i;
205 
206             BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
207 #undef M
208 #endif
209         };
210 
211 #undef N
212 #endif // defined(BOOST_PP_IS_ITERATING)
213 #endif
214 
215