【问题标题】:How to make a recursive lambda function that takes 2 arguments not 1?如何制作一个接受 2 个参数而不是 1 的递归 lambda 函数?
【发布时间】:2019-07-26 07:56:40
【问题描述】:

我已经知道如何制作一个带有一个参数的递归 lambda 函数,例如计算一个数字的阶乘,但是我尝试使用 lambda 制作一个递归幂函数(作为一种实践),但是在函数中采用 2 个参数会导致错误

这是代码:

std::function <int(int)> power = [&](int a, int n)
{
    return (n<=1) ? a : a*power(a, n-1);
};

return (n&lt;=1) ? a : a*power(a, n-1); 这一行给出了这些错误:

error:   no match for call to '(std::function<int(int)>) (int&, int)'
note:   candidate: _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int}]
note:   candidate expects 1 argument, 2 provided

【问题讨论】:

    标签: c++ c++11 recursion lambda std-function


    【解决方案1】:

    你必须使用

    std::function <int(int, int)> power = [&](int a, int n) { ... }
    

    让函数使用两个参数。

    改进建议:

    确保正确处理n = 0

    使用

    return (n <= 1) ? a : a*power(a, n-1);
    

    不对。当使用n = 0 调用函数时,您将返回a

    使用

    return (n == 0) ? 1 : a*power(a, n-1);
    

    unsigned int 用于n

    std::function <int(int, unsigned int)> power = [&](int a, unsigned int n) { ... }
    

    那么,您就不必担心函数会被调用时使用 n 的负值。


    功能齐全

    std::function <int(int, unsigned int)> power = [&](int a, unsigned int n)
    {
        return (n == 0) ? 1 : a*power(a, n-1);
    };
    

    【讨论】:

      【解决方案2】:

      也许

      std::function <int(int, int)> power = [&](int a, int n) ....
      // ...................^^^^^
      

      ?

      我的意思是:如果power 是一个std::function,它使用接收两个整数的 lambda 进行初始化,并且用作接收两个整数的函数,那么可能需要声明它接收两个整数,而不仅仅是一个。

      【讨论】:

      • 是的,它可以工作,谢谢,但为什么我不能简单地将 power 声明为 auto ?
      • @MohamedSaad - 在这种情况下不是(递归 lambda),因为 lambda 本身需要知道 power 的类型;使用auto,您进入一个循环,其中功率lambda 需要知道power 的类型,而power 需要知道lambda 的类型。
      【解决方案3】:

      您的递归 lambda 遇到了问题;它需要存在创建它的确切变量,或者它是 UB 调用它。

      auto ycomb = [](auto&&f){ return [f=f](auto&&...args){ return f(f, decltype(args)(args)...); }; };
      

      这个小玩具修复了这个错误。

      auto power = ycomb( [](auto&& self, int a, unsigned int n)->int
      {
        return (n==0) ? 1 : a*self(self, a, n-1);
      });
      

      那里。

      ycomb 是 ycombinator。很有名。

      这个power 可以被复制,并且可以安全地超过其构造范围。

      如果你不喜欢self(self, args...),你可以重用 ycombinator 来制作它:

      auto ycomb0 = [](auto&&f){
        return [=](auto&&...args){
          return f(f, decltype(args)(args)...);
        };
      };
      auto ycombx_ref = [](auto&& r, auto&& f) {
          return [&r, f](auto&&...args) {
              return f( r(r, f), decltype(args)(args)... );
          };
      };
      auto ycomb = ycomb0( ycombx_ref );
      

      现在传递给 lambda 的 self 本身不需要传递 self:

      auto power = ycomb( [](auto&& self, int a, unsigned int n)->int
      {
        return (n==0) ? 1 : a*self(a, n-1);
      });
      

      Live example.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-03-05
        • 1970-01-01
        • 2013-04-19
        • 1970-01-01
        • 1970-01-01
        • 2020-12-29
        • 1970-01-01
        相关资源
        最近更新 更多