]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/proto/include/boost/proto/transform/call.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / proto / include / boost / proto / transform / call.hpp
CommitLineData
7c673cae
FG
1///////////////////////////////////////////////////////////////////////////////
2/// \file call.hpp
3/// Contains definition of the call<> transform.
4//
5// Copyright 2008 Eric Niebler. Distributed under the Boost
6// Software License, Version 1.0. (See accompanying file
7// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9#ifndef BOOST_PROTO_TRANSFORM_CALL_HPP_EAN_11_02_2007
10#define BOOST_PROTO_TRANSFORM_CALL_HPP_EAN_11_02_2007
11
12#if defined(_MSC_VER)
13# pragma warning(push)
14# pragma warning(disable: 4714) // function 'xxx' marked as __forceinline not inlined
15#endif
16
17#include <boost/preprocessor/cat.hpp>
18#include <boost/preprocessor/facilities/intercept.hpp>
19#include <boost/preprocessor/iteration/iterate.hpp>
20#include <boost/preprocessor/repetition/enum.hpp>
21#include <boost/preprocessor/repetition/repeat.hpp>
22#include <boost/preprocessor/repetition/enum_params.hpp>
23#include <boost/preprocessor/repetition/enum_binary_params.hpp>
24#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
25#include <boost/ref.hpp>
26#include <boost/utility/result_of.hpp>
27#include <boost/proto/proto_fwd.hpp>
28#include <boost/proto/traits.hpp>
29#include <boost/proto/transform/impl.hpp>
30#include <boost/proto/detail/as_lvalue.hpp>
31#include <boost/proto/detail/poly_function.hpp>
32#include <boost/proto/transform/detail/pack.hpp>
33
34namespace boost { namespace proto
35{
36 /// \brief Wrap \c PrimitiveTransform so that <tt>when\<\></tt> knows
37 /// it is callable. Requires that the parameter is actually a
38 /// PrimitiveTransform.
39 ///
40 /// This form of <tt>call\<\></tt> is useful for annotating an
41 /// arbitrary PrimitiveTransform as callable when using it with
42 /// <tt>when\<\></tt>. Consider the following transform, which
43 /// is parameterized with another transform.
44 ///
45 /// \code
46 /// template<typename Grammar>
47 /// struct Foo
48 /// : when<
49 /// unary_plus<Grammar>
50 /// , Grammar(_child) // May or may not work.
51 /// >
52 /// {};
53 /// \endcode
54 ///
55 /// The problem with the above is that <tt>when\<\></tt> may or
56 /// may not recognize \c Grammar as callable, depending on how
57 /// \c Grammar is implemented. (See <tt>is_callable\<\></tt> for
58 /// a discussion of this issue.) You can guard against
59 /// the issue by wrapping \c Grammar in <tt>call\<\></tt>, such
60 /// as:
61 ///
62 /// \code
63 /// template<typename Grammar>
64 /// struct Foo
65 /// : when<
66 /// unary_plus<Grammar>
67 /// , call<Grammar>(_child) // OK, this works
68 /// >
69 /// {};
70 /// \endcode
71 ///
72 /// The above could also have been written as:
73 ///
74 /// \code
75 /// template<typename Grammar>
76 /// struct Foo
77 /// : when<
78 /// unary_plus<Grammar>
79 /// , call<Grammar(_child)> // OK, this works, too
80 /// >
81 /// {};
82 /// \endcode
83 template<typename PrimitiveTransform>
84 struct call
85 : PrimitiveTransform
86 {};
87
88 /// \brief A specialization that treats function pointer Transforms as
89 /// if they were function type Transforms.
90 ///
91 /// This specialization requires that \c Fun is actually a function type.
92 ///
93 /// This specialization is required for nested transforms such as
94 /// <tt>call\<T0(T1(_))\></tt>. In C++, functions that are used as
95 /// parameters to other functions automatically decay to funtion
96 /// pointer types. In other words, the type <tt>T0(T1(_))</tt> is
97 /// indistinguishable from <tt>T0(T1(*)(_))</tt>. This specialization
98 /// is required to handle these nested function pointer type transforms
99 /// properly.
100 template<typename Fun>
101 struct call<Fun *>
102 : call<Fun>
103 {};
104
105 /// INTERNAL ONLY
106 template<typename Fun>
107 struct call<detail::msvc_fun_workaround<Fun> >
108 : call<Fun>
109 {};
110
111 /// \brief Either call the PolymorphicFunctionObject with 0
112 /// arguments, or invoke the PrimitiveTransform with 3
113 /// arguments.
114 template<typename Fun>
115 struct call<Fun()> : transform<call<Fun()> >
116 {
117 /// INTERNAL ONLY
118 template<typename Expr, typename State, typename Data, bool B>
119 struct impl2
120 : transform_impl<Expr, State, Data>
121 {
122 typedef typename BOOST_PROTO_RESULT_OF<Fun()>::type result_type;
123
124 BOOST_FORCEINLINE
125 result_type operator()(
126 typename impl2::expr_param
127 , typename impl2::state_param
128 , typename impl2::data_param
129 ) const
130 {
131 return Fun()();
132 }
133 };
134
135 /// INTERNAL ONLY
136 template<typename Expr, typename State, typename Data>
137 struct impl2<Expr, State, Data, true>
138 : Fun::template impl<Expr, State, Data>
139 {};
140
141 /// Either call the PolymorphicFunctionObject \c Fun with 0 arguments; or
142 /// invoke the PrimitiveTransform \c Fun with 3 arguments: the current
143 /// expression, state, and data.
144 ///
145 /// If \c Fun is a nullary PolymorphicFunctionObject, return <tt>Fun()()</tt>.
146 /// Otherwise, return <tt>Fun()(e, s, d)</tt>.
147 ///
148 /// \param e The current expression
149 /// \param s The current state
150 /// \param d An arbitrary data
151
152 /// If \c Fun is a nullary PolymorphicFunctionObject, \c type is a typedef
153 /// for <tt>boost::result_of\<Fun()\>::type</tt>. Otherwise, it is
154 /// a typedef for <tt>boost::result_of\<Fun(Expr, State, Data)\>::type</tt>.
155 template<typename Expr, typename State, typename Data>
156 struct impl
157 : impl2<Expr, State, Data, detail::is_transform_<Fun>::value>
158 {};
159 };
160
161 /// \brief Either call the PolymorphicFunctionObject with 1
162 /// argument, or invoke the PrimitiveTransform with 3
163 /// arguments.
164 template<typename Fun, typename A0>
165 struct call<Fun(A0)> : transform<call<Fun(A0)> >
166 {
167 template<typename Expr, typename State, typename Data, bool B>
168 struct impl2
169 : transform_impl<Expr, State, Data>
170 {
171 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
172 typedef typename detail::poly_function_traits<Fun, Fun(a0)>::result_type result_type;
173
174 BOOST_FORCEINLINE
175 result_type operator ()(
176 typename impl2::expr_param e
177 , typename impl2::state_param s
178 , typename impl2::data_param d
179 ) const
180 {
181 return typename detail::poly_function_traits<Fun, Fun(a0)>::function_type()(
182 detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
183 );
184 }
185 };
186
187 template<typename Expr, typename State, typename Data>
188 struct impl2<Expr, State, Data, true>
189 : transform_impl<Expr, State, Data>
190 {
191 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
192 typedef typename Fun::template impl<a0, State, Data>::result_type result_type;
193
194 BOOST_FORCEINLINE
195 result_type operator ()(
196 typename impl2::expr_param e
197 , typename impl2::state_param s
198 , typename impl2::data_param d
199 ) const
200 {
201 return typename Fun::template impl<a0, State, Data>()(
202 typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
203 , s
204 , d
205 );
206 }
207 };
208 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt> and \c X
209 /// be the type of \c x.
210 /// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
211 /// then \c type is a typedef for <tt>boost::result_of\<Fun(X)\>::type</tt>.
212 /// Otherwise, it is a typedef for <tt>boost::result_of\<Fun(X, State, Data)\>::type</tt>.
213
214 /// Either call the PolymorphicFunctionObject with 1 argument:
215 /// the result of applying the \c A0 transform; or
216 /// invoke the PrimitiveTransform with 3 arguments:
217 /// result of applying the \c A0 transform, the state, and the
218 /// data.
219 ///
220 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
221 /// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
222 /// then return <tt>Fun()(x)</tt>. Otherwise, return
223 /// <tt>Fun()(x, s, d)</tt>.
224 ///
225 /// \param e The current expression
226 /// \param s The current state
227 /// \param d An arbitrary data
228 template<typename Expr, typename State, typename Data>
229 struct impl
230 : impl2<Expr, State, Data, detail::is_transform_<Fun>::value>
231 {};
232 };
233
234 /// \brief Either call the PolymorphicFunctionObject with 2
235 /// arguments, or invoke the PrimitiveTransform with 3
236 /// arguments.
237 template<typename Fun, typename A0, typename A1>
238 struct call<Fun(A0, A1)> : transform<call<Fun(A0, A1)> >
239 {
240 template<typename Expr, typename State, typename Data, bool B>
241 struct impl2
242 : transform_impl<Expr, State, Data>
243 {
244 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
245 typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
246 typedef typename detail::poly_function_traits<Fun, Fun(a0, a1)>::result_type result_type;
247
248 BOOST_FORCEINLINE
249 result_type operator ()(
250 typename impl2::expr_param e
251 , typename impl2::state_param s
252 , typename impl2::data_param d
253 ) const
254 {
255 return typename detail::poly_function_traits<Fun, Fun(a0, a1)>::function_type()(
256 detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
257 , detail::as_lvalue(typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d))
258 );
259 }
260 };
261
262 template<typename Expr, typename State, typename Data>
263 struct impl2<Expr, State, Data, true>
264 : transform_impl<Expr, State, Data>
265 {
266 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
267 typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
268 typedef typename Fun::template impl<a0, a1, Data>::result_type result_type;
269
270 BOOST_FORCEINLINE
271 result_type operator ()(
272 typename impl2::expr_param e
273 , typename impl2::state_param s
274 , typename impl2::data_param d
275 ) const
276 {
277 return typename Fun::template impl<a0, a1, Data>()(
278 typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
279 , typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d)
280 , d
281 );
282 }
283 };
284
285 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt> and \c X
286 /// be the type of \c x.
287 /// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt> and \c Y
288 /// be the type of \c y.
289 /// If \c Fun is a binary PolymorphicFunction object that accepts \c x
290 /// and \c y, then \c type is a typedef for
291 /// <tt>boost::result_of\<Fun(X, Y)\>::type</tt>. Otherwise, it is
292 /// a typedef for <tt>boost::result_of\<Fun(X, Y, Data)\>::type</tt>.
293
294 /// Either call the PolymorphicFunctionObject with 2 arguments:
295 /// the result of applying the \c A0 transform, and the
296 /// result of applying the \c A1 transform; or invoke the
297 /// PrimitiveTransform with 3 arguments: the result of applying
298 /// the \c A0 transform, the result of applying the \c A1
299 /// transform, and the data.
300 ///
301 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
302 /// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt>.
303 /// If \c Fun is a binary PolymorphicFunction object that accepts \c x
304 /// and \c y, return <tt>Fun()(x, y)</tt>. Otherwise, return
305 /// <tt>Fun()(x, y, d)</tt>.
306 ///
307 /// \param e The current expression
308 /// \param s The current state
309 /// \param d An arbitrary data
310 template<typename Expr, typename State, typename Data>
311 struct impl
312 : impl2<Expr, State, Data, detail::is_transform_<Fun>::value>
313 {};
314 };
315
316 /// \brief Call the PolymorphicFunctionObject or the
317 /// PrimitiveTransform with the current expression, state
318 /// and data, transformed according to \c A0, \c A1, and
319 /// \c A2, respectively.
320 template<typename Fun, typename A0, typename A1, typename A2>
321 struct call<Fun(A0, A1, A2)> : transform<call<Fun(A0, A1, A2)> >
322 {
323 template<typename Expr, typename State, typename Data, bool B>
324 struct impl2
325 : transform_impl<Expr, State, Data>
326 {
327 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
328 typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
329 typedef typename when<_, A2>::template impl<Expr, State, Data>::result_type a2;
330 typedef typename detail::poly_function_traits<Fun, Fun(a0, a1, a2)>::result_type result_type;
331
332 BOOST_FORCEINLINE
333 result_type operator ()(
334 typename impl2::expr_param e
335 , typename impl2::state_param s
336 , typename impl2::data_param d
337 ) const
338 {
339 return typename detail::poly_function_traits<Fun, Fun(a0, a1, a2)>::function_type()(
340 detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
341 , detail::as_lvalue(typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d))
342 , detail::as_lvalue(typename when<_, A2>::template impl<Expr, State, Data>()(e, s, d))
343 );
344 }
345 };
346
347 template<typename Expr, typename State, typename Data>
348 struct impl2<Expr, State, Data, true>
349 : transform_impl<Expr, State, Data>
350 {
351 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
352 typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
353 typedef typename when<_, A2>::template impl<Expr, State, Data>::result_type a2;
354 typedef typename Fun::template impl<a0, a1, a2>::result_type result_type;
355
356 BOOST_FORCEINLINE
357 result_type operator ()(
358 typename impl2::expr_param e
359 , typename impl2::state_param s
360 , typename impl2::data_param d
361 ) const
362 {
363 return typename Fun::template impl<a0, a1, a2>()(
364 typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
365 , typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d)
366 , typename when<_, A2>::template impl<Expr, State, Data>()(e, s, d)
367 );
368 }
369 };
370
371 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
372 /// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt>.
373 /// Let \c z be <tt>when\<_, A2\>()(e, s, d)</tt>.
374 /// Return <tt>Fun()(x, y, z)</tt>.
375 ///
376 /// \param e The current expression
377 /// \param s The current state
378 /// \param d An arbitrary data
379
380 template<typename Expr, typename State, typename Data>
381 struct impl
382 : impl2<Expr, State, Data, detail::is_transform_<Fun>::value>
383 {};
384 };
385
386 #include <boost/proto/transform/detail/call.hpp>
387
388 /// INTERNAL ONLY
389 ///
390 template<typename Fun>
391 struct is_callable<call<Fun> >
392 : mpl::true_
393 {};
394
395}} // namespace boost::proto
396
397#if defined(_MSC_VER)
398# pragma warning(pop)
399#endif
400
401#endif