[英]C++11: lambda, currying
我有以下代码。 你能解释一下它是如何工作的吗?
template<typename Function, typename... Arguments>
auto curry(Function func, Arguments... args) {
return [=](auto... rest) {
return func(args..., rest...);
};
}
int main() {
auto add = [](auto x, auto y) {
return x + y;
};
auto add4 = curry(add, 4);
std::cout << add4(3) << '\n'; //output: 7. (Ok)
}
首先,您必须知道curry是什么,或者在您的问题中,这是特定的部分应用情况 (currying与之相关,但略有不同)。
基本上,它意味着使用一定数量的参数来减少函数,以创建另一个函数 ,其中一些参数的值是固定的。
我的例子,原始函数是add(x,y)
,它有两个参数x和y 。 通过将x设置为4来减少函数的arity add,并创建缩减函数add4(y)
例如
add4(y)= add(x,y)其中x = 4
现在如何在您的c ++代码中实现这一目标? 借助可变参数模板 , 可变参数函数和lambda函数 。
从C ++ 11开始, Lambda函数在c ++中。 实质上,它们是动态创建的匿名函数,可以存储在变量中。 您在main()
创建add
作为lambda:
auto add = [](auto x, auto y) {
return x + y;
};
一个人通过模式[] (list-of-arguments) {function-body};
识别lambda [] (list-of-arguments) {function-body};
注: []
是不是总是空的,请参阅“捕捉变量” 有 ,我们会再试试。
现在curry函数的目的是将这些lambdas函数func
和一定数量的值中的一个作为参数,并通过按顺序将值分配给 func
的第一个参数来定义新函数 。
变量 模板参数Arguments... args
允许“ 一定数量的参数 ”机制,它允许使用任意数量的类型作为模板参数调用模板(只要它们被称为编译时)。 所以在我们的例子中,传递的参数是4,因此Arguments... args
将被int
替换,而curry
的实例将接受lambda和int
作为参数。
如果我们看一下curry
的代码,我们看到它本身只是一个lambda函数,(它是一个可变函数 ,就像printf()
),它的唯一目的是在实例化模板时连接其值已经修复的参数。 ( args...
)和那些值作为参数传递给curried函数的那些( rest...
)。
[=]符号是lambda函数的特殊捕获 ,它允许使用函数体中的所有局部变量(这里允许使用args
)。
所以要把它包起来,这是你的main函数中发生的事情:
add
的变量,它包含一个lambda函数 ,接受两个参数并添加它们。 curry(add,4)
您实例化curry
模板。
Function
是add
的类型(一个lambda采用两个int
并返回一个int
) 4
的类型,即int
实例化的curry
函数看起来像这样
curry( (int,int)->(int) func, int arg){
return [=](auto... rest) {return func(arg, rest...);};
}
请注意,由于auto
和模板类型扣除,您永远不会看到这些类型。
然后使用func
= add
和arg
= 4调用此实例
您将此实例化的结果存储在add4
,这现在是一个带有一个参数的lambda。 然后你可以调用add4
with 3作为参数( rest...
是3),然后调用add(4,3)
并返回7。
请注意,从技术上讲,您可以尝试使用多个参数调用add4
,因为add4
函数是一个可变参数函数。 只有当它在调用add
时它没有这些额外参数的位置时,编译器才会失败( 在此处查看 )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.