[phoenix] v3 extension mechanism for template functions
Hi, In Phoenix2 I used to have the following code to add expressions of type pow<N>(... expr...) which where useful for expressions involving Boost.Units. Is it possible to do something similar with Phoenix3. The usage if macros in the tutorial examples obscures how to add template parameters to the phoenix expression. In Phoenix2 it was straight forward, but I can figure out how to do this in Phoenix3. // phoenix2 code: #include <boost/units/pow.hpp> namespace boost{ namespace phoenix{ template<long N> struct pow_eval{ template <typename Env, typename Arg_> struct result{ typedef typename boost::units::power_typeof_helper<typename boost::mpl::at_c<typename Env::args_type, 0>::type, boost::units::static_rational<N> >::type type; }; template <typename RT, typename Env, typename Arg_> static RT eval(Env const& env, Arg_ const& arg_){ return boost::units::pow<N>(arg_.eval(env)); } }; template<long N, typename Arg_> actor<composite<pow_eval<N>, boost::fusion::vector<Arg_ > > > pow(actor<Arg_> const& arg_){ return compose<pow_eval<N> >(arg_); } }} use as pow<3>(arg1)(l)
On Apr 18, 8:34 pm, alfC <alfredo.cor...@gmail.com> wrote:
Hi,
In Phoenix2 I used to have the following code to add expressions of type pow<N>(... expr...) which where useful for expressions involving Boost.Units. Is it possible to do something similar with Phoenix3. The usage if macros in the tutorial examples obscures how to add template parameters to the phoenix expression. In Phoenix2 it was straight forward, but I can figure out how to do this in Phoenix3.
ok, this is the farthest I could go with Phoenix3. It seems that the tag:: struct argument in phoenix::expr is a template template. The following is the latest attempt, which doesn't compile, giving the error: boost/phoenix/core/is_nullary.hpp:124:9: error: base type ‘const boost::proto::exprns_::basic_expr<boost::phoenix::tag::pow, boost::proto::argsns_::list1<boost::phoenix::actor<boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0l> > >, 1l>&’ fails to be a struct or class type #include<boost/units/cmath.hpp> namespace boost{ namespace phoenix{ namespace tag{ template<long N> struct pow{}; } namespace expression { template <long N, typename A0> struct pow : boost::phoenix::expr< tag::pow<N> , A0 > {}; } } namespace phoenix_impl{ template<long N> struct pow_impl{ template<class Sig> struct result; template<class This, class Arg, class Cont> struct result<This(Arg, Cont)>{ typedef double type; // just for testing }; template<class Arg, class Cont> typename result<pow_impl(Arg const&, Cont const&)>::type operator()(Arg const& arg, Cont const& ctx) const { return boost::units::pow<N>(eval(arg, ctx)).value(); //value, just for testing } }; } namespace phoenix{ template <long N, typename Arg> typename expression::pow<N, Arg>::type const pow(Arg const& arg){ return expression::pow<N, Arg>::make(arg); } } }
On Tue, Apr 19, 2011 at 5:34 AM, alfC <alfredo.correa@gmail.com> wrote:
Hi,
In Phoenix2 I used to have the following code to add expressions of type pow<N>(... expr...) which where useful for expressions involving Boost.Units. Is it possible to do something similar with Phoenix3. The usage if macros in the tutorial examples obscures how to add template parameters to the phoenix expression.
Well. the intention was to not obscure but ease the process of adding new expressions. Your hint has been noted, i will explain what this macro does with an example.
In Phoenix2 it was straight forward, but I can figure out how to do this in Phoenix3.
The process is simple: 1) Define the expression, this means: 1.1) Define how the proto expression will look like 1.2) Define what expressions will match 1.3) Hook the expression up in the Actions mechanism This is done by the macro. Cause the code for that will look almost the same everytime. 2) Define what's to be done in the default_actions (usually call some other functor with the expressions children) 3) Write a generation function. Please have a look at: http://svn.boost.org/svn/boost/trunk/boost/phoenix/fusion/at.hpp
On Apr 18, 10:05 pm, Thomas Heller <thom.hel...@googlemail.com> wrote:
Well. the intention was to not obscure but ease the process of adding new expressions. Your hint has been noted, i will explain what this macro does with an example.
makes sense. Following your steps and the code base in boost/phoenix/fusion/at.hpp and boost/proto/functional/fusion/at.hpp I was able to add the pow<N>(...) expression (which works for boost.units, and doubles), see below. Thanks, #include <boost/phoenix/core/limits.hpp> #include <boost/phoenix/core/expression.hpp> #include <boost/phoenix/core/meta_grammar.hpp> #include <boost/type_traits/remove_reference.hpp> #include<boost/phoenix/core.hpp> #include<boost/phoenix/phoenix.hpp> #define BOOST_MPL_LIMIT_METAFUNCTION_ARITY 5 #include<boost/units/cmath.hpp> BOOST_PHOENIX_DEFINE_EXPRESSION( (boost)(phoenix)(pow) , (proto::terminal<proto::_>) (meta_grammar) ) namespace boost{ namespace phoenix{ struct pow_eval{ BOOST_PROTO_CALLABLE() //what for? template<typename Sig> struct result; template<typename This, typename Seq, typename N> struct result<This(Seq, N)>{ typedef typename boost::units::power_typeof_helper< typename boost::remove_const<typename boost::remove_reference<Seq>::type>::type, boost::units::static_rational<boost::remove_reference<N>::type::value> >::type type; }; template<typename Seq, typename N> typename result<pow_eval(Seq, N)>::type operator()(Seq const &seq, N const&) const{ using namespace boost::units; return pow<N::value>(seq); } }; template <typename Dummy> struct default_actions::when<rule::pow, Dummy> : proto::call< pow_eval( evaluator(proto::_child_c<1>) , proto::_value(proto::_child_c<0>) ) > {}; template<long N, typename Arg> typename expression::pow<mpl::int_<N>, Arg>::type const pow(Arg const& arg){ return expression::pow<mpl::int_<N>, Arg>::make(mpl::int_<N>(), arg); } } }
On Apr 19, 11:58 pm, alfC <alfredo.cor...@gmail.com> wrote:
makes sense. Following your steps and the code base in boost/phoenix/fusion/at.hpp and boost/proto/functional/fusion/at.hpp I was able to add the pow<N>(...) expression (which works for boost.units, and doubles), see below.
BTW, using (note the actor<...> pattern (see below) nicely lifts an ambiguity between boost::units::pow and the newly created boost::phoenix::pow. I hope the boost.units maintainers take now and include an adaptor like this to boost/units/phoenix.hpp template<long N, typename Arg> typename expression::pow<mpl::int_<N>, actor<Arg> >::type const pow(actor<Arg> const& arg){ return expression::pow<mpl::int_<N>, actor<Arg>
::make(mpl::int_<N>(), arg); }
Thanks, Alfredo
participants (2)
-
alfC
-
Thomas Heller