Re: [boost] Proto expresion construction question

Cédric Venet wrote:
Hi,
I decided to try to write a small vector library with proto to test it.
The following worked without problem (I will use extend further on but at the moment the as_expr are needed)
proto::display_expr( proto::as_expr(x)+proto::as_expr(y)*proto::as_expr(z) , std::cout );
I then added
struct fastvec_reduction_tag {}; struct sum_ {}; template<typename A> typename proto::result_of::make_expr< fastvec_reduction_tag // , MixedDomain , sum_ const , A const &
::type sum(A const &a) { return proto::make_expr<fastvec_reduction_tag/*, MixedDomain*/>(sum_(), boost::ref(a)); }
Which work well
proto::display_expr( sum(x) , std::cout );
And now, I would like to create a "function" dot(x,y) which expand to sum(x*y). I tried:
template<typename A, typename B> typename proto::result_of::make_expr< fastvec_reduction_tag // , MixedDomain , sum_ const , BOOST_TYPEOF(boost::ref(proto::as_expr(A())*proto::as_expr(B())))
const & ::type dot(A const &a, B const &b) { return proto::make_expr<fastvec_reduction_tag/*, MixedDomain*/>(sum_(), boost::ref( proto::as_expr(a)*proto::as_expr(b) )); }
Which compile but fail at runtime when I do
proto::display_expr( dot(x,y) , std::cout );
(it call << on an invalid vector (type of x and y)).
Is there a ways to create the tree for sum(x*y) directly or should I use a transform (create a tree with a dot tag and then transform it with proto)?
The problem you're running into is that as_expr(a) is creating a temporary object, which is getting held by reference in the expression tree created by proto's operator* overload. Then you're returning the tree and letting the references dangle. When creating trees and returning them from functions, you should be using make_expr() consistently so that you have explicit control over what gets stored by reference and by value. Try this: #include <iostream> #include <boost/xpressive/proto/proto.hpp> #include <boost/xpressive/proto/debug.hpp> using namespace boost; struct fastvec_reduction_tag {}; struct sum_ {friend std::ostream&operator<<(std::ostream&s,sum_){return s<<"sum_";}}; template<typename A> typename proto::result_of::make_expr< fastvec_reduction_tag , sum_ const , A const & >::type sum(A const &a) { return proto::make_expr<fastvec_reduction_tag>( sum_() , boost::ref(a) ); } template<typename A, typename B> typename proto::result_of::make_expr< fastvec_reduction_tag , sum_ const , typename proto::result_of::make_expr< proto::tag::multiplies , A const & , B const & >::type >::type dot(A const &a, B const &b) { return proto::make_expr<fastvec_reduction_tag>( sum_() , proto::make_expr<proto::tag::multiplies>( boost::ref(a) , boost::ref(b) ) ); } int main() { int x = 0, y = 1; proto::display_expr( sum(x) , std::cout ); proto::display_expr( dot(x,y) , std::cout ); return 0; }
The page 'users_guide\expression_construction\construction_utils.html' seems very complete, but hard to understand how to put it in practice, perhaps you could link it to some use in the example.
This might make a good example, in fact. Thanks. -- Eric Niebler Boost Consulting www.boost-consulting.com
participants (1)
-
Eric Niebler