Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2007-05-22 22:55:47


Maurizio Vitale wrote:
>>
>> You need proto::deep_copy():
>
> It doesn't quite work because it seems deep_copy doesn't (seem to) use
> generate for wrapping up expression, with the result that the type of
> the object returned by deep_copy is deeply different from the type
> sent in.

Oh, you're right. I'll have to fix that.

> Question: once deep_copy is fixed (or you show me how to use it in my context),
> would it be usable for initializing a static member variable?

Well, it's not ideal for that because it requires a runtime function
call. But then again, so do proto's operator overloads. This is the sort
of thing where you would want to leverage the POD-ness of proto's expr<>
type. Consider:

   // 1 + "hello"
   proto::plus<
      proto::terminal<int>::type
    , proto::terminal<char const *>::type
>::type const int_plus_string = {{1}, {"hello"}};

This thing requires no runtime initialization. And if you peek at
libs/xpressive/proto/test/lambda.cpp, check out the lambda<> expression
wrapper. It shows a way to extend a proto expression type without losing
POD-ness, so you can make the above still work.

If you'd rather go the deep copy route, you don't need to wait for me to
fix proto::deep_copy(). You can accomplish the same thing with a proto
transform. Here is some code to get you started. It deep-copies a proto
expression, and wraps everything in a myexpr<> wrapper.

#include <iostream>
#include <boost/xpressive/proto/proto.hpp>
using namespace boost;
using proto::_;

template<typename Expr>
struct myexpr
   : proto::extends< Expr, myexpr<Expr> >
{
     myexpr(Expr const &expr = Expr())
       : proto::extends< Expr, myexpr<Expr> >(expr)
     {}
};

template<typename Grammar>
struct make_myexpr
   : Grammar
{
     template<typename Expr, typename State, typename Visitor>
     struct apply
     {
         typedef myexpr<
             typename Grammar::template apply<Expr, State, Visitor>::type
> type;
     };

     template<typename Expr, typename State, typename Visitor>
     static typename apply<Expr, State, Visitor>::type
     call(Expr const &expr, State const &state, Visitor &visitor)
     {
         return typename apply<Expr, State, Visitor>::type(
             Grammar::call(expr, state, visitor)
         );
     }
};

template<typename Grammar>
struct by_val
   : Grammar
{
     template<typename Expr, typename State, typename Visitor>
     struct apply
       : proto::terminal< typename proto::result_of::arg<Expr>::type >
     {};

     template<typename Expr, typename State, typename Visitor>
     static typename apply<Expr, State, Visitor>::type
     call(Expr const &expr, State const &state, Visitor &visitor)
     {
         return typename apply<Expr, State, Visitor>::type::make(
             proto::arg(expr)
         );
     }
};

struct my_deep_copy
   : make_myexpr<
         proto::or_<
             by_val<proto::terminal<_> >
           , proto::nary_expr<_, proto::vararg<my_deep_copy> >
>
>
{};

int main()
{
     int i = 0;
     // before
     std::cout << typeid(
         proto::as_expr(1) >> 2 >> 3
         ).name() << std::endl;
     // after
     std::cout << typeid(
         my_deep_copy::call( proto::as_expr(1) >> 2 >> 3, i, i )
         ).name() << std::endl;
     return 0;
}

HTH,

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk