I was looking at the example of expression templates at https://en.wikipedia.org/wiki/Expression_templates. Then I tried to make a simple symbolic expression tree, i.e. to add constants and variables like a + b + 10. So I started with
#include <iostream>
template<typename E>
class Expression {
public:
std::ostream& print(std::ostream& os) const
{
return expression().print(os);
}
E const& expression() const { return static_cast<E const&>(*this); }
};
class Var : public Expression<Var> {
public:
Var(const char name)
: name_(name)
{}
std::ostream& print(std::ostream& os) const
{
return os << name_;
}
private:
const char name_;
};
class Constant : public Expression<Constant> {
public:
Constant(const double value)
: value_(value)
{}
std::ostream& print(std::ostream& os) const
{
return os << value_;
}
private:
const double value_;
};
template<typename E1, typename E2>
class ExpressionSum : public Expression<ExpressionSum<E1,E2>> {
E1 const& u_;
E2 const& v_;
public:
ExpressionSum(E1 const& u, E2 const& v) : u_(u), v_(v)
{
}
std::ostream& print(std::ostream& os) const
{
os << "(";
u_.print(os);
os << " + ";
v_.print(os);
os << ")";
return os;
}
};
template <typename E1, typename E2>
ExpressionSum<E1,E2> operator+(Expression<E1> const& u, Expression<E2> const& v) {
return ExpressionSum<E1, E2>(u.expression(), v.expression());
}
int main() {
Var a('a');
Var b('b');
Constant c(1.0);
auto expr = a + b + c;
expr.print(std::cout);
std::cout << std::endl;
auto expr2 = expr + Constant{2.0};
expr2.print(std::cout);
std::cout << std::endl;
}
The expression expr
is fine, but I cannot reuse expr
to build another expression like expr2
since the temporary ExpressionSum
of a+b
is already destroyed. Is there a way to store these temporaries in the expression?