|
Boost Users : |
Subject: Re: [Boost-users] [Proto] Forwarding evaluation via tag
From: Eric Niebler (eric_at_[hidden])
Date: 2009-09-29 16:21:55
joel wrote:
>
>> You'll have to post your code ... I can't tell what problem you might
>> be running into.
> Well, I decided to be a coward for today. I'll shelf this functional
> solution for later. I just added
> my own ternary_expr & quaternary_expr class for the moment as it seems
> it's all the client wants.
> I'll come back when I've digested those infos as I htink I'm just doing
> a small error.
>
> For reference here is the code I wrote:
>
> namespace bp = boost::proto;
>
> struct push_front_
Must inherit from bp::callable.
> {
> template<class Sig> struct result;
> template<class This,class Seq,class Elem>
> struct result<This(Seq,Elem)>
> {
> typedef typename
> boost::fusion::result_of::push_front<Seq,Elem>::type type;
> };
>
> template<class Seq,class Elem>
> typename result<push_front_(Seq,Elem)>::type
> operator()(Elem const& e, Seq& s ) const
Sequence and Element argument order is reversed here.
> {
> return boost::fusion::push_front(s,e);
> }
> };
>
> struct _load : bp::transform< _load >
> {
> template<typename Expr, typename State, typename Data>
> struct impl : bp::transform_impl<Expr, State, Data>
> {
> typedef typename meta::strip<Expr>::type::value_type result_type;
>
> result_type operator()( typename impl::expr_param expr
> , typename impl::state_param
> , typename impl::data_param data
> ) const
> {
> return expr(data);
> }
> };
> };
>
> struct eval_xpr
> : bp::or_< bp::when< bp::terminal< block<bp::_,bp::_> >
> , _load(bp::_)
> >
> , bp::when< bp::nary_expr< bp::_, bp::vararg<eval_xpr> >
> , bp::functional::unpack_expr<bp::tag::function>(
This will create the new expression but not evaluate it. I had
incorrectly told you to use bp::function<> here for its pass-through
transform, but that's not actually what you want. You want Proto's
_default transform.
> push_front_(bp::_,
> bp::terminal<functor<bp::tag_of<bp::_> > >() )
>
> ) )
> >
> > {};
Here is some code that should get you going again:
#include <boost/proto/core.hpp>
#include <boost/proto/transform.hpp>
#include <boost/fusion/include/push_front.hpp>
namespace bp = boost::proto;
struct push_front : bp::callable
{
template<class Sig> struct result;
template<class This, class Seq, class Elem>
struct result<This(Seq, Elem)>
: boost::fusion::result_of::push_front<
typename boost::remove_reference<Seq>::type const
, typename boost::remove_reference<Elem>::type
>
{};
template<class Seq, class Elem>
typename result<push_front(Seq const, Elem)>::type
operator()(Seq const& s, Elem const& e) const
{
return boost::fusion::push_front(s, e);
}
};
template<typename T> struct functor;
template<> struct functor<bp::tag::plus>
{
typedef int result_type;
int operator()(int x, int y) const
{
return x + y;
}
};
struct eval_xpr
: bp::or_<
bp::when<
bp::terminal< bp::_ >
, bp::_value
>
, bp::when<
bp::nary_expr< bp::_, bp::vararg<eval_xpr> >
, bp::_default<eval_xpr>(
bp::functional::unpack_expr<bp::tag::function>(
push_front(
bp::_
, bp::_make_terminal(functor<bp::tag_of<bp::_> >())
)
)
)
>
>
{};
int main()
{
bp::literal<int> x(1);
bp::literal<int> y(2);
int z = eval_xpr()(x + y);
}
Hope that helps,
-- Eric Niebler BoostPro Computing http://www.boostpro.com
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net