|
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