通过引用定义接收int->int
lambda参数的函数的正确方法是什么?
void f(std::function< int(int) >& lambda);
或
void f(auto& lambda);
我不确定最后一种形式是否是合法的语法。
还有其他方法可以定义lambda参数吗?
答案 0 :(得分:68)
您不能拥有auto
参数。你基本上有两个选择:
选项#1:如您所示使用std::function
。
选项#2:使用模板参数:
template<typename F>
void f(F &lambda) { /* ... */}
在某些情况下,选项#2可能更有效,因为它可以避免嵌入式lambda函数对象的潜在堆分配,但只有在f
可以作为模板放在标头中时才可能功能。与任何模板一样,它也可能会增加编译时间和I-cache占用空间。请注意,它也可能没有效果,就好像lambda函数对象足够小,可以在std::function
对象中以内联方式表示。
答案 1 :(得分:32)
我会将template
用作:
template<typename Functor>
void f(Functor functor)
{
cout << functor(10) << endl;
}
int g(int x)
{
return x * x;
}
int main()
{
auto lambda = [] (int x) { cout << x * 50 << endl; return x * 100; };
f(lambda); //pass lambda
f(g); //pass function
}
输出:
500
1000
100
答案 2 :(得分:3)
从 C++ 20 开始,
void f(auto& lambda);
实际上有效(它是一个 abbreviated function template):
<块引用>当占位符类型(auto
或 Concept auto
)出现在函数声明或函数模板声明的参数列表中时,该声明声明了一个函数模板,并为每个函数模板声明了一个发明的模板参数占位符附加到模板参数列表
它与@bdonlan 的答案中的选项 2 完全相同:
template<typename F>
void f(F &lambda) { /* ... */}
答案 3 :(得分:1)
void f(auto& lambda);
这很接近。实际编译的是:
#include <cassert>
/*constexpr optional*/ const auto f = [](auto &&lambda)
{
lambda();
lambda();
};
int main()
{
int counter = 0;
f([&]{ ++counter; });
assert(counter == 2);
}
答案 4 :(得分:0)
我知道已经有7年了,但这是没有其他人提到的方式:
void foo(void (*f)(int)){
std::cout<<"foo"<<std::endl;
f(1); // calls lambda which takes an int and returns void
}
int main(){
foo([](int a){std::cout<<"lambda "<<a<<std::endl;});
}
哪个输出:
foo
lambda 1
不需要模板或std :: function