【问题标题】:closure as argument and return type in C++闭包作为 C++ 中的参数和返回类型
【发布时间】:2019-12-15 11:43:44
【问题描述】:

我很难实现一个返回闭包的类方法,该闭包捕获this(在示例中为Foo::f1)。我们的想法是将其用作Bar 中的一种回调。

第一个障碍是我没有弄清楚如何在usingstatement 中指定闭包类型。

#include <iostream>

class Foo {
 public:
  Foo() = default;
  ~Foo() = default;

  // don't know what the correct type specification is
  //using fptr = [](int)->int;
  //using fptr = int operator()(int);
  //using fptr = int (*)();
  typedef int (*fptr)(int);

  fptr f1(void) {
    return [this](int k)->int { return k * this->x_; };
  }

 private:
  int x_ = 2;
};

class Bar {
 public:
  Bar() = default;
  ~Bar() = default;
  void setfun(Foo::fptr f) { f_ =  f; }
  void callfun() {
    std::cout << "result = " << f_(8) << std::endl;
  }
 private:
  Foo::fptr f_;
};


int main(int, char **) {
  Foo foo;
  Bar bar;
  bar.setfun(foo.f1());
  bar.callfun();
  return 0;
}

vg

【问题讨论】:

标签: lambda callback closures c++17 using


【解决方案1】:

f1 函数标记为返回auto

  auto f1(void) 
  {
    return [this](int k)->int { return k * this->x_; };
  }

然后你可以从Bar类模板,并在实例化时 使用decltype 获取f1 的返回类型:

template<class F>
class Bar {
};

Foo foo;
Bar< decltype( std::declval<Foo>().f1() ) > bar;

因为您将 this 捕获到 lambda,它是非无状态 lambda,不能默认构造,您不能将 F 存储为普通成员变量。 为了避免这个问题,你可以使用智能指针来存储F,例如unique_ptr

template<class F>
class Bar  {
   void setfun(F f) { f_ =  std::make_unique<F>(f); }
   std::unique_ptr<F> f_;
};

完整代码为:

class Foo {
 public:
  Foo() = default;
  ~Foo() = default;

  auto f1(void) 
  {
    return [this](int k)->int { return k * this->x_; };
  }

 private:
  int x_ = 2;
};

template<class F>
class Bar 
{
 public:
  Bar() = default;
  ~Bar() = default;

   void setfun(F f) { f_ =  std::make_unique<F>(f); }

   void callfun() 
   {
     std::cout << "result = " << (*f_)(8) << std::endl;
   }
 private:
  std::unique_ptr<F> f_;
};


int main(int, char **)  {
  Foo foo;
  Bar< decltype( std::declval<Foo>().f1() ) > bar;

  bar.setfun(foo.f1());
  bar.callfun();

Full demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-21
    • 1970-01-01
    相关资源
    最近更新 更多