PageRenderTime 36ms CodeModel.GetById 15ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/proto/make_expr.hpp

http://hadesmem.googlecode.com/
C++ Header | 501 lines | 288 code | 36 blank | 177 comment | 0 complexity | 35ec970221c6bdc2423412b0a3064326 MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////////
  2/// \file make_expr.hpp
  3/// Definition of the \c make_expr() and \c unpack_expr() utilities for
  4/// building Proto expression nodes from child nodes or from a Fusion
  5/// sequence of child nodes, respectively.
  6//
  7//  Copyright 2008 Eric Niebler. Distributed under the Boost
  8//  Software License, Version 1.0. (See accompanying file
  9//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 10
 11#ifndef BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005
 12#define BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005
 13
 14#include <boost/preprocessor/cat.hpp>
 15#include <boost/preprocessor/arithmetic/inc.hpp>
 16#include <boost/preprocessor/arithmetic/dec.hpp>
 17#include <boost/preprocessor/arithmetic/sub.hpp>
 18#include <boost/preprocessor/punctuation/comma_if.hpp>
 19#include <boost/preprocessor/iteration/iterate.hpp>
 20#include <boost/preprocessor/facilities/intercept.hpp>
 21#include <boost/preprocessor/repetition/enum.hpp>
 22#include <boost/preprocessor/repetition/enum_params.hpp>
 23#include <boost/preprocessor/repetition/enum_binary_params.hpp>
 24#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
 25#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
 26#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
 27#include <boost/preprocessor/repetition/repeat.hpp>
 28#include <boost/ref.hpp>
 29#include <boost/mpl/if.hpp>
 30#include <boost/mpl/assert.hpp>
 31#include <boost/mpl/eval_if.hpp>
 32#include <boost/utility/enable_if.hpp>
 33#include <boost/type_traits/add_const.hpp>
 34#include <boost/type_traits/add_reference.hpp>
 35#include <boost/type_traits/remove_cv.hpp>
 36#include <boost/proto/proto_fwd.hpp>
 37#include <boost/proto/traits.hpp>
 38#include <boost/proto/domain.hpp>
 39#include <boost/proto/generate.hpp>
 40#include <boost/fusion/include/begin.hpp>
 41#include <boost/fusion/include/next.hpp>
 42#include <boost/fusion/include/value_of.hpp>
 43#include <boost/fusion/include/size.hpp>
 44#include <boost/proto/detail/poly_function.hpp>
 45#include <boost/proto/detail/deprecated.hpp>
 46
 47#ifdef _MSC_VER
 48# pragma warning(push)
 49# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored
 50#endif
 51
 52namespace boost { namespace proto
 53{
 54/// INTERNAL ONLY
 55///
 56#define BOOST_PROTO_AS_CHILD_TYPE(Z, N, DATA)                                                   \
 57    typename boost::proto::detail::protoify<                                                    \
 58        BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N)                                        \
 59      , BOOST_PP_TUPLE_ELEM(3, 2, DATA)                                                         \
 60    >::result_type                                                                              \
 61    /**/
 62
 63/// INTERNAL ONLY
 64///
 65#define BOOST_PROTO_AS_CHILD(Z, N, DATA)                                                        \
 66    boost::proto::detail::protoify<                                                             \
 67        BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N)                                        \
 68      , BOOST_PP_TUPLE_ELEM(3, 2, DATA)                                                         \
 69    >()(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 1, DATA), N))                                       \
 70    /**/
 71
 72    namespace detail
 73    {
 74        template<typename T, typename Domain>
 75        struct protoify
 76          : Domain::template as_expr<T>
 77        {};
 78
 79        template<typename T, typename Domain>
 80        struct protoify<T &, Domain>
 81          : Domain::template as_child<T>
 82        {};
 83
 84        template<typename T, typename Domain>
 85        struct protoify<boost::reference_wrapper<T>, Domain>
 86          : Domain::template as_child<T>
 87        {};
 88
 89        template<typename T, typename Domain>
 90        struct protoify<boost::reference_wrapper<T> const, Domain>
 91          : Domain::template as_child<T>
 92        {};
 93
 94        // Definition of detail::unpack_expr_
 95        #include <boost/proto/detail/unpack_expr_.hpp>
 96
 97        // Definition of detail::make_expr_
 98        #include <boost/proto/detail/make_expr_.hpp>
 99    }
