Supponiamo che abbia una classe che valuti alcune funzioni di calcolo intensivo:
class Value
{
private:
int eval()
{
mCached = ExpensiveOperation();
return mCached;
}
static int mCached;
};
Supponiamo ora che Value
sia effettivamente un'espressione di modello, come Plus<1, Multiply<2, 3>>
o qualcosa di simile. Può essere annidato e potrebbe apparire più volte come parte di un'espressione più grande.
Non so quale sia l'espressione, ma so do , in base alla sua posizione nell'espressione, che la sua istanza (se ci sono più istanze esattamente dello stesso tipo) essere valutato prima.
Voglio memoizzare il risultato per i tipi successivamente istanziati, in modo che non vengano valutati più di una volta ogni volta che viene valutata l'espressione.
Il modo facile per ottenere questo è memorizzare i risultati nella cache in una sorta di hash_map
o usare singleton che controllano se un membro statico è valutato, ma l'allocazione e le ricerche dell'heap sono costose, oltre a conosciamo già i tipi in fase di compilazione e sappiamo quale istanza verrà valutata per prima, quindi perché non preparare la memoizzazione anche in fase di compilazione?
Che cosa succede se abbiamo avuto qualcosa come un tipo Cached
, che ha semplicemente tirato il risultato dalla prima classe dello stesso tipo:
template <typename Expression>
class Cached
{
int eval()
{
return Expression::mCached; // cheap!
}
};
Il problema è che ora devo ricordare di posizionare Cached
ovunque se viene ripetuta un'espressione!
// Inefficient but nice expression:
Add<Multiply<2, 3>, Multiply<2, 3>>
// Efficient but ugly expression
Add<Multiply<2, 3>, Cached<2, 3>>;
Come posso creare un'espressione che assomigli all '"inefficiente ma bella espressione" e tuttavia genera automaticamente un tipo Cached
?