在Lambda中捕获类方法

时间:2019-06-21 21:57:54

标签: c++ lambda c++17

我的课堂上有几种方法。我希望一个方法中的lambda调用该类的另一个方法。但是我不想捕获this以便限制lambda可以访问的内容的范围。这可能吗?

我尝试将方法捕获为[&method = Class::my_method]或它的变体,但是我缺少一些东西。

#include <iostream>

class Hello
{
public:

  double test_lambda(const double in)
  {
      // If I capture `this` instead, then this works fine
      const auto a_lambda = [add_number = this->add_number](const double in)
      {
        return add_number(in);  
      };
      return a_lambda(in);
  }

private:

  double add_number(const double in)
  {
      return in + 2.0;
  }

};

int main()
{
    Hello h;
    std::cout << "Hello World: " << h.test_lambda(4.0); // Expect 6
    return 0;
}

我希望我可以捕获这样的方法,但不确定是否可行。

我要基于编码首选项来限制lambda访问的原因。例如,如果我想让lambda突变一个类的成员,我可以做

another_lambda = [this](){
m_value_one = 1.0;
m_value_two = 2.0;
// This has access to other members
}

或者限制lambda可以突变的内容,我可以这样做:

another_lambda = [&value_one = this->m_value_one, &value_two = this->m_value_two](){
value_one = 1.0;
value_two = 2.0;
// This does not have access to other members
}

帖子询问是否可以使用类方法完成相同的操作,但似乎不能。

1 个答案:

答案 0 :(得分:1)

捕获并使用指向成员函数的指针

成员函数不是一流的对象,这意味着您不能分配给变量。与此最接近的事情是将指向成员函数的指针分配给变量,但是要调用指向成员函数的指针,还需要具有指向原始类的指针:

#include <iostream>

class Hello
{
   public:
    double test_lambda(double in)
    {
        auto a_lambda = [add_number = &Hello::add_number, this](double in) {
            // This is how we call a pointer to a member function
            return (this->*add_number)(in);
        };
        return a_lambda(in);
    }

   private:
    double add_number(double in) { return in + 2.0; }
};

int main()
{
    Hello h;
    std::cout << "Hello World: " << h.test_lambda(4.0); // Expect 6
    return 0;
}

更简单的解决方案-通过引用捕获

我们可以通过引用捕获当前的类,这使您可以在没有任何限定符的情况下使用add_number

#include <iostream>

class Hello
{
   public:
    double test_lambda(double in)
    {
        auto a_lambda = [&](double in) {
            // add_number can be called normally
            return add_number(in);
        };
        return a_lambda(in);
    }

   private:
    double add_number(double in) { return in + 2.0; }
};

int main()
{
    Hello h;
    std::cout << "Hello World: " << h.test_lambda(4.0); // Expect 6
    return 0;
}