将lambda表达式传递给lambda参数c ++ 11 [英] Pass lambda expression to lambda argument c++11

查看:214
本文介绍了将lambda表达式传递给lambda参数c ++ 11的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想这样做:

int main()
{
    auto f = [/*some variables*/](/*take lambda function*/)
    {/*something with lambda function*/};

    f([/*other variables*/](/*variables to be decided by f()*/)
    {/*something with variables*/});
}



我知道可以将lambda传递给函数关于λ。
以下工作:

I know that it is possible to pass a lambda to a function, as well as to a lambda. The following works:

int main()
{
    int x=0;
    int y=0;
    auto f = [x,y](double (func)(int)) -> double
    {func(0); return 0.0;};

    f([](int i) -> double
    {return 0.0;});
}

但是下面的方法不起作用添加[x])

But the following does not work (as soon as i change the scope variables to add [x])

int main()
{
    int x=0;
    int y=0;
    auto f = [x,y](double (func)(int)) -> double
    {func(0); return 0.0;}

    f([x](int i) -> double    //[x] does not work
    {return 0.0;});
}

出现错误:

error: function "lambda [](double (*)(int))->double::operator()" cannot be called with the given argument list
        argument types are: (lambda [](int)->double)
        object type is: lambda [](double (*)(int))->double

任何人都有一个想法如何解决这个问题,或绕过它吗?
我使用intel编译器
icpc(ICC)13.1.2 with std = c ++ 11

would anyone have an idea as to how to fix this, or a way around it? I am using the intel compiler icpc (ICC) 13.1.2 with std=c++11

感谢

推荐答案

有几个要澄清的问题。第一个是什么是lambda?

There are a couple of things to clarify regarding your question. The first of which is what is a lambda?

lambda表达式是一个简单的表达式,编译器将生成一个唯一的类型,被命名,同时它将生成一个类型的实例。当你写: [](int i){std :: cout<一世; } 编译器会为你生成一个大致类型:

A lambda expression is a simple expression from which the compiler will generate a unique type that cannot be named, and at the same time it will generate an instance of the type. When you write: [](int i) { std::cout << i; } the compiler will generate a type for you that is roughly:

struct __lambda_unique_name {
   void operator()(int i) const { std::cout << i; }
};

如您所见,它实现 operator()作为一个 const 成员函数。如果lambda做了任何捕获,编译器将生成代码来捕获值/引用。

As you can see, it is not a function, but a type that implements operator() as a const member function. If the lambda did any capture, the compiler would generate code to capture the value/references.

作为一个角的情况,对于像上面的lambda,被捕获,语言允许从lambda类型到具有 operator()(减去 this part),所以上面的lambda可以隐式转换为一个指向 int 的函数的指针,并且不返回:

As a corner case, for lambdas like the above, where there is no state being captured, the language allows for a conversion from the lambda type to a pointer to function with the signature of the operator() (minus the this part), so the lambda above can be implicitly converted to a pointer to function taking int and returning nothing:

void (*f)(int) = [](int i) { std::cout << i; }

现在已经说明了基础知识,在代码中有这个lambda:

Now that the basics have been stated, in your code you have this lambda:

auto f = [x,y](double (func)(int)) -> double {func(0); return 0.0;};

函数参数的规则(也适用于lambdas)确定参数不能是类型 ,因此lambda的参数衰减为指向函数的指针(与类型数组的参数衰减为指针类型的方式相同):

The rules for parameters to functions (that also apply to lambdas) determine that an argument cannot be of type function, so the argument to the lambda decays to a pointer to function (in the same way that an argument of type array decays to a pointer type):

auto f = [x,y](double (*func)(int)) -> double {func(0); return 0.0;};

稍后,您尝试传递一个具有捕获作为参数的lambda。因为有一个捕获,特殊规则不适用,并且lambda不能转换为指向函数的指针,导致您看到的编译器错误。

At a later point you are trying to pass a lambda that has a capture as an argument. Because there is a capture, the special rule does not apply and the lambda is not convertible to a pointer to function yielding the compiler error that you see.

在当前标准你可以去两种方式之一。您可以使用type-erasure从签名中删除可调用实体的确切类型:

In the current standard you can go one of two ways. You can use type-erasure to remove the exact type of the callable entity from the signature:

auto f = [x,y](std::function<double(int)> func) -> double {func(0); return 0.0;};

因为 std :: function< double(int)> code>可以用具有适当签名的任何可调用实体来初始化,这将接受下面的代码中的lambdas,代价是类型擦除,通常意味着动态分配和动态分派。

Because a std::function<double(int)> can be initialized with any callable entity with the appropriate signature, this will accept the lambdas in the code below, at the cost of type-erasure that usually implies a dynamic allocation and dynamic dispatch.

或者,您可以删除语法糖并手动滚动第一个lambda对等项,但使其通用。在这种情况下,lambda是简单的,这可能是一个有效的选项:

Alternatively, you can drop the syntactic sugar and roll the first lambda equivalent manually, but make it generic. In this case, where the lambda is simple this could be a valid option:

struct mylambda {
   template <typename F>
   double operator()(F fn) const {
      fn(0); return 0.0;
   }
} f;
// then use the non-lambda as you tried:
f([x](int i) -> double {return 0.0;});

最后,如果你足够耐心,可以等待C ++ 14, ,它还没有被批准),将支持简单化上述类的创建的多态lambdas

Finally, if you are patient enough, you can wait for C++14, where (most probably, it has not yet been ratified) there will be support for polymorphic lambdas which simplify the creation of the above class:

auto f = [](auto fn) { fn(0.0); return 0.0; } // unrolls to 'mylambda' above

这篇关于将lambda表达式传递给lambda参数c ++ 11的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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