100
101    namespace result_of
102    {
103        /// \brief Metafunction that computes the return type of the
104        /// \c make_expr() function, with a domain deduced from the
105        /// domains of the children.
106        ///
107        /// Use the <tt>result_of::make_expr\<\></tt> metafunction to
108        /// compute the return type of the \c make_expr() function.
109        ///
110        /// In this specialization, the domain is deduced from the
111        /// domains of the child types. (If
112        /// <tt>is_domain\<A0\>::value</tt> is \c true, then another
113        /// specialization is selected.)
114        template<
115            typename Tag
116          , BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, typename A)
117          , typename Void1  // = void
118          , typename Void2  // = void
119        >
120        struct make_expr
121        {
122            /// Same as <tt>result_of::make_expr\<Tag, D, A0, ... AN\>::type</tt>
123            /// where \c D is the deduced domain, which is calculated as follows:
124            ///
125            /// For each \c x in <tt>[0,N)</tt> (proceeding in order beginning with
126            /// <tt>x=0</tt>), if <tt>domain_of\<Ax\>::type</tt> is not
127            /// \c default_domain, then \c D is <tt>domain_of\<Ax\>::type</tt>.
128            /// Otherwise, \c D is \c default_domain.
129            typedef
130                typename detail::make_expr_<
131                    Tag
132                  , deduce_domain
133                    BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
134                >::result_type
135            type;
136        };
137
138        /// \brief Metafunction that computes the return type of the
139        /// \c make_expr() function, within the specified domain.
140        ///
141        /// Use the <tt>result_of::make_expr\<\></tt> metafunction to compute
142        /// the return type of the \c make_expr() function.
143        template<
144            typename Tag
145          , typename Domain
146            BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, typename A)
147        >
148        struct make_expr<
149            Tag
150          , Domain
151            BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
152          , typename Domain::proto_is_domain_
153        >
154        {
155            /// If \c Tag is <tt>tag::terminal</tt>, then \c type is a
156            /// typedef for <tt>boost::result_of\<Domain(expr\<tag::terminal,
157            /// term\<A0\> \>)\>::type</tt>.
158            ///
159            /// Otherwise, \c type is a typedef for <tt>boost::result_of\<Domain(expr\<Tag,
160            /// listN\< as_child\<A0\>::type, ... as_child\<AN\>::type\>)
161            /// \>::type</tt>, where \c N is the number of non-void template
162            /// arguments, and <tt>as_child\<A\>::type</tt> is evaluated as
163            /// follows:
164            ///
165            /// \li If <tt>is_expr\<A\>::value</tt> is \c true, then the
166            /// child type is \c A.
167            /// \li If \c A is <tt>B &</tt> or <tt>cv boost::reference_wrapper\<B\></tt>,
168            /// and <tt>is_expr\<B\>::value</tt> is \c true, then the
169            /// child type is <tt>B &</tt>.
170            /// \li If <tt>is_expr\<A\>::value</tt> is \c false, then the
171            /// child type is <tt>boost::result_of\<Domain(expr\<tag::terminal, term\<A\> \>
172            /// )\>::type</tt>.
173            /// \li If \c A is <tt>B &</tt> or <tt>cv boost::reference_wrapper\<B\></tt>,
174            /// and <tt>is_expr\<B\>::value</tt> is \c false, then the
175            /// child type is <tt>boost::result_of\<Domain(expr\<tag::terminal, term\<B &\> \>
176            /// )\>::type</tt>.
177            typedef
178                typename detail::make_expr_<
179                    Tag
180                  , Domain
181                    BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
182                >::result_type
183            type;
184        };
185
186        /// \brief Metafunction that computes the return type of the
187        /// \c unpack_expr() function, with a domain deduced from the
188        /// domains of the children.
189        ///
190        /// Use the <tt>result_of::unpack_expr\<\></tt> metafunction to
191        /// compute the return type of the \c unpack_expr() function.
192        ///
193        /// \c Sequence is a Fusion Forward Sequence.
194        ///
195        /// In this specialization, the domain is deduced from the
196        /// domains of the child types. (If
197        /// <tt>is_domain\<Sequence>::value</tt> is \c true, then another
198        /// specialization is selected.)
199        template<
200            typename Tag
201          , typename Sequence
202          , typename Void1  // = void
203          , typename Void2  // = void
204        >
205        struct unpack_expr
206        {
207            /// Let \c S be the type of a Fusion Random Access Sequence
208            /// equivalent to \c Sequence. Then \c type is the
209            /// same as <tt>result_of::make_expr\<Tag,
210            /// fusion::result_of::value_at_c\<S, 0\>::type, ...
211            /// fusion::result_of::value_at_c\<S, N-1\>::type\>::type</tt>,
212            /// where \c N is the size of \c S.
213            typedef
214                typename detail::unpack_expr_<
215                    Tag
216                  , deduce_domain
217                  , Sequence
218                  , fusion::result_of::size<Sequence>::type::value
219                >::type
220            type;
221        };
222
223        /// \brief Metafunction that computes the return type of the
224        /// \c unpack_expr() function, within the specified domain.
225        ///
226        /// Use the <tt>result_of::make_expr\<\></tt> metafunction to compute
227        /// the return type of the \c make_expr() function.
228        template<typename Tag, typename Domain, typename Sequence>
229        struct unpack_expr<Tag, Domain, Sequence, typename Domain::proto_is_domain_>
230        {
231            /// Let \c S be the type of a Fusion Random Access Sequence
232            /// equivalent to \c Sequence. Then \c type is the
233            /// same as <tt>result_of::make_expr\<Tag, Domain,
234            /// fusion::result_of::value_at_c\<S, 0\>::type, ...
235            /// fusion::result_of::value_at_c\<S, N-1\>::type\>::type</tt>,
236            /// where \c N is the size of \c S.
237            typedef
238                typename detail::unpack_expr_<
239                    Tag
240                  , Domain
241                  , Sequence
242                  , fusion::result_of::size<Sequence>::type::value
243                >::type
244            type;
245        };
246    }
247
248    namespace functional
249    {
250        /// \brief A callable function object equivalent to the
251        /// \c proto::make_expr() function.
252        ///
253        /// In all cases, <tt>functional::make_expr\<Tag, Domain\>()(a0, ... aN)</tt>
254        /// is equivalent to <tt>proto::make_expr\<Tag, Domain\>(a0, ... aN)</tt>.
255        ///
256        /// <tt>functional::make_expr\<Tag\>()(a0, ... aN)</tt>
257        /// is equivalent to <tt>proto::make_expr\<Tag\>(a0, ... aN)</tt>.
258        template<typename Tag, typename Domain  /* = deduce_domain*/>
259        struct make_expr
260        {
261            BOOST_PROTO_CALLABLE()
262            BOOST_PROTO_POLY_FUNCTION()
263
264            template<typename Sig>
265            struct result;
266
267            template<typename This, typename A0>
268            struct result<This(A0)>
269            {
270                typedef
271                    typename result_of::make_expr<
272                        Tag
273                      , Domain
274                      , A0
275                    >::type
276                type;
277            };
278
279            /// Construct an expression node with tag type \c Tag
280            /// and in the domain \c Domain.
281            ///
282            /// \return <tt>proto::make_expr\<Tag, Domain\>(a0,...aN)</tt>
283            template<typename A0>
284            typename result_of::make_expr<
285                Tag
286              , Domain
287              , A0 const
288            >::type const
289            operator ()(A0 const &a0) const
290            {
291                return proto::detail::make_expr_<
292                    Tag
293                  , Domain
294                  , A0 const
295                >()(a0);
296            }
297
298            // Additional overloads generated by the preprocessor ...
299            #include <boost/proto/detail/make_expr_funop.hpp>
300
301            /// INTERNAL ONLY
302            ///
303            template<
304                BOOST_PP_ENUM_BINARY_PARAMS(
305                    BOOST_PROTO_MAX_ARITY
306                  , typename A
307                  , = void BOOST_PP_INTERCEPT
308                )
309            >
310            struct impl
311              : detail::make_expr_<
312                  Tag
313                , Domain
314                  BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
315                >
316            {};
317        };
318
319        /// \brief A callable function object equivalent to the
320        /// \c proto::unpack_expr() function.
321        ///
322        /// In all cases, <tt>functional::unpack_expr\<Tag, Domain\>()(seq)</tt>
323        /// is equivalent to <tt>proto::unpack_expr\<Tag, Domain\>(seq)</tt>.
324        ///
325        /// <tt>functional::unpack_expr\<Tag\>()(seq)</tt>
326        /// is equivalent to <tt>proto::unpack_expr\<Tag\>(seq)</tt>.
327        template<typename Tag, typename Domain /* = deduce_domain*/>
328        struct unpack_expr
329        {
330            BOOST_PROTO_CALLABLE()
331
332            template<typename Sig>
333            struct result;
334
335            template<typename This, typename Sequence>
336            struct result<This(Sequence)>
337            {
338                typedef
339                    typename result_of::unpack_expr<
340                        Tag
341                      , Domain
342                      , typename remove_reference<Sequence>::type
343                    >::type
344                type;
345            };
346
347            /// Construct an expression node with tag type \c Tag
348            /// and in the domain \c Domain.
349            ///
350            /// \param sequence A Fusion Forward Sequence
351            /// \return <tt>proto::unpack_expr\<Tag, Domain\>(sequence)</tt>
352            template<typename Sequence>
353            typename result_of::unpack_expr<Tag, Domain, Sequence const>::type const
354            operator ()(Sequence const &sequence) const
355            {
356                return proto::detail::unpack_expr_<
357                    Tag
358                  , Domain
359                  , Sequence const
360                  , fusion::result_of::size<Sequence>::type::value
361                >::call(sequence);
362            }
363        };
364
365    } // namespace functional
366
367    /// \brief Construct an expression of the requested tag type
368    /// with a domain and with the specified arguments as children.
369    ///
370    /// This function template may be invoked either with or without
371    /// specifying a \c Domain argument. If no domain is specified,
372    /// the domain is deduced by examining in order the domains of
373    /// the given arguments and taking the first that is not
374    /// \c default_domain, if any such domain exists, or
375    /// \c default_domain otherwise.
376    ///
377    /// Let \c wrap_(x) be defined such that:
378    /// \li If \c x is a <tt>boost::reference_wrapper\<\></tt>,
379    /// \c wrap_(x) is equivalent to <tt>as_child\<Domain\>(x.get())</tt>.
380    /// \li Otherwise, \c wrap_(x) is equivalent to
381    /// <tt>as_expr\<Domain\>(x)</tt>.
382    ///
383    /// Let <tt>make_\<Tag\>(b0,...bN)</tt> be defined as
384    /// <tt>expr\<Tag, listN\<C0,...CN\> \>::make(c0,...cN)</tt>
385    /// where \c Bx is the type of \c bx.
386    ///
387    /// \return <tt>Domain()(make_\<Tag\>(wrap_(a0),...wrap_(aN)))</tt>.
388    template<typename Tag, typename A0>
389    typename lazy_disable_if<
390        is_domain<A0>
391      , result_of::make_expr<
392            Tag
393          , A0 const
394        >
395    >::type const
396    make_expr(A0 const &a0)
397    {
398        return proto::detail::make_expr_<
399            Tag
400          , deduce_domain
401          , A0 const
402        >()(a0);
403    }
404
405    /// \overload
406    ///
407    template<typename Tag, typename Domain, typename C0>
408    typename result_of::make_expr<
409        Tag
410      , Domain
411      , C0 const
412    >::type const
413    make_expr(C0 const &c0)
414    {
415        return proto::detail::make_expr_<
416            Tag
417          , Domain
418          , C0 const
419        >()(c0);
420    }
421
422    // Additional overloads generated by the preprocessor...
423    #include <boost/proto/detail/make_expr.hpp>
424
425    /// \brief Construct an expression of the requested tag type
426    /// with a domain and with childres from the specified Fusion
427    /// Forward Sequence.
428    ///
429    /// This function template may be invoked either with or without
430    /// specifying a \c Domain argument. If no domain is specified,
431    /// the domain is deduced by examining in order the domains of the
432    /// elements of \c sequence and taking the first that is not
433    /// \c default_domain, if any such domain exists, or
434    /// \c default_domain otherwise.
435    ///
436    /// Let \c s be a Fusion Random Access Sequence equivalent to \c sequence.
437    /// Let <tt>wrap_\<N\>(s)</tt>, where \c s has type \c S, be defined
438    /// such that:
439    /// \li If <tt>fusion::result_of::value_at_c\<S,N\>::type</tt> is a reference,
440    /// <tt>wrap_\<N\>(s)</tt> is equivalent to
441    /// <tt>as_child\<Domain\>(fusion::at_c\<N\>(s))</tt>.
442    /// \li Otherwise, <tt>wrap_\<N\>(s)</tt> is equivalent to
443    /// <tt>as_expr\<Domain\>(fusion::at_c\<N\>(s))</tt>.
444    ///
445    /// Let <tt>make_\<Tag\>(b0,...bN)</tt> be defined as
446    /// <tt>expr\<Tag, listN\<B0,...BN\> \>::make(b0,...bN)</tt>
447    /// where \c Bx is the type of \c bx.
448    ///
449    /// \param sequence a Fusion Forward Sequence.
450    /// \return <tt>Domain()(make_\<Tag\>(wrap_\<0\>(s),...wrap_\<N-1\>(s)))</tt>,
451    /// where N is the size of \c Sequence.
452    template<typename Tag, typename Sequence>
453    typename lazy_disable_if<
454        is_domain<Sequence>
455      , result_of::unpack_expr<Tag, Sequence const>
456    >::type const
457    unpack_expr(Sequence const &sequence)
458    {
459        return proto::detail::unpack_expr_<
460            Tag
461          , deduce_domain
462          , Sequence const
463          , fusion::result_of::size<Sequence>::type::value
464        >::call(sequence);
465    }
466
467    /// \overload
468    ///
469    template<typename Tag, typename Domain, typename Sequence2>
470    typename result_of::unpack_expr<Tag, Domain, Sequence2 const>::type const
471    unpack_expr(Sequence2 const &sequence2)
472    {
473        return proto::detail::unpack_expr_<
474            Tag
475          , Domain
476          , Sequence2 const
477          , fusion::result_of::size<Sequence2>::type::value
478        >::call(sequence2);
479    }
480
481    /// INTERNAL ONLY
482    ///
483    template<typename Tag, typename Domain>
484    struct is_callable<functional::make_expr<Tag, Domain> >
485      : mpl::true_
486    {};
487
488    /// INTERNAL ONLY
489    ///
490    template<typename Tag, typename Domain>
491    struct is_callable<functional::unpack_expr<Tag, Domain> >
492      : mpl::true_
493    {};
494
495}}
496
497#ifdef _MSC_VER
498# pragma warning(pop)
499#endif
500
501#endif // BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005