PageRenderTime 60ms CodeModel.GetById 39ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://hadesmem.googlecode.com/
C++ Header | 326 lines | 142 code | 32 blank | 152 comment | 0 complexity | cdfb4fd1cf094d8c364275766bbcd6c9 MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////////
  2/// \file domain.hpp
  3/// Contains definition of domain\<\> class template and helpers for
  4/// defining domains with a generator and a grammar for controlling
  5/// operator overloading.
  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_DOMAIN_HPP_EAN_02_13_2007
 12#define BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
 13
 14#include <boost/ref.hpp>
 15#include <boost/type_traits/is_same.hpp>
 16#include <boost/proto/proto_fwd.hpp>
 17#include <boost/proto/generate.hpp>
 18#include <boost/proto/detail/as_expr.hpp>
 19#include <boost/proto/detail/deduce_domain.hpp>
 20
 21namespace boost { namespace proto
 22{
 23
 24    namespace detail
 25    {
 26        struct not_a_generator
 27        {};
 28
 29        struct not_a_grammar
 30        {};
 31
 32        struct not_a_domain
 33        {};
 34    }
 35
 36    namespace domainns_
 37    {
 38        /// \brief For use in defining domain tags to be used
 39        /// with \c proto::extends\<\>. A \e Domain associates
 40        /// an expression type with a \e Generator, and optionally
 41        /// a \e Grammar.
 42        ///
 43        /// The Generator determines how new expressions in the
 44        /// domain are constructed. Typically, a generator wraps
 45        /// all new expressions in a wrapper that imparts
 46        /// domain-specific behaviors to expressions within its
 47        /// domain. (See \c proto::extends\<\>.)
 48        ///
 49        /// The Grammar determines whether a given expression is
 50        /// valid within the domain, and automatically disables
 51        /// any operator overloads which would cause an invalid
 52        /// expression to be created. By default, the Grammar
 53        /// parameter defaults to the wildcard, \c proto::_, which
 54        /// makes all expressions valid within the domain.
 55        ///
 56        /// The Super declares the domain currently being defined
 57        /// to be a sub-domain of Super. Expressions in sub-domains
 58        /// can be freely combined with expressions in its super-
 59        /// domain (and <I>its</I> super-domain, etc.).
 60        ///
 61        /// Example:
 62        /// \code
 63        /// template<typename Expr>
 64        /// struct MyExpr;
 65        ///
 66        /// struct MyGrammar
 67        ///   : or_< terminal<_>, plus<MyGrammar, MyGrammar> >
 68        /// {};
 69        ///
 70        /// // Define MyDomain, in which all expressions are
 71        /// // wrapped in MyExpr<> and only expressions that
 72        /// // conform to MyGrammar are allowed.
 73        /// struct MyDomain
 74        ///   : domain<generator<MyExpr>, MyGrammar>
 75        /// {};
 76        ///
 77        /// // Use MyDomain to define MyExpr
 78        /// template<typename Expr>
 79        /// struct MyExpr
 80        ///   : extends<Expr, MyExpr<Expr>, MyDomain>
 81        /// {
 82        ///     // ...
 83        /// };
 84        /// \endcode
 85        ///
 86        template<
 87            typename Generator // = default_generator
 88          , typename Grammar   // = proto::_
 89          , typename Super     // = no_super_domain
 90        >
 91        struct domain
 92          : Generator
 93        {
 94            typedef Generator proto_generator;
 95            typedef Grammar   proto_grammar;
 96            typedef Super     proto_super_domain;
 97            typedef domain    proto_base_domain;
 98
 99            /// INTERNAL ONLY
100            typedef void proto_is_domain_;
101
102            /// \brief A unary MonomorphicFunctionObject that turns objects into Proto
103            /// expression objects in this domain.
104            ///
105            /// The <tt>as_expr\<\></tt> function object turns objects into Proto expressions, if
106            /// they are not already, by making them Proto terminals held by value if
107            /// possible. Objects that are already Proto expressions are left alone.
108            ///
109            /// If <tt>wants_basic_expr\<Generator\>::value</tt> is true, then let \c E be \c basic_expr;
110            /// otherwise, let \t E be \c expr. Given an lvalue \c t of type \c T:
111            ///
112            /// If \c T is not a Proto expression type the resulting terminal is
113            /// calculated as follows:
114            ///
115            ///   If \c T is a function type, an abstract type, or a type derived from
116            ///   \c std::ios_base, let \c A be <tt>T &</tt>.
117            ///   Otherwise, let \c A be the type \c T stripped of cv-qualifiers.
118            ///   Then, the result of applying <tt>as_expr\<T\>()(t)</tt> is
119            ///   <tt>Generator()(E\<tag::terminal, term\<A\> \>::make(t))</tt>.
120            ///
121            /// If \c T is a Proto expression type and its generator type is different from
122            /// \c Generator, the result is <tt>Generator()(t)</tt>.
123            ///
124            /// Otherwise, the result is \c t converted to an (un-const) rvalue.
125            ///
126            template<typename T, typename IsExpr = void, typename Callable = proto::callable>
127            struct as_expr
128              : detail::as_expr<
129                    T
130                  , typename detail::base_generator<Generator>::type
131                  , wants_basic_expr<Generator>::value
132                >
133            {
134                BOOST_PROTO_CALLABLE()
135            };
136
137            /// INTERNAL ONLY
138            ///
139            template<typename T>
140            struct as_expr<T, typename T::proto_is_expr_, proto::callable>
141            {
142                BOOST_PROTO_CALLABLE()
143                typedef typename remove_const<T>::type result_type;
144
145                result_type operator()(T &e) const
146                {
147                    return e;
148                }
149            };
150
151            /// \brief A unary MonomorphicFunctionObject that turns objects into Proto
152            /// expression objects in this domain.
153            ///
154            /// The <tt>as_child\<\></tt> function object turns objects into Proto expressions, if
155            /// they are not already, by making them Proto terminals held by reference.
156            /// Objects that are already Proto expressions are simply returned by reference.
157            ///
158            /// If <tt>wants_basic_expr\<Generator\>::value</tt> is true, then let \c E be \c basic_expr;
159            /// otherwise, let \t E be \c expr. Given an lvalue \c t of type \c T:
160            ///
161            /// If \c T is not a Proto expression type the resulting terminal is
162            /// <tt>Generator()(E\<tag::terminal, term\<T &\> \>::make(t))</tt>.
163            ///
164            /// If \c T is a Proto expression type and its generator type is different from
165            /// \c Generator, the result is <tt>Generator()(t)</tt>.
166            ///
167            /// Otherwise, the result is the lvalue \c t.
168            ///
169            template<typename T, typename IsExpr = void, typename Callable = proto::callable>
170            struct as_child
171              : detail::as_child<
172                    T
173                  , typename detail::base_generator<Generator>::type
174                  , wants_basic_expr<Generator>::value
175                >
176            {
177                BOOST_PROTO_CALLABLE()
178            };
179
180            /// INTERNAL ONLY
181            ///
182            template<typename T>
183            struct as_child<T, typename T::proto_is_expr_, proto::callable>
184            {
185                BOOST_PROTO_CALLABLE()
186                typedef T &result_type;
187
188                result_type operator()(T &e) const
189                {
190                    return e;
191                }
192            };
193        };
194
195        /// \brief The domain expressions have by default, if
196        /// \c proto::extends\<\> has not been used to associate
197        /// a domain with an expression.
198        ///
199        struct default_domain
200          : domain<>
201        {};
202
203        /// \brief A domain to use when you prefer the use of
204        /// \c proto::basic_expr\<\> over \c proto::expr\<\>.
205        ///
206        struct basic_default_domain
207          : domain<basic_default_generator>
208        {};
209
210        /// \brief A pseudo-domain for use in functions and
211        /// metafunctions that require a domain parameter. It
212        /// indicates that the domain of the parent node should
213        /// be inferred from the domains of the child nodes.
214        ///
215        /// \attention \c deduce_domain is not itself a valid domain.
216        ///
217        struct deduce_domain
218          : domain<detail::not_a_generator, detail::not_a_grammar, detail::not_a_domain>
219        {};
220
221        /// \brief Given a domain, a tag type and an argument list,
222        /// compute the type of the expression to generate. This is
223        /// either an instance of \c proto::expr\<\> or
224        /// \c proto::basic_expr\<\>.
225        ///
226        template<typename Domain, typename Tag, typename Args, bool WantsBasicExpr>
227        struct base_expr
228        {
229            typedef proto::expr<Tag, Args, Args::arity> type;
230        };
231
232        /// INTERNAL ONLY
233        ///
234        template<typename Domain, typename Tag, typename Args>
235        struct base_expr<Domain, Tag, Args, true>
236        {
237            typedef proto::basic_expr<Tag, Args, Args::arity> type;
238        };
239
240    }
241
242    /// A metafunction that returns \c mpl::true_
243    /// if the type \c T is the type of a Proto domain;
244    /// \c mpl::false_ otherwise. If \c T inherits from
245    /// \c proto::domain\<\>, \c is_domain\<T\> is
246    /// \c mpl::true_.
247    template<typename T, typename Void  /* = void*/>
248    struct is_domain
249      : mpl::false_
250    {};
251
252    /// INTERNAL ONLY
253    ///
254    template<typename T>
255    struct is_domain<T, typename T::proto_is_domain_>
256      : mpl::true_
257    {};
258
259    /// A metafunction that returns the domain of
260    /// a given type. If \c T is a Proto expression
261    /// type, it returns that expression's associated
262    /// domain. If not, it returns
263    /// \c proto::default_domain.
264    template<typename T, typename Void /* = void*/>
265    struct domain_of
266    {
267        typedef default_domain type;
268    };
269
270    /// INTERNAL ONLY
271    ///
272    template<typename T>
273    struct domain_of<T, typename T::proto_is_expr_>
274    {
275        typedef typename T::proto_domain type;
276    };
277
278    /// INTERNAL ONLY
279    ///
280    template<typename T>
281    struct domain_of<T &, void>
282    {
283        typedef typename domain_of<T>::type type;
284    };
285
286    /// INTERNAL ONLY
287    ///
288    template<typename T>
289    struct domain_of<boost::reference_wrapper<T>, void>
290    {
291        typedef typename domain_of<T>::type type;
292    };
293
294    /// INTERNAL ONLY
295    ///
296    template<typename T>
297    struct domain_of<boost::reference_wrapper<T> const, void>
298    {
299        typedef typename domain_of<T>::type type;
300    };
301
302    /// A metafunction that returns \c mpl::true_
303    /// if the type \c SubDomain is a sub-domain of
304    /// \c SuperDomain; \c mpl::false_ otherwise.
305    template<typename SubDomain, typename SuperDomain>
306    struct is_sub_domain_of
307      : is_sub_domain_of<typename SubDomain::proto_super_domain, SuperDomain>
308    {};
309
310    /// INTERNAL ONLY
311    ///
312    template<typename SuperDomain>
313    struct is_sub_domain_of<proto::no_super_domain, SuperDomain>
314      : mpl::false_
315    {};
316
317    /// INTERNAL ONLY
318    ///
319    template<typename SuperDomain>
320    struct is_sub_domain_of<SuperDomain, SuperDomain>
321      : mpl::true_
322    {};
323
324}}
325
326#endif