domain.hpp 11 KB

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