Ответ 1
Лямбда - это функтор, просто определяемый коротким синтаксисом.
Проблема заключается в том, что этот синтаксис ограничен. Это не всегда позволяет вам решать проблему наиболее эффективным и гибким способом - или вообще. До С++ 14, operator()
не мог даже быть шаблоном.
Кроме того, лямбда имеет ровно один operator()
. Вы не можете предоставить несколько перегрузок, чтобы различать, скажем, типы аргументов:
struct MyComparator
{
bool operator()( int a, int b ) const {return a < b;}
bool operator()( float a, float b ) const {return /*Some maths here*/;}
};
.. или значение категории аргумента объекта (т.е. вызывающего объекта замыкания). Вы также не можете определять специальные функции-члены, включая конструкторы и деструкторы - что, если функтор должен отвечать за ресурсы?
Другая проблема с лямбдами заключается в том, что они не могут быть рекурсивными. Конечно, нормальные функции (включая операторные функции) могут быть.
Также учтите, что lambdas не могут использовать в качестве компараторов для ассоциативных контейнеров или удалений для интеллектуальных указателей: вы не можете напрямую передать тип закрытия в качестве аргумента шаблона и должны построить элемент контейнера из другого объекта-закрытия. (Типы Closure не имеют конструктора по умолчанию!). Для блока-области map
, который не слишком много хлопот:
auto l = [val] (int a, int b) {return val*a < b;};
std::map<int, int, decltype(l)> map(l);
Теперь, что произойдет, если ваш map
является членом данных? Какой шаблонный аргумент, какой инициализатор в списке инициализации конструкторов? Вам придется использовать другой статический член данных, но поскольку вы должны определить его вне определения классов, которое, возможно, является уродливым.
Подводя итог: Lambdas не полезны для более сложных сценариев, потому что они не были созданы для них. Они обеспечивают короткий и сжатый способ создания простых функциональных объектов для соответствующих простых ситуаций.