|
Boost : |
From: Eric Niebler (eric_at_[hidden])
Date: 2007-07-17 10:58:43
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk