Powodem jest to, że lambdy są obiektami funkcyjnymi, więc przekazanie ich do szablonu funkcji utworzy wystąpienie nowej funkcji specjalnie dla tego obiektu. Kompilator może więc w trywialny sposób wbudować wywołanie lambda.
Z drugiej strony, w przypadku funkcji obowiązuje stare zastrzeżenie: wskaźnik funkcji jest przekazywany do szablonu funkcji, a kompilatory tradycyjnie mają wiele problemów z wbudowywaniem wywołań za pomocą wskaźników funkcji. Oni mogą być teoretycznie inlined, ale tylko wtedy, gdy funkcja jest otaczająca inlined również.
Jako przykład rozważ następujący szablon funkcji:
template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
Nazywając to lambdą w ten sposób:
int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });
Wyniki w tej instancji (utworzone przez kompilator):
template <>
void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) {
for (; begin != end; ++begin)
*begin = f.operator()(*begin);
}
… Kompilator zna _some_lambda_type::operator ()
i może wbudowane wywołania do niego w trywialny sposób. (I wywołanie funkcji map
z dowolnego innego lambda by utworzyć nowy instancji z map
ponieważ każdy lambda ma inny typ).
Ale gdy jest wywoływana ze wskaźnikiem funkcji, instancja wygląda następująco:
template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
... i tu f
wskazuje na inny adres dla każdego wywołania map
, a więc kompilator nie może inline wywołania f
chyba otaczający wywołanie map
zostało również inlined tak, że kompilator może rozwiązać f
do jednej konkretnej funkcji.