Boost logo

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