La cosa che in assoluto costa meno è passare un functore come parametro template; in tal caso, il compilatore ha il "quadro completo", sa subito chi verrà chiamato e può fare inlining di tutto quel che crede necessario.

In alternativa, in genere puntatori a funzione, puntatori a funzione membro e funzioni virtuali costano poco di più; il costo del branch misprediction in genere è molto basso se si continua a chiamare la stessa funzione (il branch predictor impara rapidamente dove deve effettivamente andare), il costo principale è rappresentato dalla mancata opportunità di inlining, che, per funzioni molto piccole e ben espandibili in linea, può essere considerevole.

std::function, infine, è inevitabilmente "costosa", dato che, per ottenere l'effetto della type erasure, fa uso di doppia indirezione con di mezzo chiamate virtuali.