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
namespace boost { namespace proto
{
// make std::vector a proto terminal extension
template
struct is_extension >
: mpl::true_
{};
}}
namespace proto = boost::proto;
using proto::_;
// Deep-copy all terminals except vectors
struct DeepCopyNotVectors
: proto::or_<
proto::when<
proto::terminal >
// 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 >(_)
>
, proto::when, 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