/* * $Id: bad_xpr_const_ref.cc,v 1.1 2003/10/21 19:40:38 opetzold Exp $ * * This example shows the problem on holding references * by expressions. On higher optimization levels all things * are good. Without optimizations it crashs. */ extern "C" int printf(const char*, ...); #ifndef restrict #define restrict __restrict__ #endif template class Vector; struct Fcnl_Assign { static inline void apply_on(double& restrict lhs, double rhs) { lhs = rhs; } }; struct Fcnl_Add { static inline double apply_on(double lhs, double rhs) { return lhs + rhs; } }; template struct MetaVector { enum { doIt = (Stride < (Sz-1)) ? 1 : 0 }; template static inline void assign(E1& lhs, const E2& rhs, const Fcnl& fn) { fn.apply_on(lhs(Stride), rhs(Stride)); MetaVector::assign(lhs, rhs, fn); } }; template<> struct MetaVector<0,0> { template static inline void assign(E1&, const E2&, const Fcnl&) { } }; template struct XprVector { explicit XprVector(const E& e) : m_expr(e) { } double operator()(unsigned i) const { return m_expr(i); } template void assign_to(E2& e, const Fcnl& fn) const { MetaVector::assign(e, *this, fn); } const E m_expr; }; template struct VectorConstReference { explicit VectorConstReference(const Vector& rhs) : m_data(rhs.m_data) { } double operator()(unsigned i) const { return m_data[i * Stride]; } const double* restrict m_data; }; template struct Vector { explicit Vector() { } double& restrict operator()(unsigned i) { return m_data[i]; } double operator()(unsigned i) const { return m_data[i]; } typedef VectorConstReference ConstReference; ConstReference const_ref() const { return ConstReference(*this); } template void assign_to(Vector& v, const Fcnl& fn) { MetaVector::assign(v, *this, fn); } template Vector& operator=(const XprVector& rhs) { rhs.assign_to(*this, Fcnl_Assign()); return *this; } double m_data[Sz]; }; template struct XprBinOp { explicit XprBinOp(const E1& lhs, const E2& rhs) : m_lhs(lhs), m_rhs(rhs) { } double operator()(unsigned i) const { return BinOp::apply_on(m_lhs(i), m_rhs(i)); } const E1& m_lhs; const E2& m_rhs; }; template inline XprVector< XprBinOp< Fcnl_Add, VectorConstReference, VectorConstReference >, Sz > add (const Vector& lhs, const Vector& rhs) { typedef XprBinOp < Fcnl_Add, VectorConstReference, VectorConstReference > expr_type; return XprVector( expr_type(lhs.const_ref(), rhs.const_ref())); } int main() { Vector<5> v, v1,v2; v1(0) = 1; v1(1) = 2; v1(2) = 3; v1(3) = 4; v1(4) = 5; v2(0) = 1; v2(1) = 2; v2(2) = 3; v2(3) = 4; v2(4) = 5; v = add(v1, v2); printf("v(0) = %f\n", v(0)); }