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/xpressive/proto/detail/prefix.hpp>
15 #include <boost/ref.hpp>
16 #include <boost/mpl/bool.hpp>
17 #include <boost/xpressive/proto/proto_fwd.hpp>
18 #include <boost/xpressive/proto/generate.hpp>
19 #include <boost/xpressive/proto/detail/suffix.hpp>
20 
21 namespace boost { namespace proto
22 {
23 
24     namespace detail
25     {
26         struct not_a_generator
27         {};
28 
29         struct not_a_grammar
30         {};
31     }
32 
33     namespace domainns_
34     {
35         /// \brief For use in defining domain tags to be used
36         /// with \c proto::extends\<\>. A \e Domain associates
37         /// an expression type with a \e Generator, and optionally
38         /// a \e Grammar.
39         ///
40         /// The Generator determines how new expressions in the
41         /// domain are constructed. Typically, a generator wraps
42         /// all new expressions in a wrapper that imparts
43         /// domain-specific behaviors to expressions within its
44         /// domain. (See \c proto::extends\<\>.)
45         ///
46         /// The Grammar determines whether a given expression is
47         /// valid within the domain, and automatically disables
48         /// any operator overloads which would cause an invalid
49         /// expression to be created. By default, the Grammar
50         /// parameter defaults to the wildcard, \c proto::_, which
51         /// makes all expressions valid within the domain.
52         ///
53         /// Example:
54         /// \code
55         /// template<typename Expr>
56         /// struct MyExpr;
57         ///
58         /// struct MyGrammar
59         ///   : or_< terminal<_>, plus<MyGrammar, MyGrammar> >
60         /// {};
61         ///
62         /// // Define MyDomain, in which all expressions are
63         /// // wrapped in MyExpr<> and only expressions that
64         /// // conform to MyGrammar are allowed.
65         /// struct MyDomain
66         ///   : domain<generator<MyExpr>, MyGrammar>
67         /// {};
68         ///
69         /// // Use MyDomain to define MyExpr
70         /// template<typename Expr>
71         /// struct MyExpr
72         ///   : extends<Expr, MyExpr<Expr>, MyDomain>
73         /// {
74         ///     // ...
75         /// };
76         /// \endcode
77         ///
78         template<
79             typename Generator BOOST_PROTO_FOR_DOXYGEN_ONLY(= default_generator)
80           , typename Grammar   BOOST_PROTO_FOR_DOXYGEN_ONLY(= proto::_)
81         >
82         struct domain
83           : Generator
84         {
85             typedef Grammar proto_grammar;
86             typedef void proto_is_domain_;
87         };
88 
89         /// \brief The domain expressions have by default, if
90         /// \c proto::extends\<\> has not been used to associate
91         /// a domain with an expression.
92         ///
93         struct default_domain
94           : domain<>
95         {};
96 
97         /// \brief A pseudo-domain for use in functions and
98         /// metafunctions that require a domain parameter. It
99         /// indicates that the domain of the parent node should
100         /// be inferred from the domains of the children nodes.
101         ///
102         /// \attention \c deduce_domain is not itself a valid domain.
103         ///
104         struct deduce_domain
105           : domain<detail::not_a_generator, detail::not_a_grammar>
106         {};
107     }
108 
109     namespace result_of
110     {
111         /// A metafunction that returns \c mpl::true_
112         /// if the type \c T is the type of a Proto domain;
113         /// \c mpl::false_ otherwise. If \c T inherits from
114         /// \c proto::domain\<\>, \c is_domain\<T\> is
115         /// \c mpl::true_.
116         template<typename T, typename Void  BOOST_PROTO_FOR_DOXYGEN_ONLY(= void)>
117         struct is_domain
118           : mpl::false_
119         {};
120 
121         /// INTERNAL ONLY
122         ///
123         template<typename T>
124         struct is_domain<T, typename T::proto_is_domain_>
125           : mpl::true_
126         {};
127 
128         /// A metafunction that returns the domain of
129         /// a given type. If \c T is a Proto expression
130         /// type, it returns that expression's associated
131         /// domain. If not, it returns
132         /// \c proto::default_domain.
133         template<typename T, typename Void  BOOST_PROTO_FOR_DOXYGEN_ONLY(= void)>
134         struct domain_of
135         {
136             typedef default_domain type;
137         };
138 
139         /// INTERNAL ONLY
140         ///
141         template<typename T>
142         struct domain_of<T, typename T::proto_is_expr_>
143         {
144             typedef typename T::proto_domain type;
145         };
146 
147         /// INTERNAL ONLY
148         ///
149         template<typename T>
150         struct domain_of<T &, void>
151         {
152             typedef typename domain_of<T>::type type;
153         };
154 
155         /// INTERNAL ONLY
156         ///
157         template<typename T>
158         struct domain_of<boost::reference_wrapper<T>, void>
159         {
160             typedef typename domain_of<T>::type type;
161         };
162 
163         /// INTERNAL ONLY
164         ///
165         template<typename T>
166         struct domain_of<boost::reference_wrapper<T> const, void>
167         {
168             typedef typename domain_of<T>::type type;
169         };
170     }
171 }}
172 
173 #endif
174