|
||||
File indexing completed on 2025-01-18 09:50:19
0001 /////////////////////////////////////////////////////////////////////////////// 0002 /// \file callable.hpp 0003 /// Definintion of callable_context\<\>, an evaluation context for 0004 /// proto::eval() that explodes each node and calls the derived context 0005 /// type with the expressions constituents. If the derived context doesn't 0006 /// have an overload that handles this node, fall back to some other 0007 /// context. 0008 // 0009 // Copyright 2008 Eric Niebler. Distributed under the Boost 0010 // Software License, Version 1.0. (See accompanying file 0011 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0012 0013 #ifndef BOOST_PROTO_CONTEXT_CALLABLE_HPP_EAN_06_23_2007 0014 #define BOOST_PROTO_CONTEXT_CALLABLE_HPP_EAN_06_23_2007 0015 0016 #include <boost/config.hpp> 0017 #include <boost/detail/workaround.hpp> 0018 #include <boost/preprocessor/cat.hpp> 0019 #include <boost/preprocessor/iteration/iterate.hpp> 0020 #include <boost/preprocessor/facilities/intercept.hpp> 0021 #include <boost/preprocessor/repetition/repeat.hpp> 0022 #include <boost/preprocessor/repetition/enum_params.hpp> 0023 #include <boost/preprocessor/repetition/enum_trailing.hpp> 0024 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 0025 #include <boost/preprocessor/arithmetic/inc.hpp> 0026 #include <boost/preprocessor/selection/max.hpp> 0027 #include <boost/mpl/if.hpp> 0028 #include <boost/mpl/bool.hpp> 0029 #include <boost/utility/result_of.hpp> 0030 #include <boost/type_traits/remove_cv.hpp> 0031 #include <boost/proto/proto_fwd.hpp> 0032 #include <boost/proto/traits.hpp> // for child_c 0033 0034 namespace boost { namespace proto 0035 { 0036 namespace detail 0037 { 0038 template<typename Context> 0039 struct callable_context_wrapper 0040 : remove_cv<Context>::type 0041 { 0042 callable_context_wrapper(); 0043 typedef private_type_ fun_type(...); 0044 operator fun_type *() const; 0045 0046 BOOST_DELETED_FUNCTION(callable_context_wrapper &operator =(callable_context_wrapper const &)) 0047 }; 0048 0049 template<typename T> 0050 yes_type check_is_expr_handled(T const &); 0051 0052 no_type check_is_expr_handled(private_type_ const &); 0053 0054 template<typename Expr, typename Context, long Arity = Expr::proto_arity_c> 0055 struct is_expr_handled; 0056 0057 template<typename Expr, typename Context> 0058 struct is_expr_handled<Expr, Context, 0> 0059 { 0060 static callable_context_wrapper<Context> &sctx_; 0061 static Expr &sexpr_; 0062 static typename Expr::proto_tag &stag_; 0063 0064 static const bool value = 0065 sizeof(yes_type) == 0066 sizeof( 0067 detail::check_is_expr_handled( 0068 (sctx_(stag_, proto::value(sexpr_)), 0) 0069 ) 0070 ); 0071 0072 typedef mpl::bool_<value> type; 0073 }; 0074 } 0075 0076 namespace context 0077 { 0078 /// \brief A BinaryFunction that accepts a Proto expression and a 0079 /// callable context and calls the context with the expression tag 0080 /// and children as arguments, effectively fanning the expression 0081 /// out. 0082 /// 0083 /// <tt>callable_eval\<\></tt> requires that \c Context is a 0084 /// PolymorphicFunctionObject that can be invoked with \c Expr's 0085 /// tag and children as expressions, as follows: 0086 /// 0087 /// \code 0088 /// context(Expr::proto_tag(), child_c<0>(expr), child_c<1>(expr), ...) 0089 /// \endcode 0090 template< 0091 typename Expr 0092 , typename Context 0093 , long Arity // = Expr::proto_arity_c 0094 > 0095 struct callable_eval 0096 {}; 0097 0098 /// \brief A BinaryFunction that accepts a Proto expression and a 0099 /// callable context and calls the context with the expression tag 0100 /// and children as arguments, effectively fanning the expression 0101 /// out. 0102 /// 0103 /// <tt>callable_eval\<\></tt> requires that \c Context is a 0104 /// PolymorphicFunctionObject that can be invoked with \c Expr's 0105 /// tag and children as expressions, as follows: 0106 /// 0107 /// \code 0108 /// context(Expr::proto_tag(), value(expr)) 0109 /// \endcode 0110 template<typename Expr, typename Context> 0111 struct callable_eval<Expr, Context, 0> 0112 { 0113 typedef typename proto::result_of::value<Expr const &>::type value_type; 0114 0115 typedef 0116 typename BOOST_PROTO_RESULT_OF< 0117 Context(typename Expr::proto_tag, value_type) 0118 >::type 0119 result_type; 0120 0121 /// \param expr The current expression 0122 /// \param context The callable evaluation context 0123 /// \return <tt>context(Expr::proto_tag(), value(expr))</tt> 0124 result_type operator ()(Expr &expr, Context &context) const 0125 { 0126 return context(typename Expr::proto_tag(), proto::value(expr)); 0127 } 0128 }; 0129 0130 /// \brief An evaluation context adaptor that makes authoring a 0131 /// context a simple matter of writing function overloads, rather 0132 /// then writing template specializations. 0133 /// 0134 /// <tt>callable_context\<\></tt> is a base class that implements 0135 /// the context protocol by passing fanned-out expression nodes to 0136 /// the derived context, making it easy to customize the handling 0137 /// of expression types by writing function overloads. Only those 0138 /// expression types needing special handling require explicit 0139 /// handling. All others are dispatched to a user-specified 0140 /// default context, \c DefaultCtx. 0141 /// 0142 /// <tt>callable_context\<\></tt> is defined simply as: 0143 /// 0144 /// \code 0145 /// template<typename Context, typename DefaultCtx = default_context> 0146 /// struct callable_context 0147 /// { 0148 /// template<typename Expr, typename ThisContext = Context> 0149 /// struct eval 0150 /// : mpl::if_< 0151 /// is_expr_handled_<Expr, Context> // For exposition 0152 /// , callable_eval<Expr, ThisContext> 0153 /// , typename DefaultCtx::template eval<Expr, Context> 0154 /// >::type 0155 /// {}; 0156 /// }; 0157 /// \endcode 0158 /// 0159 /// The Boolean metafunction <tt>is_expr_handled_\<\></tt> uses 0160 /// metaprogramming tricks to determine whether \c Context has 0161 /// an overloaded function call operator that accepts the 0162 /// fanned-out constituents of an expression of type \c Expr. 0163 /// If so, the handling of the expression is dispatched to 0164 /// <tt>callable_eval\<\></tt>. If not, it is dispatched to 0165 /// the user-specified \c DefaultCtx. 0166 /// 0167 /// Below is an example of how to use <tt>callable_context\<\></tt>: 0168 /// 0169 /// \code 0170 /// // An evaluation context that increments all 0171 /// // integer terminals in-place. 0172 /// struct increment_ints 0173 /// : callable_context< 0174 /// increment_ints const // derived context 0175 /// , null_context const // fall-back context 0176 /// > 0177 /// { 0178 /// typedef void result_type; 0179 /// 0180 /// // Handle int terminals here: 0181 /// void operator()(proto::tag::terminal, int &i) const 0182 /// { 0183 /// ++i; 0184 /// } 0185 /// }; 0186 /// \endcode 0187 /// 0188 /// With \c increment_ints, we can do the following: 0189 /// 0190 /// \code 0191 /// literal<int> i = 0, j = 10; 0192 /// proto::eval( i - j * 3.14, increment_ints() ); 0193 /// 0194 /// assert( i.get() == 1 && j.get() == 11 ); 0195 /// \endcode 0196 template< 0197 typename Context 0198 , typename DefaultCtx // = default_context 0199 > 0200 struct callable_context 0201 { 0202 /// A BinaryFunction that accepts an \c Expr and a 0203 /// \c Context, and either fans out the expression and passes 0204 /// it to the context, or else hands off the expression to 0205 /// \c DefaultCtx. 0206 /// 0207 /// If \c Context is a PolymorphicFunctionObject such that 0208 /// it can be invoked with the tag and children of \c Expr, 0209 /// as <tt>ctx(Expr::proto_tag(), child_c\<0\>(expr), child_c\<1\>(expr)...)</tt>, 0210 /// then <tt>eval\<Expr, ThisContext\></tt> inherits from 0211 /// <tt>callable_eval\<Expr, ThisContext\></tt>. Otherwise, 0212 /// <tt>eval\<Expr, ThisContext\></tt> inherits from 0213 /// <tt>DefaultCtx::eval\<Expr, Context\></tt>. 0214 template<typename Expr, typename ThisContext = Context> 0215 struct eval 0216 : mpl::if_c< 0217 detail::is_expr_handled<Expr, Context>::value 0218 , callable_eval<Expr, ThisContext> 0219 , typename DefaultCtx::template eval<Expr, Context> 0220 >::type 0221 {}; 0222 }; 0223 } 0224 0225 #include <boost/proto/context/detail/callable_eval.hpp> 0226 0227 }} 0228 0229 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |