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