| 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 |
| 338 | |