将lambda表达式传递给lambda参数c ++ 11 [英] Pass lambda expression to lambda argument 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屋!