123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- ///////////////////////////////////////////////////////////////////////////////
- /// \file domain.hpp
- /// Contains definition of domain\<\> class template and helpers for
- /// defining domains with a generator and a grammar for controlling
- /// operator overloading.
- //
- // Copyright 2008 Eric Niebler. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
- #define BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
- #include <boost/ref.hpp>
- #include <boost/type_traits/is_same.hpp>
- #include <boost/proto/proto_fwd.hpp>
- #include <boost/proto/generate.hpp>
- #include <boost/proto/detail/as_expr.hpp>
- #include <boost/proto/detail/deduce_domain.hpp>
- #if defined(_MSC_VER)
- # pragma warning(push)
- # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
- #endif
- namespace boost { namespace proto
- {
- namespace detail
- {
- struct not_a_generator
- {};
- struct not_a_grammar
- {};
- struct not_a_domain
- {};
- }
- namespace domainns_
- {
- /// \brief For use in defining domain tags to be used
- /// with \c proto::extends\<\>. A \e Domain associates
- /// an expression type with a \e Generator, and optionally
- /// a \e Grammar.
- ///
- /// The Generator determines how new expressions in the
- /// domain are constructed. Typically, a generator wraps
- /// all new expressions in a wrapper that imparts
- /// domain-specific behaviors to expressions within its
- /// domain. (See \c proto::extends\<\>.)
- ///
- /// The Grammar determines whether a given expression is
- /// valid within the domain, and automatically disables
- /// any operator overloads which would cause an invalid
- /// expression to be created. By default, the Grammar
- /// parameter defaults to the wildcard, \c proto::_, which
- /// makes all expressions valid within the domain.
- ///
- /// The Super declares the domain currently being defined
- /// to be a sub-domain of Super. Expressions in sub-domains
- /// can be freely combined with expressions in its super-
- /// domain (and <I>its</I> super-domain, etc.).
- ///
- /// Example:
- /// \code
- /// template<typename Expr>
- /// struct MyExpr;
- ///
- /// struct MyGrammar
- /// : or_< terminal<_>, plus<MyGrammar, MyGrammar> >
- /// {};
- ///
- /// // Define MyDomain, in which all expressions are
- /// // wrapped in MyExpr<> and only expressions that
- /// // conform to MyGrammar are allowed.
- /// struct MyDomain
- /// : domain<generator<MyExpr>, MyGrammar>
- /// {};
- ///
- /// // Use MyDomain to define MyExpr
- /// template<typename Expr>
- /// struct MyExpr
- /// : extends<Expr, MyExpr<Expr>, MyDomain>
- /// {
- /// // ...
- /// };
- /// \endcode
- ///
- template<
- typename Generator // = default_generator
- , typename Grammar // = proto::_
- , typename Super // = no_super_domain
- >
- struct domain
- : Generator
- {
- typedef Generator proto_generator;
- typedef Grammar proto_grammar;
- typedef Super proto_super_domain;
- typedef domain proto_base_domain;
- /// INTERNAL ONLY
- typedef void proto_is_domain_;
- /// \brief A unary MonomorphicFunctionObject that turns objects into Proto
- /// expression objects in this domain.
- ///
- /// The <tt>as_expr\<\></tt> function object turns objects into Proto expressions, if
- /// they are not already, by making them Proto terminals held by value if
- /// possible. Objects that are already Proto expressions are left alone.
- ///
- /// If <tt>wants_basic_expr\<Generator\>::value</tt> is true, then let \c E be \c basic_expr;
- /// otherwise, let \t E be \c expr. Given an lvalue \c t of type \c T:
- ///
- /// If \c T is not a Proto expression type the resulting terminal is
- /// calculated as follows:
- ///
- /// If \c T is a function type, an abstract type, or a type derived from
- /// \c std::ios_base, let \c A be <tt>T &</tt>.
- /// Otherwise, let \c A be the type \c T stripped of cv-qualifiers.
- /// Then, the result of applying <tt>as_expr\<T\>()(t)</tt> is
- /// <tt>Generator()(E\<tag::terminal, term\<A\> \>::make(t))</tt>.
- ///
- /// If \c T is a Proto expression type and its generator type is different from
- /// \c Generator, the result is <tt>Generator()(t)</tt>.
- ///
- /// Otherwise, the result is \c t converted to an (un-const) rvalue.
- ///
- template<typename T, typename IsExpr = void, typename Callable = proto::callable>
- struct as_expr
- : detail::as_expr<
- T
- , typename detail::base_generator<Generator>::type
- , wants_basic_expr<Generator>::value
- >
- {
- BOOST_PROTO_CALLABLE()
- };
- /// INTERNAL ONLY
- ///
- template<typename T>
- struct as_expr<T, typename T::proto_is_expr_, proto::callable>
- {
- BOOST_PROTO_CALLABLE()
- typedef typename remove_const<T>::type result_type;
- BOOST_FORCEINLINE
- result_type operator()(T &e) const
- {
- return e;
- }
- };
- /// \brief A unary MonomorphicFunctionObject that turns objects into Proto
- /// expression objects in this domain.
- ///
- /// The <tt>as_child\<\></tt> function object turns objects into Proto expressions, if
- /// they are not already, by making them Proto terminals held by reference.
- /// Objects that are already Proto expressions are simply returned by reference.
- ///
- /// If <tt>wants_basic_expr\<Generator\>::value</tt> is true, then let \c E be \c basic_expr;
- /// otherwise, let \t E be \c expr. Given an lvalue \c t of type \c T:
- ///
- /// If \c T is not a Proto expression type the resulting terminal is
- /// <tt>Generator()(E\<tag::terminal, term\<T &\> \>::make(t))</tt>.
- ///
- /// If \c T is a Proto expression type and its generator type is different from
- /// \c Generator, the result is <tt>Generator()(t)</tt>.
- ///
- /// Otherwise, the result is the lvalue \c t.
- ///
- template<typename T, typename IsExpr = void, typename Callable = proto::callable>
- struct as_child
- : detail::as_child<
- T
- , typename detail::base_generator<Generator>::type
- , wants_basic_expr<Generator>::value
- >
- {
- BOOST_PROTO_CALLABLE()
- };
- /// INTERNAL ONLY
- ///
- template<typename T>
- struct as_child<T, typename T::proto_is_expr_, proto::callable>
- {
- BOOST_PROTO_CALLABLE()
- typedef T &result_type;
- BOOST_FORCEINLINE
- result_type operator()(T &e) const
- {
- return e;
- }
- };
- };
- /// \brief The domain expressions have by default, if
- /// \c proto::extends\<\> has not been used to associate
- /// a domain with an expression.
- ///
- struct default_domain
- : domain<>
- {};
- /// \brief A domain to use when you prefer the use of
- /// \c proto::basic_expr\<\> over \c proto::expr\<\>.
- ///
- struct basic_default_domain
- : domain<basic_default_generator>
- {};
- /// \brief A pseudo-domain for use in functions and
- /// metafunctions that require a domain parameter. It
- /// indicates that the domain of the parent node should
- /// be inferred from the domains of the child nodes.
- ///
- /// \attention \c deduce_domain is not itself a valid domain.
- ///
- struct deduce_domain
- : domain<detail::not_a_generator, detail::not_a_grammar, detail::not_a_domain>
- {};
- /// \brief Given a domain, a tag type and an argument list,
- /// compute the type of the expression to generate. This is
- /// either an instance of \c proto::expr\<\> or
- /// \c proto::basic_expr\<\>.
- ///
- template<typename Domain, typename Tag, typename Args, bool WantsBasicExpr>
- struct base_expr
- {
- typedef proto::expr<Tag, Args, Args::arity> type;
- };
- /// INTERNAL ONLY
- ///
- template<typename Domain, typename Tag, typename Args>
- struct base_expr<Domain, Tag, Args, true>
- {
- typedef proto::basic_expr<Tag, Args, Args::arity> type;
- };
- }
- /// A metafunction that returns \c mpl::true_
- /// if the type \c T is the type of a Proto domain;
- /// \c mpl::false_ otherwise. If \c T inherits from
- /// \c proto::domain\<\>, \c is_domain\<T\> is
- /// \c mpl::true_.
- template<typename T, typename Void /* = void*/>
- struct is_domain
- : mpl::false_
- {};
- /// INTERNAL ONLY
- ///
- template<typename T>
- struct is_domain<T, typename T::proto_is_domain_>
- : mpl::true_
- {};
- /// A metafunction that returns the domain of
- /// a given type. If \c T is a Proto expression
- /// type, it returns that expression's associated
- /// domain. If not, it returns
- /// \c proto::default_domain.
- template<typename T, typename Void /* = void*/>
- struct domain_of
- {
- typedef default_domain type;
- };
- /// INTERNAL ONLY
- ///
- template<typename T>
- struct domain_of<T, typename T::proto_is_expr_>
- {
- typedef typename T::proto_domain type;
- };
- /// INTERNAL ONLY
- ///
- template<typename T>
- struct domain_of<T &, void>
- {
- typedef typename domain_of<T>::type type;
- };
- /// INTERNAL ONLY
- ///
- template<typename T>
- struct domain_of<boost::reference_wrapper<T>, void>
- {
- typedef typename domain_of<T>::type type;
- };
- /// INTERNAL ONLY
- ///
- template<typename T>
- struct domain_of<boost::reference_wrapper<T> const, void>
- {
- typedef typename domain_of<T>::type type;
- };
- /// A metafunction that returns \c mpl::true_
- /// if the type \c SubDomain is a sub-domain of
- /// \c SuperDomain; \c mpl::false_ otherwise.
- template<typename SubDomain, typename SuperDomain>
- struct is_sub_domain_of
- : is_sub_domain_of<typename SubDomain::proto_super_domain, SuperDomain>
- {};
- /// INTERNAL ONLY
- ///
- template<typename SuperDomain>
- struct is_sub_domain_of<proto::no_super_domain, SuperDomain>
- : mpl::false_
- {};
- /// INTERNAL ONLY
- ///
- template<typename SuperDomain>
- struct is_sub_domain_of<SuperDomain, SuperDomain>
- : mpl::true_
- {};
- }}
- #if defined(_MSC_VER)
- # pragma warning(pop)
- #endif
- #endif
|