在lambda函数中使用auto
#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
不应该用在lambdaexpression式中?
这工作:
std::for_each( v.begin(), v.end(), []( int it ) { foo( it+5 ); } );
为什么使用auto关键字的版本不起作用?
auto关键字不能用作函数参数的types。 如果你不想在lambda函数中使用实际的types,那么你可以使用下面的代码。
for_each(begin(v), end(v), [](decltype(*begin(v)) it ){ foo( it + 5); });
Herb Sutter在一次采访中对此进行了简要的讨论。 对auto
参数的需求实际上和要求任何函数都可以用auto
是一样的:
auto add(auto a, auto b) -> decltype(a + b) { return a + b; }
但是请注意,这不是一个真正的函数,而是一个模板函数,类似于:
template <typename S, typename T> auto add(S a, T b) -> decltype(a + b) { return a + b; }
所以你基本上要求一个设施,通过改变它的参数来把任何函数变成一个模板。 由于模板是C ++types系统中非常不同的一种实体(思考所有模板的特殊规则,比如两阶段查找和推演),这将是一个彻底的devise变革,带来不可预见的后果,很快就会在标准中出现。
C ++ 14允许使用auto声明lambda函数(通用lambda函数)参数。
auto multiply = [](auto a, auto b) {return a*b;};
在编译器甚至可以实例化std::for_each
之前,需要知道lambda的types。 另一方面,即使理论上可能,只有在函数被调用的情况下, for_each
被实例化之后,才能推导出该auto
。
如果可能的话,忘记for_each
,并使用基于范围的for循环更简单:
for (int it : v) { foo(it + 5); }
这也应该很好地处理auto
(和auto&
和const auto&
)。
for (auto it : v) { foo(it + 5); }