传递lambda作为参数 - 通过引用或值? [英] passing lambda as argument - by reference or value?

查看:104
本文介绍了传递lambda作为参数 - 通过引用或值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个模板代码,它将一个函数作为参数,并在执行一些处理后执行它。尽管其他人可能会传递该函数一个lambda,一个函数指针或甚至一个 std :: function ,但它主要是为lambda(而不是我禁止其他格式)。我想问一下我应该怎样服用这种lambda - 按价值?引用?或者别的什么。



示例代码 -

  #include <的iostream> 
#include< functional>
使用namespace std;

模板< typename Functor>
void f(Functor functor)
{
functor();
}

void g()
{
cout<< 从函数调用;
}

int main()
{
int n = 5;

f([](){cout <<从Temp Lambda \\\
调用;});

f([&](){cout<<从捕获温度Lambda \\\
调用; ++ n;});

auto l = [](){cout<< 从存储的Lambda \\\
调用;};
f(l);

std :: function< void()> funcSTD = [](){cout<< 从std :: Function \\\
调用; };
f(funcSTD);

f(g);
}

在上面的代码中,我可以选择其中的一种 -

 模板< typename Functor> 
void f(Functor functor)

template< typename Functor>
void f(Functor& functor)

模板< typename Functor>
void f(Functor&& functor)

更好的方法是什么?为什么?是否有任何限制?

解决方案

作为一个可能的缺点,请注意,如果lambda不可复制。如果你能摆脱它,通过复制就好了。

举个例子:

  #包括<存储器GT&; 
#include< utility>

模板< typename F>
void g(F&& f){
std :: forward< F>(f)();
}

模板< typename F>
void h(F f){
f();


int main(){
auto lambda = [foo = std :: make_unique< int>()](){};

g(lambda);
// h(lambda);



$ b $ p
$ b

在上面的代码片段中, lambda 不可复制,因为 foo 。由于 std :: unique_ptr 的拷贝构造函数被删除,所以它的拷贝构造函数被删除。

另一方面, code> F&& f
同时接受左值和右值引用作为转发引用以及常量引用。

换句话说,如果你想要重复使用同一个lambda作为参数不止一次,如果函数通过拷贝获取对象并且必须移动它,因为它不可复制(不过,实际上,您可以,这是一个包装的问题它在一个lambda中通过引用捕获外层)。


I've written a template code that takes a functor as an argument and after some processing, executes it. Although someone else might pass that function a lambda, a function pointer or even an std::function but it is meant primarily for lambda(not that I ban other formats). I want to ask how should I take that lambda - by value? by reference? or something else.

Example code -

#include <iostream>
#include <functional>
using namespace std;

template<typename Functor>
void f(Functor functor)
{
    functor();
}

void g()
{
    cout << "Calling from Function\n";
}

int main() 
{
    int n = 5;

    f([](){cout << "Calling from Temp Lambda\n";});

    f([&](){cout << "Calling from Capturing Temp Lambda\n"; ++n;});

    auto l = [](){cout << "Calling from stored Lambda\n";};
    f(l);

    std::function<void()> funcSTD = []() { cout << "Calling from std::Function\n"; };
    f(funcSTD);

    f(g);
}

In above code, I've a choice of making it either of these -

template<typename Functor>
    void f(Functor functor)

template<typename Functor>
    void f(Functor &functor)

template<typename Functor>
    void f(Functor &&functor)

What would be the better way and why? Are there any limitations to any of these?

解决方案

As a possible drawback, note that passing by copy could not work if the lambda isn't copyable. If you can get away with it, passing by copy is just fine.
As an example:

#include<memory>
#include<utility>

template<typename F>
void g(F &&f) {
    std::forward<F>(f)();
}

template<typename F>
void h(F f) {
    f();
}

int main() {
    auto lambda = [foo=std::make_unique<int>()](){};

    g(lambda);
    //h(lambda);
}

In the snippet above, lambda isn't copyable because of foo. Its copy constructor is deleted as a consequence of the fact that the copy constructor of a std::unique_ptr is deleted.
On the other side, F &&f accepts both lvalue and rvalue references being it a forwarding reference, as well as const references.
In other terms, if you want to reuse the same lambda as an argument more than once, you cannot if your functions get your object by copy and you must move it for it's not copyable (well, actually you can, it's a matter of wrapping it in a lambda that captures the outer one by reference).

这篇关于传递lambda作为参数 - 通过引用或值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