c ++ 0x:通过引用接收lambda作为参数的正确方法

lur*_*her 69 c++ lambda function-parameter function-prototypes c++11

定义int->int通过引用接收lambda参数的函数的正确方法是什么?

void f(std::function< int(int) >& lambda);
Run Code Online (Sandbox Code Playgroud)

要么

void f(auto& lambda);
Run Code Online (Sandbox Code Playgroud)

我不确定最后一种形式是否是合法的语法.

还有其他方法来定义lambda参数吗?

bdo*_*lan 74

你不能有auto参数.你基本上有两个选择:

选项#1:std::function按照您的使用进行操作.

选项#2:使用模板参数:

template<typename F>
void f(F &lambda) { /* ... */}
Run Code Online (Sandbox Code Playgroud)

在某些情况下,选项#2可能更有效,因为它可以避免嵌入式lambda函数对象的潜在堆分配,但只有在f可以作为模板函数放置在头中时才可能.与任何模板一样,它也可能会增加编译时间和I-cache占用空间.请注意,它也可能没有效果,就好像lambda函数对象足够小,它可以在std::function对象中内联表示.

  • 这句话,_"如果lambda函数对象足够小,它可能在`std :: function`对象中内联表示"_是误导性的.Lambdas始终可用于内联(编译器当然可以选择不使用).`std :: function`实现通常使用小对象优化来避免堆分配.如果lambda具有足够小的_capture list_,它将被存储在`std :: function`中而不使用堆.除此之外,lambda的大小没有任何实际意义. (5认同)
  • @bdonlan:顺便说一句,为什么在`void f(F&lambda)`中有`&`? (2认同)
  • @bdonlan:但const&假设lambda的成员(按值捕获)无法更改.这可能不是用户想要的. (2认同)
  • @bdonlan已经有一段时间了,但是作为非const引用传递不允许在函数调用中构造临时lambda.这里的r值参考最好. (2认同)

Naw*_*waz 34

我会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 
}
Run Code Online (Sandbox Code Playgroud)

输出:

500
1000
100
Run Code Online (Sandbox Code Playgroud)

演示:http://www.ideone.com/EayVq


Pud*_*dle 25

我知道已经 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;});
}
Run Code Online (Sandbox Code Playgroud)

哪些输出:

foo
lambda 1
Run Code Online (Sandbox Code Playgroud)

不需要模板或 std::function

  • 这仅限于可以衰减为函数指针的 lambdas(没有捕获的 lambdas),并且还需要指定精确的签名(尽管与 `std::function` 情况相同),而模板化版本没有这个限制。 (24认同)
  • 非常感谢您! (2认同)

Ale*_*nov 12

从 C++ 20 开始,

void f(auto& lambda);
Run Code Online (Sandbox Code Playgroud)

实际上有效(这是一个缩写的函数模板):

当占位符类型( 或autoConcept auto出现在函数声明或函数模板声明的参数列表中时,该声明声明了一个函数模板,并且为每个占位符发明了一个模板参数,并将其附加到模板参数列表中

它完全相当于 @bdonlan 答案中的选项 2:

template<typename F>
void f(F &lambda) { /* ... */}
Run Code Online (Sandbox Code Playgroud)

  • 正如稍微提到的,根据“f()”的需要用一些概念来约束 F 可能会更好 (2认同)