Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:33

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file generate.hpp
0003 /// Contains definition of generate\<\> class template, which end users can
0004 /// specialize for generating domain-specific expression wrappers.
0005 //
0006 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0007 //  Software License, Version 1.0. (See accompanying file
0008 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 #ifndef BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007
0011 #define BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007
0012 
0013 #include <boost/config.hpp>
0014 #include <boost/version.hpp>
0015 #include <boost/preprocessor/cat.hpp>
0016 #include <boost/preprocessor/iteration/iterate.hpp>
0017 #include <boost/preprocessor/facilities/intercept.hpp>
0018 #include <boost/preprocessor/repetition/enum_params.hpp>
0019 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
0020 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
0021 #include <boost/mpl/bool.hpp>
0022 #include <boost/utility/enable_if.hpp>
0023 #include <boost/utility/result_of.hpp>
0024 #include <boost/proto/proto_fwd.hpp>
0025 #include <boost/proto/args.hpp>
0026 
0027 #if defined(_MSC_VER)
0028 # pragma warning(push)
0029 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
0030 #endif
0031 
0032 namespace boost { namespace proto
0033 {
0034 
0035     namespace detail
0036     {
0037         template<typename Expr>
0038         struct by_value_generator_;
0039 
0040         template<typename Tag, typename Arg>
0041         struct by_value_generator_<proto::expr<Tag, term<Arg>, 0> >
0042         {
0043             typedef
0044                 proto::expr<
0045                     Tag
0046                   , term<typename detail::term_traits<Arg>::value_type>
0047                   , 0
0048                 >
0049             type;
0050 
0051             BOOST_FORCEINLINE
0052             static type const call(proto::expr<Tag, term<Arg>, 0> const &e)
0053             {
0054                 type that = {e.child0};
0055                 return that;
0056             }
0057         };
0058 
0059         template<typename Tag, typename Arg>
0060         struct by_value_generator_<proto::basic_expr<Tag, term<Arg>, 0> >
0061         {
0062             typedef
0063                 proto::basic_expr<
0064                     Tag
0065                   , term<typename detail::term_traits<Arg>::value_type>
0066                   , 0
0067                 >
0068             type;
0069 
0070             BOOST_FORCEINLINE
0071             static type const call(proto::basic_expr<Tag, term<Arg>, 0> const &e)
0072             {
0073                 type that = {e.child0};
0074                 return that;
0075             }
0076         };
0077 
0078         // Include the other specializations of by_value_generator_
0079         #include <boost/proto/detail/generate_by_value.hpp>
0080     }
0081 
0082     /// \brief Annotate a generator to indicate that it would
0083     /// prefer to be passed instances of \c proto::basic_expr\<\> rather
0084     /// than \c proto::expr\<\>. <tt>use_basic_expr\<Generator\></tt> is
0085     /// itself a generator.
0086     ///
0087     template<typename Generator>
0088     struct use_basic_expr
0089       : Generator
0090     {
0091         BOOST_PROTO_USE_BASIC_EXPR()
0092     };
0093 
0094     /// \brief A simple generator that passes an expression
0095     /// through unchanged.
0096     ///
0097     /// Generators are intended for use as the first template parameter
0098     /// to the \c domain\<\> class template and control if and how
0099     /// expressions within that domain are to be customized.
0100     /// The \c default_generator makes no modifications to the expressions
0101     /// passed to it.
0102     struct default_generator
0103     {
0104         BOOST_PROTO_CALLABLE()
0105 
0106         template<typename Sig>
0107         struct result;
0108 
0109         template<typename This, typename Expr>
0110         struct result<This(Expr)>
0111         {
0112             typedef Expr type;
0113         };
0114 
0115         /// \param expr A Proto expression
0116         /// \return expr
0117         template<typename Expr>
0118         BOOST_FORCEINLINE
0119         BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(Expr, Expr const &)
0120         operator ()(Expr const &e) const
0121         {
0122             return e;
0123         }
0124     };
0125 
0126     /// \brief A simple generator that passes an expression
0127     /// through unchanged and specifies a preference for
0128     /// \c proto::basic_expr\<\> over \c proto::expr\<\>.
0129     ///
0130     /// Generators are intended for use as the first template parameter
0131     /// to the \c domain\<\> class template and control if and how
0132     /// expressions within that domain are to be customized.
0133     /// The \c default_generator makes no modifications to the expressions
0134     /// passed to it.
0135     struct basic_default_generator
0136       : proto::use_basic_expr<default_generator>
0137     {};
0138     
0139     /// \brief A generator that wraps expressions passed
0140     /// to it in the specified extension wrapper.
0141     ///
0142     /// Generators are intended for use as the first template parameter
0143     /// to the \c domain\<\> class template and control if and how
0144     /// expressions within that domain are to be customized.
0145     /// \c generator\<\> wraps each expression passed to it in
0146     /// the \c Extends\<\> wrapper.
0147     template<template<typename> class Extends>
0148     struct generator
0149     {
0150         BOOST_PROTO_CALLABLE()
0151         BOOST_PROTO_USE_BASIC_EXPR()
0152 
0153         template<typename Sig>
0154         struct result;
0155 
0156         template<typename This, typename Expr>
0157         struct result<This(Expr)>
0158         {
0159             typedef Extends<Expr> type;
0160         };
0161 
0162         template<typename This, typename Expr>
0163         struct result<This(Expr &)>
0164         {
0165             typedef Extends<Expr> type;
0166         };
0167 
0168         template<typename This, typename Expr>
0169         struct result<This(Expr const &)>
0170         {
0171             typedef Extends<Expr> type;
0172         };
0173 
0174         /// \param expr A Proto expression
0175         /// \return Extends<Expr>(expr)
0176         template<typename Expr>
0177         BOOST_FORCEINLINE
0178         Extends<Expr> operator ()(Expr const &e) const
0179         {
0180             return Extends<Expr>(e);
0181         }
0182     };
0183 
0184     /// \brief A generator that wraps expressions passed
0185     /// to it in the specified extension wrapper and uses
0186     /// aggregate initialization for the wrapper.
0187     ///
0188     /// Generators are intended for use as the first template parameter
0189     /// to the \c domain\<\> class template and control if and how
0190     /// expressions within that domain are to be customized.
0191     /// \c pod_generator\<\> wraps each expression passed to it in
0192     /// the \c Extends\<\> wrapper, and uses aggregate initialzation
0193     /// for the wrapped object.
0194     template<template<typename> class Extends>
0195     struct pod_generator
0196     {
0197         BOOST_PROTO_CALLABLE()
0198         BOOST_PROTO_USE_BASIC_EXPR()
0199 
0200         template<typename Sig>
0201         struct result;
0202 
0203         template<typename This, typename Expr>
0204         struct result<This(Expr)>
0205         {
0206             typedef Extends<Expr> type;
0207         };
0208 
0209         template<typename This, typename Expr>
0210         struct result<This(Expr &)>
0211         {
0212             typedef Extends<Expr> type;
0213         };
0214 
0215         template<typename This, typename Expr>
0216         struct result<This(Expr const &)>
0217         {
0218             typedef Extends<Expr> type;
0219         };
0220 
0221         /// \param expr The expression to wrap
0222         /// \return <tt>Extends\<Expr\> that = {expr}; return that;</tt>
0223         template<typename Expr>
0224         BOOST_FORCEINLINE
0225         Extends<Expr> operator ()(Expr const &e) const
0226         {
0227             Extends<Expr> that = {e};
0228             return that;
0229         }
0230 
0231         // Work-around for:
0232         // https://connect.microsoft.com/VisualStudio/feedback/details/765449/codegen-stack-corruption-using-runtime-checks-when-aggregate-initializing-struct
0233     #if BOOST_WORKAROUND(BOOST_MSVC, < 1800)
0234         template<typename Class, typename Member>
0235         BOOST_FORCEINLINE
0236         Extends<expr<tag::terminal, proto::term<Member Class::*> > > operator ()(expr<tag::terminal, proto::term<Member Class::*> > const &e) const
0237         {
0238             Extends<expr<tag::terminal, proto::term<Member Class::*> > > that;
0239             proto::value(that.proto_expr_) = proto::value(e);
0240             return that;
0241         }
0242 
0243         template<typename Class, typename Member>
0244         BOOST_FORCEINLINE
0245         Extends<basic_expr<tag::terminal, proto::term<Member Class::*> > > operator ()(basic_expr<tag::terminal, proto::term<Member Class::*> > const &e) const
0246         {
0247             Extends<basic_expr<tag::terminal, proto::term<Member Class::*> > > that;
0248             proto::value(that.proto_expr_) = proto::value(e);
0249             return that;
0250         }
0251     #endif
0252     };
0253 
0254     /// \brief A generator that replaces child nodes held by
0255     /// reference with ones held by value. Use with
0256     /// \c compose_generators to forward that result to another
0257     /// generator.
0258     ///
0259     /// Generators are intended for use as the first template parameter
0260     /// to the \c domain\<\> class template and control if and how
0261     /// expressions within that domain are to be customized.
0262     /// \c by_value_generator ensures all child nodes are
0263     /// held by value. This generator is typically composed with a
0264     /// second generator for further processing, as
0265     /// <tt>compose_generators\<by_value_generator, MyGenerator\></tt>.
0266     struct by_value_generator
0267     {
0268         BOOST_PROTO_CALLABLE()
0269 
0270         template<typename Sig>
0271         struct result;
0272 
0273         template<typename This, typename Expr>
0274         struct result<This(Expr)>
0275         {
0276             typedef
0277                 typename detail::by_value_generator_<Expr>::type
0278             type;
0279         };
0280 
0281         template<typename This, typename Expr>
0282         struct result<This(Expr &)>
0283         {
0284             typedef
0285                 typename detail::by_value_generator_<Expr>::type
0286             type;
0287         };
0288 
0289         template<typename This, typename Expr>
0290         struct result<This(Expr const &)>
0291         {
0292             typedef
0293                 typename detail::by_value_generator_<Expr>::type
0294             type;
0295         };
0296 
0297         /// \param expr The expression to modify.
0298         /// \return <tt>deep_copy(expr)</tt>
0299         template<typename Expr>
0300         BOOST_FORCEINLINE
0301         typename result<by_value_generator(Expr)>::type operator ()(Expr const &e) const
0302         {
0303             return detail::by_value_generator_<Expr>::call(e);
0304         }
0305     };
0306 
0307     /// \brief A composite generator that first applies one
0308     /// transform to an expression and then forwards the result
0309     /// on to another generator for further transformation.
0310     ///
0311     /// Generators are intended for use as the first template parameter
0312     /// to the \c domain\<\> class template and control if and how
0313     /// expressions within that domain are to be customized.
0314     /// \c compose_generators\<\> is a composite generator that first
0315     /// applies one transform to an expression and then forwards the
0316     /// result on to another generator for further transformation.
0317     template<typename First, typename Second>
0318     struct compose_generators
0319     {
0320         BOOST_PROTO_CALLABLE()
0321 
0322         template<typename Sig>
0323         struct result;
0324 
0325         template<typename This, typename Expr>
0326         struct result<This(Expr)>
0327         {
0328             typedef
0329                 typename Second::template result<
0330                     Second(typename First::template result<First(Expr)>::type)
0331                 >::type
0332             type;
0333         };
0334 
0335         template<typename This, typename Expr>
0336         struct result<This(Expr &)>
0337         {
0338             typedef
0339                 typename Second::template result<
0340                     Second(typename First::template result<First(Expr)>::type)
0341                 >::type
0342             type;
0343         };
0344 
0345         template<typename This, typename Expr>
0346         struct result<This(Expr const &)>
0347         {
0348             typedef
0349                 typename Second::template result<
0350                     Second(typename First::template result<First(Expr)>::type)
0351                 >::type
0352             type;
0353         };
0354 
0355         /// \param expr The expression to modify.
0356         /// \return Second()(First()(expr))
0357         template<typename Expr>
0358         BOOST_FORCEINLINE
0359         typename result<compose_generators(Expr)>::type operator ()(Expr const &e) const
0360         {
0361             return Second()(First()(e));
0362         }
0363     };
0364 
0365     /// \brief Tests a generator to see whether it would prefer
0366     /// to be passed instances of \c proto::basic_expr\<\> rather than
0367     /// \c proto::expr\<\>.
0368     ///
0369     template<typename Generator, typename Void>
0370     struct wants_basic_expr
0371       : mpl::false_
0372     {};
0373 
0374     template<typename Generator>
0375     struct wants_basic_expr<Generator, typename Generator::proto_use_basic_expr_>
0376       : mpl::true_
0377     {};
0378 
0379     /// INTERNAL ONLY
0380     template<>
0381     struct is_callable<default_generator>
0382       : mpl::true_
0383     {};
0384 
0385     /// INTERNAL ONLY
0386     template<template<typename> class Extends>
0387     struct is_callable<generator<Extends> >
0388       : mpl::true_
0389     {};
0390 
0391     /// INTERNAL ONLY
0392     template<template<typename> class Extends>
0393     struct is_callable<pod_generator<Extends> >
0394       : mpl::true_
0395     {};
0396 
0397     /// INTERNAL ONLY
0398     template<>
0399     struct is_callable<by_value_generator>
0400       : mpl::true_
0401     {};
0402 
0403     /// INTERNAL ONLY
0404     template<typename First, typename Second>
0405     struct is_callable<compose_generators<First, Second> >
0406       : mpl::true_
0407     {};
0408 
0409 }}
0410 
0411 // Specializations of boost::result_of and boost::tr1_result_of to eliminate
0412 // some unnecessary template instantiations
0413 namespace boost
0414 {
0415     template<typename Expr>
0416     struct result_of<proto::default_domain(Expr)>
0417     {
0418         typedef Expr type;
0419     };
0420 
0421     template<typename Expr>
0422     struct result_of<proto::basic_default_domain(Expr)>
0423     {
0424         typedef Expr type;
0425     };
0426 
0427     template<typename Expr>
0428     struct result_of<proto::default_generator(Expr)>
0429     {
0430         typedef Expr type;
0431     };
0432 
0433     template<typename Expr>
0434     struct result_of<proto::basic_default_generator(Expr)>
0435     {
0436         typedef Expr type;
0437     };
0438 
0439     #if BOOST_VERSION >= 104400
0440     template<typename Expr>
0441     struct tr1_result_of<proto::default_domain(Expr)>
0442     {
0443         typedef Expr type;
0444     };
0445 
0446     template<typename Expr>
0447     struct tr1_result_of<proto::basic_default_domain(Expr)>
0448     {
0449         typedef Expr type;
0450     };
0451 
0452     template<typename Expr>
0453     struct tr1_result_of<proto::default_generator(Expr)>
0454     {
0455         typedef Expr type;
0456     };
0457 
0458     template<typename Expr>
0459     struct tr1_result_of<proto::basic_default_generator(Expr)>
0460     {
0461         typedef Expr type;
0462     };
0463     #endif
0464 }
0465 
0466 #if defined(_MSC_VER)
0467 # pragma warning(pop)
0468 #endif
0469 
0470 #endif // BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007