]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/proto/include/boost/proto/domain.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / proto / include / boost / proto / domain.hpp
CommitLineData
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
26namespace 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