Suppose I have a class that evaluates some computationally intensive function:
class Value
{
private:
int eval()
{
mCached = ExpensiveOperation();
return mCached;
}
static int mCached;
};
Now suppose that Value
is actually some template expression, like Plus<1, Multiply<2, 3>>
or something to that effect. It may itself be nested and might appear multiple times as part of a larger expression.
I don't know what the expression is, but I do know, based on its position in the expression, which instantiation of it (if there are multiple instantiations of exactly the same type) will be evaluated first.
I want to memoize the result for subsequently instantiated types, such that they are not evaluated more than once each time the expression is evaluated.
The easy way of achieving this is store the cached results in some sort of hash_map
or to use singletons which check whether a static member is evaluated, but heap allocation and lookups are expensive, plus we already know the types at compile time and we know which instance is going to be evaluated first, so why not prepare the memoization at compile time as well?
What if we had something like a Cached
type, which simply pulled the result from the first class of the same type:
template <typename Expression>
class Cached
{
int eval()
{
return Expression::mCached; // cheap!
}
};
The problem is that I now have to remember to place Cached
everywhere if an expression is repeated!
// Inefficient but nice expression:
Add<Multiply<2, 3>, Multiply<2, 3>>
// Efficient but ugly expression
Add<Multiply<2, 3>, Cached<2, 3>>;
How can I create an expression that looks like the "inefficient but nice expression" yet still automatically generates a Cached
type?