/* * $Id$ */ /* * Copyright (c) 2016 Brook Milligan. * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ #include #include #include #include "exp.hpp" // XXX - suggested addition to Boost.Proto: // a metafunction such as here for deducing the type of a proto terminal. // This makes specializing on the type of terminal possible (see below). #include "terminal.hpp" // XXX - enabling the following yields compilation errors (at least in Boost v1.59) #define USE_PROTO_CHILD_0_FOR_SPECIALIZING 0 struct placeholder {}; typedef boost::proto::terminal::type real_type; typedef boost::proto::terminal::type const placeholder_type; placeholder_type _ = {{}}; class context { typedef context this_context; #if USE_PROTO_CHILD_0_FOR_SPECIALIZING public: template < typename Expr , typename Tag = typename boost::proto::tag_of::type , typename Arg0 = typename boost::proto::result_of::child_c::type > struct eval; template < typename Expr, typename Tag, typename Arg0 > struct eval : boost::proto::context::default_eval< Expr,this_context const > {}; template < typename Expr > struct eval< Expr,boost::proto::tag::terminal,placeholder > { typedef double result_type; result_type operator () (Expr&, this_context const& context) const { return context.x_; } }; #else // !USE_PROTO_CHILD_0_FOR_SPECIALIZING template < typename Expr , typename Arg0 = boost::proto::type_traits::terminal_t > struct terminal_eval : boost::proto::context::default_eval< Expr,this_context const > {}; template < typename Expr > struct terminal_eval< Expr,placeholder > { typedef double result_type; result_type operator () (Expr&, this_context const& context) const { return context.x_; } }; public: template < typename Expr , long Arity = boost::proto::arity_of::value > struct eval; template < typename Expr, long Arity > struct eval : boost::proto::context::default_eval< Expr,this_context const > {}; template < typename Expr > struct eval< Expr,0 > : terminal_eval {}; #endif // USE_PROTO_CHILD_0_FOR_SPECIALIZING private: double x_ = 2; }; int main () { real_type x = { 0 }; auto f = math::exp(x); assert(boost::proto::eval(f,context()) == std::exp(0)); boost::proto::value(x) = 1; assert(boost::proto::eval(f,context()) == std::exp(1)); auto g = math::exp(_); assert(boost::proto::eval(g,context()) == std::exp(2)); return 0; }