Back to home page

EIC code displayed by LXR

 
 

    


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

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file domain.hpp
0003 /// Contains definition of domain\<\> class template and helpers for
0004 /// defining domains with a generator and a grammar for controlling
0005 /// operator overloading.
0006 //
0007 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0008 //  Software License, Version 1.0. (See accompanying file
0009 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #ifndef BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
0012 #define BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
0013 
0014 #include <boost/ref.hpp>
0015 #include <boost/type_traits/is_same.hpp>
0016 #include <boost/proto/proto_fwd.hpp>
0017 #include <boost/proto/generate.hpp>
0018 #include <boost/proto/detail/as_expr.hpp>
0019 #include <boost/proto/detail/deduce_domain.hpp>
0020 
0021 #if defined(_MSC_VER)
0022 # pragma warning(push)
0023 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
0024 #endif
0025 
0026 namespace boost { namespace proto
0027 {
0028 
0029     namespace detail
0030     {
0031         struct not_a_generator
0032         {};
0033 
0034         struct not_a_grammar
0035         {};
0036 
0037         struct not_a_domain
0038         {};
0039     }
0040 
0041     namespace domainns_
0042     {
0043         /// \brief For use in defining domain tags to be used
0044         /// with \c proto::extends\<\>. A \e Domain associates
0045         /// an expression type with a \e Generator, and optionally
0046         /// a \e Grammar.
0047         ///
0048         /// The Generator determines how new expressions in the
0049         /// domain are constructed. Typically, a generator wraps
0050         /// all new expressions in a wrapper that imparts
0051         /// domain-specific behaviors to expressions within its
0052         /// domain. (See \c proto::extends\<\>.)
0053         ///
0054         /// The Grammar determines whether a given expression is
0055         /// valid within the domain, and automatically disables
0056         /// any operator overloads which would cause an invalid
0057         /// expression to be created. By default, the Grammar
0058         /// parameter defaults to the wildcard, \c proto::_, which
0059         /// makes all expressions valid within the domain.
0060         ///
0061         /// The Super declares the domain currently being defined
0062         /// to be a sub-domain of Super. Expressions in sub-domains
0063         /// can be freely combined with expressions in its super-
0064         /// domain (and <I>its</I> super-domain, etc.).
0065         ///
0066         /// Example:
0067         /// \code
0068         /// template<typename Expr>
0069         /// struct MyExpr;
0070         ///
0071         /// struct MyGrammar
0072         ///   : or_< terminal<_>, plus<MyGrammar, MyGrammar> >
0073         /// {};
0074         ///
0075         /// // Define MyDomain, in which all expressions are
0076         /// // wrapped in MyExpr<> and only expressions that
0077         /// // conform to MyGrammar are allowed.
0078         /// struct MyDomain
0079         ///   : domain<generator<MyExpr>, MyGrammar>
0080         /// {};
0081         ///
0082         /// // Use MyDomain to define MyExpr
0083         /// template<typename Expr>
0084         /// struct MyExpr
0085         ///   : extends<Expr, MyExpr<Expr>, MyDomain>
0086         /// {
0087         ///     // ...
0088         /// };
0089         /// \endcode
0090         ///
0091         template<
0092             typename Generator // = default_generator
0093           , typename Grammar   // = proto::_
0094           , typename Super     // = no_super_domain
0095         >
0096         struct domain
0097           : Generator
0098         {
0099             typedef Generator proto_generator;
0100             typedef Grammar   proto_grammar;
0101             typedef Super     proto_super_domain;
0102             typedef domain    proto_base_domain;
0103 
0104             /// INTERNAL ONLY
0105             typedef void proto_is_domain_;
0106 
0107             /// \brief A unary MonomorphicFunctionObject that turns objects into Proto
0108             /// expression objects in this domain.
0109             ///
0110             /// The <tt>as_expr\<\></tt> function object turns objects into Proto expressions, if
0111             /// they are not already, by making them Proto terminals held by value if
0112             /// possible. Objects that are already Proto expressions are left alone.
0113             ///
0114             /// If <tt>wants_basic_expr\<Generator\>::value</tt> is true, then let \c E be \c basic_expr;
0115             /// otherwise, let \t E be \c expr. Given an lvalue \c t of type \c T:
0116             ///
0117             /// If \c T is not a Proto expression type the resulting terminal is
0118             /// calculated as follows:
0119             ///
0120             ///   If \c T is a function type, an abstract type, or a type derived from
0121             ///   \c std::ios_base, let \c A be <tt>T &</tt>.
0122             ///   Otherwise, let \c A be the type \c T stripped of cv-qualifiers.
0123             ///   Then, the result of applying <tt>as_expr\<T\>()(t)</tt> is
0124             ///   <tt>Generator()(E\<tag::terminal, term\<A\> \>::make(t))</tt>.
0125             ///
0126             /// If \c T is a Proto expression type and its generator type is different from
0127             /// \c Generator, the result is <tt>Generator()(t)</tt>.
0128             ///
0129             /// Otherwise, the result is \c t converted to an (un-const) rvalue.
0130             ///
0131             template<typename T, typename IsExpr = void, typename Callable = proto::callable>
0132             struct as_expr
0133               : detail::as_expr<
0134                     T
0135                   , typename detail::base_generator<Generator>::type
0136                   , wants_basic_expr<Generator>::value
0137                 >
0138             {
0139                 BOOST_PROTO_CALLABLE()
0140             };
0141 
0142             /// INTERNAL ONLY
0143             ///
0144             template<typename T>
0145             struct as_expr<T, typename T::proto_is_expr_, proto::callable>
0146             {
0147                 BOOST_PROTO_CALLABLE()
0148                 typedef typename remove_const<T>::type result_type;
0149 
0150                 BOOST_FORCEINLINE
0151                 result_type operator()(T &e) const
0152                 {
0153                     return e;
0154                 }
0155             };
0156 
0157             /// \brief A unary MonomorphicFunctionObject that turns objects into Proto
0158             /// expression objects in this domain.
0159             ///
0160             /// The <tt>as_child\<\></tt> function object turns objects into Proto expressions, if
0161             /// they are not already, by making them Proto terminals held by reference.
0162             /// Objects that are already Proto expressions are simply returned by reference.
0163             ///
0164             /// If <tt>wants_basic_expr\<Generator\>::value</tt> is true, then let \c E be \c basic_expr;
0165             /// otherwise, let \t E be \c expr. Given an lvalue \c t of type \c T:
0166             ///
0167             /// If \c T is not a Proto expression type the resulting terminal is
0168             /// <tt>Generator()(E\<tag::terminal, term\<T &\> \>::make(t))</tt>.
0169             ///
0170             /// If \c T is a Proto expression type and its generator type is different from
0171             /// \c Generator, the result is <tt>Generator()(t)</tt>.
0172             ///
0173             /// Otherwise, the result is the lvalue \c t.
0174             ///
0175             template<typename T, typename IsExpr = void, typename Callable = proto::callable>
0176             struct as_child
0177               : detail::as_child<
0178                     T
0179                   , typename detail::base_generator<Generator>::type
0180                   , wants_basic_expr<Generator>::value
0181                 >
0182             {
0183                 BOOST_PROTO_CALLABLE()
0184             };
0185 
0186             /// INTERNAL ONLY
0187             ///
0188             template<typename T>
0189             struct as_child<T, typename T::proto_is_expr_, proto::callable>
0190             {
0191                 BOOST_PROTO_CALLABLE()
0192                 typedef T &result_type;
0193 
0194                 BOOST_FORCEINLINE
0195                 result_type operator()(T &e) const
0196                 {
0197                     return e;
0198                 }
0199             };
0200         };
0201 
0202         /// \brief The domain expressions have by default, if
0203         /// \c proto::extends\<\> has not been used to associate
0204         /// a domain with an expression.
0205         ///
0206         struct default_domain
0207           : domain<>
0208         {};
0209 
0210         /// \brief A domain to use when you prefer the use of
0211         /// \c proto::basic_expr\<\> over \c proto::expr\<\>.
0212         ///
0213         struct basic_default_domain
0214           : domain<basic_default_generator>
0215         {};
0216 
0217         /// \brief A pseudo-domain for use in functions and
0218         /// metafunctions that require a domain parameter. It
0219         /// indicates that the domain of the parent node should
0220         /// be inferred from the domains of the child nodes.
0221         ///
0222         /// \attention \c deduce_domain is not itself a valid domain.
0223         ///
0224         struct deduce_domain
0225           : domain<detail::not_a_generator, detail::not_a_grammar, detail::not_a_domain>
0226         {};
0227 
0228         /// \brief Given a domain, a tag type and an argument list,
0229         /// compute the type of the expression to generate. This is
0230         /// either an instance of \c proto::expr\<\> or
0231         /// \c proto::basic_expr\<\>.
0232         ///
0233         template<typename Domain, typename Tag, typename Args, bool WantsBasicExpr>
0234         struct base_expr
0235         {
0236             typedef proto::expr<Tag, Args, Args::arity> type;
0237         };
0238 
0239         /// INTERNAL ONLY
0240         ///
0241         template<typename Domain, typename Tag, typename Args>
0242         struct base_expr<Domain, Tag, Args, true>
0243         {
0244             typedef proto::basic_expr<Tag, Args, Args::arity> type;
0245         };
0246 
0247     }
0248 
0249     /// A metafunction that returns \c mpl::true_
0250     /// if the type \c T is the type of a Proto domain;
0251     /// \c mpl::false_ otherwise. If \c T inherits from
0252     /// \c proto::domain\<\>, \c is_domain\<T\> is
0253     /// \c mpl::true_.
0254     template<typename T, typename Void  /* = void*/>
0255     struct is_domain
0256       : mpl::false_
0257     {};
0258 
0259     /// INTERNAL ONLY
0260     ///
0261     template<typename T>
0262     struct is_domain<T, typename T::proto_is_domain_>
0263       : mpl::true_
0264     {};
0265 
0266     /// A metafunction that returns the domain of
0267     /// a given type. If \c T is a Proto expression
0268     /// type, it returns that expression's associated
0269     /// domain. If not, it returns
0270     /// \c proto::default_domain.
0271     template<typename T, typename Void /* = void*/>
0272     struct domain_of
0273     {
0274         typedef default_domain type;
0275     };
0276 
0277     /// INTERNAL ONLY
0278     ///
0279     template<typename T>
0280     struct domain_of<T, typename T::proto_is_expr_>
0281     {
0282         typedef typename T::proto_domain type;
0283     };
0284 
0285     /// INTERNAL ONLY
0286     ///
0287     template<typename T>
0288     struct domain_of<T &, void>
0289     {
0290         typedef typename domain_of<T>::type type;
0291     };
0292 
0293     /// INTERNAL ONLY
0294     ///
0295     template<typename T>
0296     struct domain_of<boost::reference_wrapper<T>, void>
0297     {
0298         typedef typename domain_of<T>::type type;
0299     };
0300 
0301     /// INTERNAL ONLY
0302     ///
0303     template<typename T>
0304     struct domain_of<boost::reference_wrapper<T> const, void>
0305     {
0306         typedef typename domain_of<T>::type type;
0307     };
0308 
0309     /// A metafunction that returns \c mpl::true_
0310     /// if the type \c SubDomain is a sub-domain of
0311     /// \c SuperDomain; \c mpl::false_ otherwise.
0312     template<typename SubDomain, typename SuperDomain>
0313     struct is_sub_domain_of
0314       : is_sub_domain_of<typename SubDomain::proto_super_domain, SuperDomain>
0315     {};
0316 
0317     /// INTERNAL ONLY
0318     ///
0319     template<typename SuperDomain>
0320     struct is_sub_domain_of<proto::no_super_domain, SuperDomain>
0321       : mpl::false_
0322     {};
0323 
0324     /// INTERNAL ONLY
0325     ///
0326     template<typename SuperDomain>
0327     struct is_sub_domain_of<SuperDomain, SuperDomain>
0328       : mpl::true_
0329     {};
0330 
0331 }}
0332 
0333 #if defined(_MSC_VER)
0334 # pragma warning(pop)
0335 #endif
0336 
0337 #endif