annotate DEPENDENCIES/generic/include/boost/proto/context/callable.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2 /// \file callable.hpp
Chris@16 3 /// Definintion of callable_context\<\>, an evaluation context for
Chris@16 4 /// proto::eval() that explodes each node and calls the derived context
Chris@16 5 /// type with the expressions constituents. If the derived context doesn't
Chris@16 6 /// have an overload that handles this node, fall back to some other
Chris@16 7 /// context.
Chris@16 8 //
Chris@16 9 // Copyright 2008 Eric Niebler. Distributed under the Boost
Chris@16 10 // Software License, Version 1.0. (See accompanying file
Chris@16 11 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 12
Chris@16 13 #ifndef BOOST_PROTO_CONTEXT_CALLABLE_HPP_EAN_06_23_2007
Chris@16 14 #define BOOST_PROTO_CONTEXT_CALLABLE_HPP_EAN_06_23_2007
Chris@16 15
Chris@16 16 #include <boost/config.hpp>
Chris@16 17 #include <boost/detail/workaround.hpp>
Chris@16 18 #include <boost/preprocessor/cat.hpp>
Chris@16 19 #include <boost/preprocessor/iteration/iterate.hpp>
Chris@16 20 #include <boost/preprocessor/facilities/intercept.hpp>
Chris@16 21 #include <boost/preprocessor/repetition/repeat.hpp>
Chris@16 22 #include <boost/preprocessor/repetition/enum_params.hpp>
Chris@16 23 #include <boost/preprocessor/repetition/enum_trailing.hpp>
Chris@16 24 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
Chris@16 25 #include <boost/preprocessor/arithmetic/inc.hpp>
Chris@16 26 #include <boost/preprocessor/selection/max.hpp>
Chris@16 27 #include <boost/mpl/if.hpp>
Chris@16 28 #include <boost/mpl/bool.hpp>
Chris@16 29 #include <boost/utility/result_of.hpp>
Chris@16 30 #include <boost/type_traits/remove_cv.hpp>
Chris@16 31 #include <boost/proto/proto_fwd.hpp>
Chris@16 32 #include <boost/proto/traits.hpp> // for child_c
Chris@16 33
Chris@16 34 namespace boost { namespace proto
Chris@16 35 {
Chris@16 36 namespace detail
Chris@16 37 {
Chris@16 38 template<typename Context>
Chris@16 39 struct callable_context_wrapper
Chris@16 40 : remove_cv<Context>::type
Chris@16 41 {
Chris@16 42 callable_context_wrapper();
Chris@16 43 typedef private_type_ fun_type(...);
Chris@16 44 operator fun_type *() const;
Chris@16 45 private:
Chris@16 46 callable_context_wrapper &operator =(callable_context_wrapper const &);
Chris@16 47 };
Chris@16 48
Chris@16 49 template<typename T>
Chris@16 50 yes_type check_is_expr_handled(T const &);
Chris@16 51
Chris@16 52 no_type check_is_expr_handled(private_type_ const &);
Chris@16 53
Chris@16 54 template<typename Expr, typename Context, long Arity = Expr::proto_arity_c>
Chris@16 55 struct is_expr_handled;
Chris@16 56
Chris@16 57 template<typename Expr, typename Context>
Chris@16 58 struct is_expr_handled<Expr, Context, 0>
Chris@16 59 {
Chris@16 60 static callable_context_wrapper<Context> &sctx_;
Chris@16 61 static Expr &sexpr_;
Chris@16 62 static typename Expr::proto_tag &stag_;
Chris@16 63
Chris@16 64 static const bool value =
Chris@16 65 sizeof(yes_type) ==
Chris@16 66 sizeof(
Chris@16 67 detail::check_is_expr_handled(
Chris@16 68 (sctx_(stag_, proto::value(sexpr_)), 0)
Chris@16 69 )
Chris@16 70 );
Chris@16 71
Chris@16 72 typedef mpl::bool_<value> type;
Chris@16 73 };
Chris@16 74 }
Chris@16 75
Chris@16 76 namespace context
Chris@16 77 {
Chris@16 78 /// \brief A BinaryFunction that accepts a Proto expression and a
Chris@16 79 /// callable context and calls the context with the expression tag
Chris@16 80 /// and children as arguments, effectively fanning the expression
Chris@16 81 /// out.
Chris@16 82 ///
Chris@16 83 /// <tt>callable_eval\<\></tt> requires that \c Context is a
Chris@16 84 /// PolymorphicFunctionObject that can be invoked with \c Expr's
Chris@16 85 /// tag and children as expressions, as follows:
Chris@16 86 ///
Chris@16 87 /// \code
Chris@16 88 /// context(Expr::proto_tag(), child_c<0>(expr), child_c<1>(expr), ...)
Chris@16 89 /// \endcode
Chris@16 90 template<
Chris@16 91 typename Expr
Chris@16 92 , typename Context
Chris@16 93 , long Arity // = Expr::proto_arity_c
Chris@16 94 >
Chris@16 95 struct callable_eval
Chris@16 96 {};
Chris@16 97
Chris@16 98 /// \brief A BinaryFunction that accepts a Proto expression and a
Chris@16 99 /// callable context and calls the context with the expression tag
Chris@16 100 /// and children as arguments, effectively fanning the expression
Chris@16 101 /// out.
Chris@16 102 ///
Chris@16 103 /// <tt>callable_eval\<\></tt> requires that \c Context is a
Chris@16 104 /// PolymorphicFunctionObject that can be invoked with \c Expr's
Chris@16 105 /// tag and children as expressions, as follows:
Chris@16 106 ///
Chris@16 107 /// \code
Chris@16 108 /// context(Expr::proto_tag(), value(expr))
Chris@16 109 /// \endcode
Chris@16 110 template<typename Expr, typename Context>
Chris@16 111 struct callable_eval<Expr, Context, 0>
Chris@16 112 {
Chris@16 113 typedef typename proto::result_of::value<Expr const &>::type value_type;
Chris@16 114
Chris@16 115 typedef
Chris@16 116 typename BOOST_PROTO_RESULT_OF<
Chris@16 117 Context(typename Expr::proto_tag, value_type)
Chris@16 118 >::type
Chris@16 119 result_type;
Chris@16 120
Chris@16 121 /// \param expr The current expression
Chris@16 122 /// \param context The callable evaluation context
Chris@16 123 /// \return <tt>context(Expr::proto_tag(), value(expr))</tt>
Chris@16 124 result_type operator ()(Expr &expr, Context &context) const
Chris@16 125 {
Chris@16 126 return context(typename Expr::proto_tag(), proto::value(expr));
Chris@16 127 }
Chris@16 128 };
Chris@16 129
Chris@16 130 /// \brief An evaluation context adaptor that makes authoring a
Chris@16 131 /// context a simple matter of writing function overloads, rather
Chris@16 132 /// then writing template specializations.
Chris@16 133 ///
Chris@16 134 /// <tt>callable_context\<\></tt> is a base class that implements
Chris@16 135 /// the context protocol by passing fanned-out expression nodes to
Chris@16 136 /// the derived context, making it easy to customize the handling
Chris@16 137 /// of expression types by writing function overloads. Only those
Chris@16 138 /// expression types needing special handling require explicit
Chris@16 139 /// handling. All others are dispatched to a user-specified
Chris@16 140 /// default context, \c DefaultCtx.
Chris@16 141 ///
Chris@16 142 /// <tt>callable_context\<\></tt> is defined simply as:
Chris@16 143 ///
Chris@16 144 /// \code
Chris@16 145 /// template<typename Context, typename DefaultCtx = default_context>
Chris@16 146 /// struct callable_context
Chris@16 147 /// {
Chris@16 148 /// template<typename Expr, typename ThisContext = Context>
Chris@16 149 /// struct eval
Chris@16 150 /// : mpl::if_<
Chris@16 151 /// is_expr_handled_<Expr, Context> // For exposition
Chris@16 152 /// , callable_eval<Expr, ThisContext>
Chris@16 153 /// , typename DefaultCtx::template eval<Expr, Context>
Chris@16 154 /// >::type
Chris@16 155 /// {};
Chris@16 156 /// };
Chris@16 157 /// \endcode
Chris@16 158 ///
Chris@16 159 /// The Boolean metafunction <tt>is_expr_handled_\<\></tt> uses
Chris@16 160 /// metaprogramming tricks to determine whether \c Context has
Chris@16 161 /// an overloaded function call operator that accepts the
Chris@16 162 /// fanned-out constituents of an expression of type \c Expr.
Chris@16 163 /// If so, the handling of the expression is dispatched to
Chris@16 164 /// <tt>callable_eval\<\></tt>. If not, it is dispatched to
Chris@16 165 /// the user-specified \c DefaultCtx.
Chris@16 166 ///
Chris@16 167 /// Below is an example of how to use <tt>callable_context\<\></tt>:
Chris@16 168 ///
Chris@16 169 /// \code
Chris@16 170 /// // An evaluation context that increments all
Chris@16 171 /// // integer terminals in-place.
Chris@16 172 /// struct increment_ints
Chris@16 173 /// : callable_context<
Chris@16 174 /// increment_ints const // derived context
Chris@16 175 /// , null_context const // fall-back context
Chris@16 176 /// >
Chris@16 177 /// {
Chris@16 178 /// typedef void result_type;
Chris@16 179 ///
Chris@16 180 /// // Handle int terminals here:
Chris@16 181 /// void operator()(proto::tag::terminal, int &i) const
Chris@16 182 /// {
Chris@16 183 /// ++i;
Chris@16 184 /// }
Chris@16 185 /// };
Chris@16 186 /// \endcode
Chris@16 187 ///
Chris@16 188 /// With \c increment_ints, we can do the following:
Chris@16 189 ///
Chris@16 190 /// \code
Chris@16 191 /// literal<int> i = 0, j = 10;
Chris@16 192 /// proto::eval( i - j * 3.14, increment_ints() );
Chris@16 193 ///
Chris@16 194 /// assert( i.get() == 1 && j.get() == 11 );
Chris@16 195 /// \endcode
Chris@16 196 template<
Chris@16 197 typename Context
Chris@16 198 , typename DefaultCtx // = default_context
Chris@16 199 >
Chris@16 200 struct callable_context
Chris@16 201 {
Chris@16 202 /// A BinaryFunction that accepts an \c Expr and a
Chris@16 203 /// \c Context, and either fans out the expression and passes
Chris@16 204 /// it to the context, or else hands off the expression to
Chris@16 205 /// \c DefaultCtx.
Chris@16 206 ///
Chris@16 207 /// If \c Context is a PolymorphicFunctionObject such that
Chris@16 208 /// it can be invoked with the tag and children of \c Expr,
Chris@16 209 /// as <tt>ctx(Expr::proto_tag(), child_c\<0\>(expr), child_c\<1\>(expr)...)</tt>,
Chris@16 210 /// then <tt>eval\<Expr, ThisContext\></tt> inherits from
Chris@16 211 /// <tt>callable_eval\<Expr, ThisContext\></tt>. Otherwise,
Chris@16 212 /// <tt>eval\<Expr, ThisContext\></tt> inherits from
Chris@16 213 /// <tt>DefaultCtx::eval\<Expr, Context\></tt>.
Chris@16 214 template<typename Expr, typename ThisContext = Context>
Chris@16 215 struct eval
Chris@16 216 : mpl::if_c<
Chris@16 217 detail::is_expr_handled<Expr, Context>::value
Chris@16 218 , callable_eval<Expr, ThisContext>
Chris@16 219 , typename DefaultCtx::template eval<Expr, Context>
Chris@16 220 >::type
Chris@16 221 {};
Chris@16 222 };
Chris@16 223 }
Chris@16 224
Chris@16 225 #include <boost/proto/context/detail/callable_eval.hpp>
Chris@16 226
Chris@16 227 }}
Chris@16 228
Chris@16 229 #endif