Boost logo

Boost Users :

Subject: Re: [Boost-users] [Proto] Questions about deep_copy
From: Eric Niebler (eric_at_[hidden])
Date: 2009-05-10 11:48:29


Kim Kuen Tang wrote:
> Hi all,
>
> consider the following code:
>
> std::vector<double> a(10,1.0), b(10,2.0);
> BOOST_AUTO( temp , proto::as_expr<MixedDomain>(a+b+0.1) ); // is the
> function proto::as_expr<MixedDomain>() needed?
<snip>
>
> But the code crashes during runtime. The reason is that the number 0.1
> is held by reference.
> So the number 0.1 goes out of scope before i try to evaluate the
> expression temp[0];
>
> A way to solve this problem is to deep copy the expression with
> deep_copy. But on the other hand i do not want to copy the two vectors a
> and b.

Deep-copying only some terminals is fundamentally unsafe. But if you
really don't want to deep-copy the vector terminals, you'll need to
implement your own deep-copy algorithm. It's easiest to write a grammar
with transforms that does it for you.

   #include <vector>
   #include <boost/proto/proto.hpp>

   namespace boost { namespace proto
   {
       // make std::vector a proto terminal extension
       template<typename T, typename Al>
       struct is_extension<std::vector<T, Al> >
         : mpl::true_
       {};
   }}

   namespace proto = boost::proto;
   using proto::_;

   // Deep-copy all terminals except vectors
   struct DeepCopyNotVectors
     : proto::or_<
           proto::when<
               proto::terminal<std::vector<_,_> >
               // The vector itself will be held by reference, but the
               // temporary proto terminal expression wrapping the
               // reference should be held by value.
             , boost::remove_const<boost::remove_reference<_> >(_)
>
         , proto::when<proto::terminal<_>, proto::_deep_copy(_)>
         , proto::otherwise<
               proto::nary_expr<_, proto::vararg<DeepCopyNotVectors> >
>
>
   {};

   int main()
   {
       using namespace proto::exops;

       std::vector<int> a, b;

       BOOST_AUTO(tmp0, a + b + 0.1);
       BOOST_AUTO(tmp1, DeepCopyNotVectors()(a + b + 0.1));

       std::cout << typeid(tmp0).name() << "\n\n";
       std::cout << typeid(tmp1).name() << "\n";
   }

   int main()
   {
       using namespace proto::exops;

       std::vector<int> a, b;

       BOOST_AUTO(tmp0, a + b + 0.1);
       BOOST_AUTO(tmp1, DeepCopyNotVectors()(a + b + 0.1));

       std::cout << typeid(tmp0).name() << "\n\n";
       std::cout << typeid(tmp1).name() << "\n";
   }

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net