
Maurizio Vitale wrote:
On Jul 17, 2007, at 2:54 AM, dan marsden wrote:
function<int(int&,int&)> f(_0 + _1); // Copy lambda expression into a Boost.Function func
Now I've got problems because proto trees are built out of references (to temporaries). So func will blow up later when the temporaries are off the stack
bitten by this in the past. There's a proto::deep_copy function that you can use for converting references to values.
Maurizio, deep_copy() alone will not work here. The user is creating a lambda expression and assigning it directly to function<>: function<int(int&,int&)> f(_0 + _1); function<> knows nothing about proto expressions, and doesn't know to call proto::deep_copy(). Dan, this is a job for a custom generator. (Thanks, I haven't had need of one until now! This'll make a great example.) You're already using a generator to wrap your expressions. But you also need a deep_copy-ing generator. Here's the basic idea ... #include <iostream> #include <boost/xpressive/proto/proto.hpp> using namespace boost::proto; template<typename Expr> struct lambda_expr; struct lambda_generator { template<typename Expr> struct apply { typedef lambda_expr< typename result_of::deep_copy<Expr>::type > type; }; template<typename Expr> static typename apply<Expr>::type make(Expr const &expr) { typename apply<Expr>::type that = {deep_copy(expr)}; return that; } }; struct lambda_domain : domain<lambda_generator> {}; template<typename Expr> struct lambda_expr { BOOST_PROTO_EXTENDS(Expr, lambda_expr<Expr>, lambda_domain) BOOST_PROTO_EXTENDS_ASSIGN(Expr, lambda_expr<Expr>, lambda_domain) BOOST_PROTO_EXTENDS_SUBSCRIPT(Expr, lambda_expr<Expr>, lambda_domain) // Implement operator() here. }; struct one_tag {}; lambda_expr<terminal<one_tag>::type> const _1 = {{{}}}; int main() { _1 + 42; std::cout << typeid(_1+42).name() << std::endl; return 0; } Of course, calling deep_copy() in the generator is sub-optimal. Every part of the tree has been deep_copied already except the top-most node. When I find time, I'll write a by_value_generator which makes sure everything in the tree is held by value. (I'm using the BOOST_PROTO_EXTENDS macros here instead of proto::extends<> so that _1 can be statically initialized. You may want to do something similar, if you aren't already.) HTH, -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com