Here is a simple example, with a "Vect" of three doubles and an
imaginary operation "*wedge*" that takes two Vects and returns a new
Vect. The details of the operation don't matter - that's your job!
First, a simple class and operation with traditional function-like
syntax for using the operation:
class Vect {
private :
double vs_[3];
friend Vect wedge_product(const Vect &a, const Vect &b);
};
Vect wedge_product(const Vect &a, const Vect &b);
Vect test1(const Vect &a, const Vect &b, const Vect &c) {
Vect ab = wedge_product(a, b);
Vect abc = wedge_product(ab, c);
return abc;
}
Then we make a class for the "wedge" object. This has no data or
operations in itself - it exists just to provide overloads to the *
operator, and to hold an intermediary proxy class Wedge::ProductHelper.
This class holds a reference to a Vect and exists to provide another
overload to the * operator, this time passing its reference and the
other operand on to the real wedge_product function:
class Wedge {
class ProductHelper {
public:
const Vect& v_;
ProductHelper(const Vect& v) : v_(v) {}
};
friend Vect operator*(Wedge::ProductHelper w, const Vect& a);
friend Wedge::ProductHelper operator*(const Vect& a, Wedge);
};
const Wedge wedge;
inline Vect operator*(Wedge::ProductHelper w, const Vect& a) {
return wedge_product(a, w.v_);
}
inline Wedge::ProductHelper operator*(const Vect &a, Wedge) {
return Wedge::ProductHelper(a);
}
Now we can use the code like this:
Vect test2(const Vect &a, const Vect &b, const Vect &c) {
return a *wedge* b *wedge* c;
}
As far as the language is concerned, this is handled by taking "a" and
the "wedge" object and applying operator *, giving a
Wedge::ProductHelper that holds "a". This is is then used as a parameter
to another operator * along with b, and that overload leads to a call of
the real function wedge_product, returning a new vector ("ab" from the
first test function). The process is then run again to multiply in "c".
Your challenge now is:
1) Get all the boiler-plate in templates.
2) Make sure everything that can be hidden from public use, is hidden.
3) Turn it all into expression templates for run-time efficiency.