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