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