La raison en est que les lambdas sont fonction des objets afin de les transmettre à un modèle de fonction pour instancier une nouvelle fonction spécifiquement pour cet objet. Le compilateur peut donc trivialement inline le lambda appel.
Pour les fonctions, d'autre part, la vieille mise en garde s'applique: une fonction de pointeur est transmis à la fonction de modèle, et les compilateurs, traditionnellement, ont beaucoup de problèmes d'inlining des appels via des pointeurs de fonction. Ils peuvent théoriquement être inline, mais seulement si l'environnement de la fonction est incorporé.
Par exemple, considérons la fonction suivante template:
template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
Appelant avec un lambda comme ceci:
int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });
Les résultats de cette instanciation (créé par le compilateur):
template <>
void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) {
for (; begin != end; ++begin)
*begin = f.operator()(*begin);
}
... le compilateur connaît _some_lambda_type::operator ()
et peut inline appels à trivialement. (Et de l'invocation de la fonction map
avec tout les autres lambda de créer une nouvelle instanciation d' map
depuis chaque lambda a un type distinct.)
Mais lorsqu'elle est appelée avec un pointeur de fonction, l'instanciation se fait comme suit:
template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
... et ici, f
de points à une adresse différente pour chaque appel à l' map
, et donc le compilateur ne peut pas inline appels d' f
moins que les environs appel à l' map
a également été insérée pour que le compilateur puisse résoudre f
à une fonction spécifique.