Использование auto в лямбда-функции - PullRequest
39 голосов
/ 10 октября 2011
#include <vector>
#include <algorithm>

void foo( int )
{
}

int main()
{
  std::vector< int > v( { 1,2,3 } );

  std::for_each( v.begin(), v.end(), []( auto it ) { foo( it+5 ); } );
}

При компиляции приведенный выше пример запускает вывод ошибки следующим образом:

h4.cpp: In function 'int main()':
h4.cpp:13:47: error: parameter declared 'auto'
h4.cpp: In lambda function:
h4.cpp:13:59: error: 'it' was not declared in this scope

Означает ли это, что ключевое слово auto не должно использоваться в лямбда-выражениях?

Это работает:

std::for_each( v.begin(), v.end(), []( int it ) { foo( it+5 ); } );

Почему не работает версия с ключевым словом auto?

Ответы [ 4 ]

67 голосов
/ 10 октября 2011

ключевое слово auto не работает как тип для аргументов функции.Если вы не хотите использовать фактический тип в лямбда-функциях, вы можете использовать приведенный ниже код.

 for_each(begin(v), end(v), [](decltype(*begin(v)) it ){
       foo( it + 5);         
 });
20 голосов
/ 16 июля 2015

C ++ 14 позволяет объявлять параметры лямбда-функции (универсальной лямбда-функции) с помощью auto.

auto multiply = [](auto a, auto b) {return a*b;};

Подробнее: http://en.cppreference.com/w/cpp/language/lambda

20 голосов
/ 10 октября 2011

Это кратко обсуждалось Хербом Саттером во время интервью. Ваше требование к auto аргументам фактически ничем не отличается от требования, что любая функция должна быть объявлена ​​с auto, например:

auto add(auto a, auto b) -> decltype(a + b) { return a + b; }

Тем не менее, обратите внимание, что на самом деле это вовсе не функция, а скорее функция template , родственная:

template <typename S, typename T>
auto add(S a, T b) -> decltype(a + b) { return a + b; }

Таким образом, вы, по сути, запрашиваете средство для превращения любой функции в шаблон путем изменения ее аргументов. Поскольку шаблоны - это совсем другой вид сущности в системе типов C ++ (подумайте обо всех специальных правилах для шаблонов, таких как двухфазный поиск и дедукция), это будет радикальным изменением дизайна с непредвиденными последствиями, что, безусловно, скоро будет в стандарте.

4 голосов
/ 10 октября 2011

Тип лямбды должен быть известен еще до того, как компилятор сможет создать экземпляр std::for_each. С другой стороны, даже если теоретически это возможно, то auto может быть выведено только после того, как был создан экземпляр for_each, увидев, как вызывается функтор.

Если это вообще возможно, забудьте о for_each и используйте основанные на диапазоне значения для циклов, которые намного проще:

for (int it : v) { 
   foo(it + 5); 
}

Это также должно хорошо справляться с autoauto& и const auto&).

for (auto it : v) { 
   foo(it + 5); 
}
...