blob: b18d5b47b4d0baaf1796114fb69e1c86103d4e86 [file]
/*
* $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<unsigned Sz> 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<unsigned Sz, unsigned Stride=0>
struct MetaVector
{
enum {
doIt = (Stride < (Sz-1)) ? 1 : 0
};
template <class E1, class E2, class Fcnl>
static inline
void assign(E1& lhs, const E2& rhs, const Fcnl& fn) {
fn.apply_on(lhs(Stride), rhs(Stride));
MetaVector<Sz * doIt, (Stride+1) * doIt>::assign(lhs, rhs, fn);
}
};
template<>
struct MetaVector<0,0>
{
template <class E1, class E2, class Fcnl>
static inline void assign(E1&, const E2&, const Fcnl&) { }
};
template<class E, unsigned Sz>
struct XprVector
{
explicit XprVector(const E& e) : m_expr(e) { }
double operator()(unsigned i) const {
return m_expr(i);
}
template<class E2, class Fcnl>
void assign_to(E2& e, const Fcnl& fn) const {
MetaVector<Sz, 0>::assign(e, *this, fn);
}
const E m_expr;
};
template<unsigned Sz, unsigned Stride=1>
struct VectorConstReference
{
explicit VectorConstReference(const Vector<Sz>& rhs) : m_data(rhs.m_data) { }
double operator()(unsigned i) const {
return m_data[i * Stride];
}
const double* restrict m_data;
};
template<unsigned Sz>
struct Vector
{
explicit Vector() { }
double& restrict operator()(unsigned i) { return m_data[i]; }
double operator()(unsigned i) const { return m_data[i]; }
typedef VectorConstReference<Sz, 1> ConstReference;
ConstReference const_ref() const { return ConstReference(*this); }
template<class Fcnl>
void assign_to(Vector& v, const Fcnl& fn) {
MetaVector<Sz, 0>::assign(v, *this, fn);
}
template<class E>
Vector& operator=(const XprVector<E, Sz>& rhs) {
rhs.assign_to(*this, Fcnl_Assign());
return *this;
}
double m_data[Sz];
};
template<class BinOp, class E1, class E2>
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<unsigned Sz>
inline
XprVector<
XprBinOp<
Fcnl_Add,
VectorConstReference<Sz>,
VectorConstReference<Sz>
>,
Sz
>
add (const Vector<Sz>& lhs, const Vector<Sz>& rhs) {
typedef XprBinOp <
Fcnl_Add,
VectorConstReference<Sz>,
VectorConstReference<Sz>
> expr_type;
return XprVector<expr_type, Sz>(
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));
}