|
||||
File indexing completed on 2025-01-18 09:50:32
0001 /////////////////////////////////////////////////////////////////////////////// 0002 /// \file domain.hpp 0003 /// Contains definition of domain\<\> class template and helpers for 0004 /// defining domains with a generator and a grammar for controlling 0005 /// operator overloading. 0006 // 0007 // Copyright 2008 Eric Niebler. Distributed under the Boost 0008 // Software License, Version 1.0. (See accompanying file 0009 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0010 0011 #ifndef BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007 0012 #define BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007 0013 0014 #include <boost/ref.hpp> 0015 #include <boost/type_traits/is_same.hpp> 0016 #include <boost/proto/proto_fwd.hpp> 0017 #include <boost/proto/generate.hpp> 0018 #include <boost/proto/detail/as_expr.hpp> 0019 #include <boost/proto/detail/deduce_domain.hpp> 0020 0021 #if defined(_MSC_VER) 0022 # pragma warning(push) 0023 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined 0024 #endif 0025 0026 namespace boost { namespace proto 0027 { 0028 0029 namespace detail 0030 { 0031 struct not_a_generator 0032 {}; 0033 0034 struct not_a_grammar 0035 {}; 0036 0037 struct not_a_domain 0038 {}; 0039 } 0040 0041 namespace domainns_ 0042 { 0043 /// \brief For use in defining domain tags to be used 0044 /// with \c proto::extends\<\>. A \e Domain associates 0045 /// an expression type with a \e Generator, and optionally 0046 /// a \e Grammar. 0047 /// 0048 /// The Generator determines how new expressions in the 0049 /// domain are constructed. Typically, a generator wraps 0050 /// all new expressions in a wrapper that imparts 0051 /// domain-specific behaviors to expressions within its 0052 /// domain. (See \c proto::extends\<\>.) 0053 /// 0054 /// The Grammar determines whether a given expression is 0055 /// valid within the domain, and automatically disables 0056 /// any operator overloads which would cause an invalid 0057 /// expression to be created. By default, the Grammar 0058 /// parameter defaults to the wildcard, \c proto::_, which 0059 /// makes all expressions valid within the domain. 0060 /// 0061 /// The Super declares the domain currently being defined 0062 /// to be a sub-domain of Super. Expressions in sub-domains 0063 /// can be freely combined with expressions in its super- 0064 /// domain (and <I>its</I> super-domain, etc.). 0065 /// 0066 /// Example: 0067 /// \code 0068 /// template<typename Expr> 0069 /// struct MyExpr; 0070 /// 0071 /// struct MyGrammar 0072 /// : or_< terminal<_>, plus<MyGrammar, MyGrammar> > 0073 /// {}; 0074 /// 0075 /// // Define MyDomain, in which all expressions are 0076 /// // wrapped in MyExpr<> and only expressions that 0077 /// // conform to MyGrammar are allowed. 0078 /// struct MyDomain 0079 /// : domain<generator<MyExpr>, MyGrammar> 0080 /// {}; 0081 /// 0082 /// // Use MyDomain to define MyExpr 0083 /// template<typename Expr> 0084 /// struct MyExpr 0085 /// : extends<Expr, MyExpr<Expr>, MyDomain> 0086 /// { 0087 /// // ... 0088 /// }; 0089 /// \endcode 0090 /// 0091 template< 0092 typename Generator // = default_generator 0093 , typename Grammar // = proto::_ 0094 , typename Super // = no_super_domain 0095 > 0096 struct domain 0097 : Generator 0098 { 0099 typedef Generator proto_generator; 0100 typedef Grammar proto_grammar; 0101 typedef Super proto_super_domain; 0102 typedef domain proto_base_domain; 0103 0104 /// INTERNAL ONLY 0105 typedef void proto_is_domain_; 0106 0107 /// \brief A unary MonomorphicFunctionObject that turns objects into Proto 0108 /// expression objects in this domain. 0109 /// 0110 /// The <tt>as_expr\<\></tt> function object turns objects into Proto expressions, if 0111 /// they are not already, by making them Proto terminals held by value if 0112 /// possible. Objects that are already Proto expressions are left alone. 0113 /// 0114 /// If <tt>wants_basic_expr\<Generator\>::value</tt> is true, then let \c E be \c basic_expr; 0115 /// otherwise, let \t E be \c expr. Given an lvalue \c t of type \c T: 0116 /// 0117 /// If \c T is not a Proto expression type the resulting terminal is 0118 /// calculated as follows: 0119 /// 0120 /// If \c T is a function type, an abstract type, or a type derived from 0121 /// \c std::ios_base, let \c A be <tt>T &</tt>. 0122 /// Otherwise, let \c A be the type \c T stripped of cv-qualifiers. 0123 /// Then, the result of applying <tt>as_expr\<T\>()(t)</tt> is 0124 /// <tt>Generator()(E\<tag::terminal, term\<A\> \>::make(t))</tt>. 0125 /// 0126 /// If \c T is a Proto expression type and its generator type is different from 0127 /// \c Generator, the result is <tt>Generator()(t)</tt>. 0128 /// 0129 /// Otherwise, the result is \c t converted to an (un-const) rvalue. 0130 /// 0131 template<typename T, typename IsExpr = void, typename Callable = proto::callable> 0132 struct as_expr 0133 : detail::as_expr< 0134 T 0135 , typename detail::base_generator<Generator>::type 0136 , wants_basic_expr<Generator>::value 0137 > 0138 { 0139 BOOST_PROTO_CALLABLE() 0140 }; 0141 0142 /// INTERNAL ONLY 0143 /// 0144 template<typename T> 0145 struct as_expr<T, typename T::proto_is_expr_, proto::callable> 0146 { 0147 BOOST_PROTO_CALLABLE() 0148 typedef typename remove_const<T>::type result_type; 0149 0150 BOOST_FORCEINLINE 0151 result_type operator()(T &e) const 0152 { 0153 return e; 0154 } 0155 }; 0156 0157 /// \brief A unary MonomorphicFunctionObject that turns objects into Proto 0158 /// expression objects in this domain. 0159 /// 0160 /// The <tt>as_child\<\></tt> function object turns objects into Proto expressions, if 0161 /// they are not already, by making them Proto terminals held by reference. 0162 /// Objects that are already Proto expressions are simply returned by reference. 0163 /// 0164 /// If <tt>wants_basic_expr\<Generator\>::value</tt> is true, then let \c E be \c basic_expr; 0165 /// otherwise, let \t E be \c expr. Given an lvalue \c t of type \c T: 0166 /// 0167 /// If \c T is not a Proto expression type the resulting terminal is 0168 /// <tt>Generator()(E\<tag::terminal, term\<T &\> \>::make(t))</tt>. 0169 /// 0170 /// If \c T is a Proto expression type and its generator type is different from 0171 /// \c Generator, the result is <tt>Generator()(t)</tt>. 0172 /// 0173 /// Otherwise, the result is the lvalue \c t. 0174 /// 0175 template<typename T, typename IsExpr = void, typename Callable = proto::callable> 0176 struct as_child 0177 : detail::as_child< 0178 T 0179 , typename detail::base_generator<Generator>::type 0180 , wants_basic_expr<Generator>::value 0181 > 0182 { 0183 BOOST_PROTO_CALLABLE() 0184 }; 0185 0186 /// INTERNAL ONLY 0187 /// 0188 template<typename T> 0189 struct as_child<T, typename T::proto_is_expr_, proto::callable> 0190 { 0191 BOOST_PROTO_CALLABLE() 0192 typedef T &result_type; 0193 0194 BOOST_FORCEINLINE 0195 result_type operator()(T &e) const 0196 { 0197 return e; 0198 } 0199 }; 0200 }; 0201 0202 /// \brief The domain expressions have by default, if 0203 /// \c proto::extends\<\> has not been used to associate 0204 /// a domain with an expression. 0205 /// 0206 struct default_domain 0207 : domain<> 0208 {}; 0209 0210 /// \brief A domain to use when you prefer the use of 0211 /// \c proto::basic_expr\<\> over \c proto::expr\<\>. 0212 /// 0213 struct basic_default_domain 0214 : domain<basic_default_generator> 0215 {}; 0216 0217 /// \brief A pseudo-domain for use in functions and 0218 /// metafunctions that require a domain parameter. It 0219 /// indicates that the domain of the parent node should 0220 /// be inferred from the domains of the child nodes. 0221 /// 0222 /// \attention \c deduce_domain is not itself a valid domain. 0223 /// 0224 struct deduce_domain 0225 : domain<detail::not_a_generator, detail::not_a_grammar, detail::not_a_domain> 0226 {}; 0227 0228 /// \brief Given a domain, a tag type and an argument list, 0229 /// compute the type of the expression to generate. This is 0230 /// either an instance of \c proto::expr\<\> or 0231 /// \c proto::basic_expr\<\>. 0232 /// 0233 template<typename Domain, typename Tag, typename Args, bool WantsBasicExpr> 0234 struct base_expr 0235 { 0236 typedef proto::expr<Tag, Args, Args::arity> type; 0237 }; 0238 0239 /// INTERNAL ONLY 0240 /// 0241 template<typename Domain, typename Tag, typename Args> 0242 struct base_expr<Domain, Tag, Args, true> 0243 { 0244 typedef proto::basic_expr<Tag, Args, Args::arity> type; 0245 }; 0246 0247 } 0248 0249 /// A metafunction that returns \c mpl::true_ 0250 /// if the type \c T is the type of a Proto domain; 0251 /// \c mpl::false_ otherwise. If \c T inherits from 0252 /// \c proto::domain\<\>, \c is_domain\<T\> is 0253 /// \c mpl::true_. 0254 template<typename T, typename Void /* = void*/> 0255 struct is_domain 0256 : mpl::false_ 0257 {}; 0258 0259 /// INTERNAL ONLY 0260 /// 0261 template<typename T> 0262 struct is_domain<T, typename T::proto_is_domain_> 0263 : mpl::true_ 0264 {}; 0265 0266 /// A metafunction that returns the domain of 0267 /// a given type. If \c T is a Proto expression 0268 /// type, it returns that expression's associated 0269 /// domain. If not, it returns 0270 /// \c proto::default_domain. 0271 template<typename T, typename Void /* = void*/> 0272 struct domain_of 0273 { 0274 typedef default_domain type; 0275 }; 0276 0277 /// INTERNAL ONLY 0278 /// 0279 template<typename T> 0280 struct domain_of<T, typename T::proto_is_expr_> 0281 { 0282 typedef typename T::proto_domain type; 0283 }; 0284 0285 /// INTERNAL ONLY 0286 /// 0287 template<typename T> 0288 struct domain_of<T &, void> 0289 { 0290 typedef typename domain_of<T>::type type; 0291 }; 0292 0293 /// INTERNAL ONLY 0294 /// 0295 template<typename T> 0296 struct domain_of<boost::reference_wrapper<T>, void> 0297 { 0298 typedef typename domain_of<T>::type type; 0299 }; 0300 0301 /// INTERNAL ONLY 0302 /// 0303 template<typename T> 0304 struct domain_of<boost::reference_wrapper<T> const, void> 0305 { 0306 typedef typename domain_of<T>::type type; 0307 }; 0308 0309 /// A metafunction that returns \c mpl::true_ 0310 /// if the type \c SubDomain is a sub-domain of 0311 /// \c SuperDomain; \c mpl::false_ otherwise. 0312 template<typename SubDomain, typename SuperDomain> 0313 struct is_sub_domain_of 0314 : is_sub_domain_of<typename SubDomain::proto_super_domain, SuperDomain> 0315 {}; 0316 0317 /// INTERNAL ONLY 0318 /// 0319 template<typename SuperDomain> 0320 struct is_sub_domain_of<proto::no_super_domain, SuperDomain> 0321 : mpl::false_ 0322 {}; 0323 0324 /// INTERNAL ONLY 0325 /// 0326 template<typename SuperDomain> 0327 struct is_sub_domain_of<SuperDomain, SuperDomain> 0328 : mpl::true_ 0329 {}; 0330 0331 }} 0332 0333 #if defined(_MSC_VER) 0334 # pragma warning(pop) 0335 #endif 0336 0337 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |