繁体   English   中英

C ++ 11:lambda,currying

[英]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) ,它有两个参数xy 通过将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函数中发生的事情:

  1. 您创建一个名为add的变量,它包含一个lambda函数 ,接受两个参数并添加它们。
  2. 当您调用curry(add,4)您实例化curry模板。
    • 第一个模板参数Functionadd的类型(一个lambda采用两个int并返回一个int
    • 第二个可变参数只包含一种类型: 4的类型,即int

实例化的curry函数看起来像这样

curry( (int,int)->(int) func, int arg){
    return [=](auto... rest) {return func(arg, rest...);};
}

请注意,由于auto和模板类型扣除,您永远不会看到这些类型。

  1. 然后使用func = addarg = 4调用此实例

  2. 您将此实例化的结果存储在add4 ,这现在是一个带有一个参数的lambda。 然后你可以调用add4 with 3作为参数( rest...是3),然后调用add(4,3)并返回7。

请注意,从技术上讲,您可以尝试使用多个参数调用add4 ,因为add4函数是一个可变参数函数。 只有当它在调用add时它没有这些额外参数的位置时,编译器才会失败( 在此处查看

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM