
Eric, the attached file exibits a problem with (I think) display_expr: The second line in main() fails. But if you comment out the definition of META_EXPR(plus,left,...) and replace it with the one just below it and presently commented out then everything is fine. Seems like display_expr is not appy with function applied to more than one argument. Unless there's something stupid in my code. Regards, Maurizio

Maurizio Vitale wrote:
Eric, the attached file exibits a problem with (I think) display_expr: The second line in main() fails. But if you comment out the definition of META_EXPR(plus,left,...) and replace it with the one just below it and presently commented out then everything is fine. Seems like display_expr is not appy with function applied to more than one argument.
Unless there's something stupid in my code.
Essentially, what you're doing is: BOOST_TYPEOF(some + proto + expr) e = some + proto + expr; // Use e It doesn't work quite like this. The reason why is that "some + proto + expr" is a tree where some of the nodes are temporary objects, which are held by reference by other nodes. It's a castle in the air, and at the semicolon, it crashes down. You need proto::deep_copy(): BOOST_TYPEOF(proto::deep_copy(some + proto + expr)) e = proto::deep_copy(some + proto + expr); // Use e Or even better: BOOST_PROTO_AUTO(e, some + proto + expr); which does the deep_copy for you. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler <eric@boost-consulting.com> writes:
Unless there's something stupid in my code.
I thought so :-)
Essentially, what you're doing is:
BOOST_TYPEOF(some + proto + expr) e = some + proto + expr; // Use e
It doesn't work quite like this. The reason why is that "some + proto + expr" is a tree where some of the nodes are temporary objects, which are held by reference by other nodes. It's a castle in the air, and at the semicolon, it crashes down.
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. But this is not the reason I didn't use it, more simply, I forgot about it. 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? Regards, Maurizio

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

Eric Niebler <eric@boost-consulting.com> writes:
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.
I'll take a look at the lambda example again, but in this particular case I'll probably stay with the deep_copy approach: I'll have maybe 10-20 of those expressions and they'll be initialized at startup and I think explicit expressions make the intent clearer. But unless I find other problems, I'll try to make my expressions PODs. That should be good regardless.
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.
Thanks for the code. I'll use the fixed deep_copy, but it is always educational. Regards, Maurizio

Maurizio Vitale wrote:
Eric Niebler <eric@boost-consulting.com> writes:
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.
deep_copy() uses generate<> now. Let me know if you still have problems. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler <eric@boost-consulting.com> writes:
deep_copy() uses generate<> now. Let me know if you still have problems.
Works now, thanks. It maybe worth mentioning (in the docs as well) that the type returned by deep_copy is different from the type of the expression being copied (it has to be because of ref-to-val) It is obvious once you're into proto, but might be surprising at first. If you can use BOOST_PROTO_AUTO everything is taken care of, but if you're forced to declare a variable somewhere and initialize it somewhere else you've to declare it with BOOST_TYPEOF ((proto::deep_copy (my - proto + expr))). This is the case when initializing a static class member, although your suggestion from your other message in this thread of extending preserving POD-ness probably solves this problem as well. Thanks again, Maurizio
participants (2)
-
Eric Niebler
-
Maurizio Vitale