Вероятно, это связано с тем, что для этого уже существует синтаксис, и цель лямбда-выражений состоит в том, чтобы ввести гораздо более простой синтаксис, охватывающий большинство случаев.Когда вы пытаетесь охватить все случаи (что, если вы хотите, чтобы автоматически сгенерированный функтор наследовал определенный базовый класс?), Вы теряете сравнительные преимущества (простота и краткость) лямбды.
Я действительно не понимаюМне нравится предложенный синтаксис.T
является ключевым словом?Все ли идентификаторы, для которых не удалось найти имя, автоматически превращаются в аргументы типа имени шаблона?Это предотвращает обнаружение орфографических ошибок, что, по мнению IMO, BAD идея:
for_each(c.begin(),c.end(),[](iterater& t) { ++t; });
// programmer misspelled "iterator" and now has a polymorphic lambda, oops
Оно также вводит поведение на расстоянии, если именованный тип вводится в некоторый заголовокфайл где-то, значение внезапно меняется.Также действительно ПЛОХО .
Ну, так как предполагается создать шаблон, мы можем заимствовать существующий синтаксис:
for_each(c.begin(),c.end(),[]template<typename T>(T& t) { ++t; });
Это однозначно и теперь позволяетвведите аргументы шаблона (полезно для принятия массивов по ссылке), но это действительно громоздко.На этом этапе вам лучше писать функтор вручную, это будет намного легче понять.
Однако я думаю, что простой синтаксис возможен при использовании ключевого слова auto
:
for_each(c.begin(),c.end(),[](auto& t) { ++t; });
В следующем разделе неправильно предполагается, что параметр шаблона отображается в типе функтора, а не в его operator()()
:
Но теперь у вас есть проблема, из-за которой for_each
выводитАргумент шаблона typename, а не аргумент шаблона шаблона.Вывод типа невозможен в этом контексте.
В текущем предложении лямбда имеет тип , даже если это не упоминаемый (кроме decltype
) тип.Вам нужно было бы потерять эту функцию, чтобы разместить вывод на сайте вызова.
Пример, показывающий, что проблема не является недостатком лямбда-выражений, это просто не выводимый контекст:
#include <vector>
#include <algorithm>
#include <iterator>
int main(void)
{
using namespace std;
vector<int> a(10);
vector<int> b(10);
vector<int> results;
transform(a.begin(), a.end(), b.begin(), back_inserter(results), min<int>);
}
Параметр типа шаблона для std::min
должен быть указан явно.Лямбды ничем не отличаются от использования существующих функторов в этом отношении.
РЕДАКТИРОВАТЬ: Хорошо, теперь, когда я понимаю, мы не предлагаем, чтобы лямбда генерировала тип функтора шаблона, а единственный тип не функтора шаблона, который осуществляетоператор приложения шаблонной функции (operator()()
), я согласен, что компилятор должен быть в состоянии генерировать такую вещь.Я предлагаю, чтобы использование ключевого слова auto
было бы хорошим простым синтаксисом для запроса этого.
Однако я не очень доволен и auto
.А как насчет лямбд с несколькими параметрами:
[](auto& x, auto& y){ return x + y; }
//becomes
template<typename T1, typename T2>
auto operator()(T1& x, T2& y) -> decltype(x + y) { return x + y; }
Хорошо, это работает достаточно хорошо, но что если нам нужны два параметра, а только один аргумент типа:
[](auto& x, decltype(x)& y){ return x + y; }
//becomes
template<typename T1>
auto operator()(T1& x, T1& y) -> decltype(x + y) { return x + y; }
Кажется, хорошо, но янайти синтаксис, вводящий в заблуждение.Синтаксис предполагает, что параметр типа выводится из первого фактического параметра, а второй параметр приводится к одному и тому же типу, но на самом деле оба фактических параметра считаются равными во время вывода типа.
Возможно, лучше всего, чтобы этот случайбыть ограниченным одним лямбда-параметром для каждого аргумента типа, и если вы хотите что-то более ограниченное, напишите функтор самостоятельно.Мне кажется, это хороший компромисс между гибкостью и мощью против простоты синтаксиса.