#include <cassert>
#include <iostream>
namespace expr
{
typedef unsigned int uint;
// globals to count constructor and destructor calls
// of a vec
uint ctor_calls = 0;
uint dtor_calls = 0;
// print the numbers
void printctor()
{
std::cout << "ctor/dtor = " << ctor_calls
<< "/" << dtor_calls << "\n";
}
// an example vec container of three successive floats
class vec
{
public:
float v[3];
// note: the {...} is c++0x initializer syntax
vec () : v({0,0,0}) { ++ctor_calls; }
vec (const vec& o) : v({o.v[0], o.v[1], o.v[2]}) { ++ctor_calls; }
vec (float x,float y,float z) : v({x,y,z}) { ++ctor_calls; }
~vec() { ++dtor_calls; }
// return indexed value
float operator[](uint index) const { return v[index]; }
// return indexed reference
float& operator[](uint index) { return v[index]; }
void print() { std::cout << "<"<<v[0]<<","<<v[1]<<","<<v[2]<<">\n"; }
// assignment to an expression
// E must have operator[](uint)
template <class E>
vec& operator= (const E& x)
{
for (uint i=0; i!=3; ++i) (*this)[i] = x[i];
return *this;
}
};
// basic catch-all expression node
// L and R must provide operator[](uint)
// O must provide static function float eval(float,float)
template <class L, class O, class R>
struct expression
{
expression(const L& l, const R& r)
: l(l), r(r) { }
float operator[](const uint index) const
{
return O::eval(l[index], r[index]);
}
const L& l;
const R& r;
};
// wraps a reference to float into an operator[](uint) entity
class scalar
{
public:
scalar(const float& t) : t(t) { }
// act like an endless vector of ts
float operator[](uint) const { return t; }
const float& t;
};
// an operation function object
struct plus
{
static float eval(const float a, const float b) { return a + b; }
};
// anything + anything
template <class L, class R>
expression<L,plus,R> operator+(const L& l, const R& r)
{
return expression<L,plus,R>(l, r);
}
// anything + scalar
template <class L>
expression<L,plus,scalar> operator+(const L& l, const float& r)
{
return expression<L,plus,scalar>(l, r);
}
}
void do_some()
{
using namespace expr;
vec a(1,2,3), b(2,3,4), c(3,4,5);
a.print(); b.print(); c.print();
// works
a = b + c;
a.print();
assert( a.v[0] == 5 && a.v[1] == 7 && a.v[2] == 9 );
// does not work -> segfault
a = b + 1.f;
a.print();
assert( a.v[0] == 3 && a.v[1] == 4 && a.v[2] == 5 );
}
int main()
{
do_some();
// check ctor calls
expr::printctor();
return 0;
}
I2luY2x1ZGUgPGNhc3NlcnQ+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCm5hbWVzcGFjZSBleHByCnsKCXR5cGVkZWYgdW5zaWduZWQgaW50IHVpbnQ7CgoJLy8gZ2xvYmFscyB0byBjb3VudCBjb25zdHJ1Y3RvciBhbmQgZGVzdHJ1Y3RvciBjYWxscwoJLy8gb2YgYSB2ZWMKCXVpbnQgY3Rvcl9jYWxscyA9IDA7Cgl1aW50IGR0b3JfY2FsbHMgPSAwOwoJLy8gcHJpbnQgdGhlIG51bWJlcnMKCXZvaWQgcHJpbnRjdG9yKCkKCXsKCQlzdGQ6OmNvdXQgPDwgImN0b3IvZHRvciA9ICIgPDwgY3Rvcl9jYWxscyAKICAgICAgICAgICAgICAgIDw8ICIvIiA8PCBkdG9yX2NhbGxzIDw8ICJcbiI7Cgl9CgoJLy8gYW4gZXhhbXBsZSB2ZWMgY29udGFpbmVyIG9mIHRocmVlIHN1Y2Nlc3NpdmUgZmxvYXRzCgljbGFzcyB2ZWMKCXsKCQlwdWJsaWM6CgoJCWZsb2F0IHZbM107CgoJCS8vIG5vdGU6IHRoZSB7Li4ufSBpcyBjKysweCBpbml0aWFsaXplciBzeW50YXgKCQl2ZWMgKCkgOiB2KHswLDAsMH0pIHsgKytjdG9yX2NhbGxzOyB9CgkJdmVjIChjb25zdCB2ZWMmIG8pIDogdih7by52WzBdLCBvLnZbMV0sIG8udlsyXX0pIHsgKytjdG9yX2NhbGxzOyB9CgkJdmVjIChmbG9hdCB4LGZsb2F0IHksZmxvYXQgeikgOiB2KHt4LHksen0pIHsgKytjdG9yX2NhbGxzOyB9CgoJCX52ZWMoKSB7ICsrZHRvcl9jYWxsczsgfQoKCQkvLyByZXR1cm4gaW5kZXhlZCB2YWx1ZQoJCWZsb2F0IG9wZXJhdG9yW10odWludCBpbmRleCkgY29uc3QgeyByZXR1cm4gdltpbmRleF07IH0KCQkvLyByZXR1cm4gaW5kZXhlZCByZWZlcmVuY2UKCQlmbG9hdCYgb3BlcmF0b3JbXSh1aW50IGluZGV4KSB7IHJldHVybiB2W2luZGV4XTsgfQoKCQl2b2lkIHByaW50KCkgeyBzdGQ6OmNvdXQgPDwgIjwiPDx2WzBdPDwiLCI8PHZbMV08PCIsIjw8dlsyXTw8Ij5cbiI7IH0KCgkJLy8gYXNzaWdubWVudCB0byBhbiBleHByZXNzaW9uCiAgICAgICAgICAgICAgICAvLyBFIG11c3QgaGF2ZSBvcGVyYXRvcltdKHVpbnQpCgkJdGVtcGxhdGUgPGNsYXNzIEU+CgkJdmVjJiBvcGVyYXRvcj0gKGNvbnN0IEUmIHgpCgkJewoJCQlmb3IgKHVpbnQgaT0wOyBpIT0zOyArK2kpICgqdGhpcylbaV0gPSB4W2ldOwoJCQlyZXR1cm4gKnRoaXM7CgkJfQoJfTsKCgoJLy8gYmFzaWMgY2F0Y2gtYWxsIGV4cHJlc3Npb24gbm9kZQoJLy8gTCBhbmQgUiBtdXN0IHByb3ZpZGUgb3BlcmF0b3JbXSh1aW50KQoJLy8gTyBtdXN0IHByb3ZpZGUgc3RhdGljIGZ1bmN0aW9uIGZsb2F0IGV2YWwoZmxvYXQsZmxvYXQpCgl0ZW1wbGF0ZSA8Y2xhc3MgTCwgY2xhc3MgTywgY2xhc3MgUj4KCXN0cnVjdCBleHByZXNzaW9uCgl7CgkJZXhwcmVzc2lvbihjb25zdCBMJiBsLCBjb25zdCBSJiByKQoJCQk6CWwobCksIHIocikgeyB9CgoJCWZsb2F0IG9wZXJhdG9yW10oY29uc3QgdWludCBpbmRleCkgY29uc3QKCQl7CgkJCXJldHVybiBPOjpldmFsKGxbaW5kZXhdLCByW2luZGV4XSk7CgkJfQoKCQljb25zdCBMJiBsOwoJCWNvbnN0IFImIHI7Cgl9OwoKCS8vIHdyYXBzIGEgcmVmZXJlbmNlIHRvIGZsb2F0IGludG8gYW4gb3BlcmF0b3JbXSh1aW50KSBlbnRpdHkKCWNsYXNzIHNjYWxhcgoJewoJCXB1YmxpYzoKCgkJc2NhbGFyKGNvbnN0IGZsb2F0JiB0KSA6IHQodCkgeyB9CgoJCS8vIGFjdCBsaWtlIGFuIGVuZGxlc3MgdmVjdG9yIG9mIHRzCgkJZmxvYXQgb3BlcmF0b3JbXSh1aW50KSBjb25zdCB7IHJldHVybiB0OyB9CgoJCWNvbnN0IGZsb2F0JiB0OwoJfTsKCgkvLyBhbiBvcGVyYXRpb24gZnVuY3Rpb24gb2JqZWN0CglzdHJ1Y3QgcGx1cwoJewoJCXN0YXRpYyBmbG9hdCBldmFsKGNvbnN0IGZsb2F0IGEsIGNvbnN0IGZsb2F0IGIpIHsgcmV0dXJuIGEgKyBiOyB9Cgl9OwoKCS8vIGFueXRoaW5nICsgYW55dGhpbmcKCXRlbXBsYXRlIDxjbGFzcyBMLCBjbGFzcyBSPgoJZXhwcmVzc2lvbjxMLHBsdXMsUj4gb3BlcmF0b3IrKGNvbnN0IEwmIGwsIGNvbnN0IFImIHIpCgl7CgkJcmV0dXJuIGV4cHJlc3Npb248TCxwbHVzLFI+KGwsIHIpOwoJfQoKCS8vIGFueXRoaW5nICsgc2NhbGFyCgl0ZW1wbGF0ZSA8Y2xhc3MgTD4KCWV4cHJlc3Npb248TCxwbHVzLHNjYWxhcj4gb3BlcmF0b3IrKGNvbnN0IEwmIGwsIGNvbnN0IGZsb2F0JiByKQoJewoJCXJldHVybiBleHByZXNzaW9uPEwscGx1cyxzY2FsYXI+KGwsIHIpOwoJfQp9Cgp2b2lkIGRvX3NvbWUoKQp7Cgl1c2luZyBuYW1lc3BhY2UgZXhwcjsKCgl2ZWMgYSgxLDIsMyksIGIoMiwzLDQpLCBjKDMsNCw1KTsKCWEucHJpbnQoKTsgYi5wcmludCgpOyBjLnByaW50KCk7CgoJLy8gd29ya3MKCWEgPSBiICsgYzsKCWEucHJpbnQoKTsKCWFzc2VydCggYS52WzBdID09IDUgJiYgYS52WzFdID09IDcgJiYgYS52WzJdID09IDkgKTsKCgkvLyBkb2VzIG5vdCB3b3JrIC0+IHNlZ2ZhdWx0CglhID0gYiArIDEuZjsKCWEucHJpbnQoKTsKCWFzc2VydCggYS52WzBdID09IDMgJiYgYS52WzFdID09IDQgJiYgYS52WzJdID09IDUgKTsKfQoKaW50IG1haW4oKQp7Cglkb19zb21lKCk7CgoJLy8gY2hlY2sgY3RvciBjYWxscwoJZXhwcjo6cHJpbnRjdG9yKCk7CgogICAgcmV0dXJuIDA7Cn0=