Il motivo è che le lambda sono oggetti funzione, quindi passandoli a un modello di funzione verrà creata un'istanza di una nuova funzione specifica per quell'oggetto. Il compilatore può quindi banalmente incorporare la chiamata lambda.
Per le funzioni, d'altra parte, si applica il vecchio avvertimento: un puntatore a funzione viene passato al modello di funzione, e tradizionalmente i compilatori hanno molti problemi nell'allineare le chiamate tramite puntatori a funzione. In teoria possono essere incorporati, ma solo se anche la funzione circostante è incorporata.
Ad esempio, considerare il seguente modello di funzione:
template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
Chiamandolo con un lambda come questo:
int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });
Risultati in questa istanza (creato dal compilatore):
template <>
void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) {
for (; begin != end; ++begin)
*begin = f.operator()(*begin);
}
... il compilatore conosce _some_lambda_type::operator ()e può incorporare le chiamate in modo banale. (E invocare la funzione mapcon qualsiasi altra lambda creerebbe una nuova istanza mappoiché ogni lambda ha un tipo distinto.)
Ma quando viene chiamato con un puntatore a funzione, l'istanza appare come segue:
template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
... e qui findica un indirizzo diverso per ogni chiamata a mape quindi il compilatore non può incorporare le chiamate a fmeno che anche la chiamata circostante a mapsia stata incorporata in modo che il compilatore possa risolvere funa specifica funzione.