如何使 lambda 函数成为类的好友

How to make a lambda function friend of a class?

本文关键字:好友 何使 lambda 函数      更新时间:2023-10-16

我试图创建一个在构造函数中作为参数的类lambda函数,我希望这个函数与该类成为朋友。该类的代码如下所示:

using func = std::function<void(void)>;    
class foo
{
public:
    foo(func f)
    {
        this->f = f;
    }
    func f;
private:
    int value_I_want_to_modify; //an int I want to change from the function I've passed in the constructor
}

main()我会写这样的东西:

int main()
{
    //this will give an error because I cannot access private members from outside class
    foo v
    {
        [&v](void) { v.value_I_want_to_modify = 0 };
    }
}

现在我希望该函数与类成为朋友,但我找不到一种方法。

如何使 lambda 函数成为类的朋友?

你不能。这是一个第22条军规的问题。


如果在定义类之前定义 lambda 函数,则无法访问类的成员变量。

using func = std::function<void(void)>;    
class foo;
// Trying to define the lambda function before the class.
// Can't use f.value_I_want_to_modify since foo is not defined yet.
auto lambda_function = [](foo& f) { f.value_I_want_to_modify = 0;}
class foo
{
   public:
      foo(func f)
      {
         this->f = f;
      }
      func f;
   private:
      int value_I_want_to_modify;
};
int main()
{
    foo v{lambda_function};
}

如果在定义类后定义 lambda 函数,则不能使 lambda 函数成为类的友元。

using func = std::function<void(void)>;
class foo
{
   public:
      foo(func f)
      {
         this->f = f;
      }
      func f;
   private:
      int value_I_want_to_modify;
};
int main()
{
   foo f
   {
      // Can't make the lambda function a friend of foo
      // since it cannot be declared before the class definition.
      [&f](void) { f.value_I_want_to_modify = 0;}
   }
}

最简单的解决方法是修改 lambda 函数以接受int&作为参数并修改其值。

#include <functional>
using func = std::function<void(int&)>;
class foo
{
   public:
      foo(func f)
      {
         this->f = f;
         this->f(value_I_want_to_modify);
      }
   private:
      func f;
      int value_I_want_to_modify;
};
int main()
{
   foo v{ [](int& out) { out = 0;} };
}

你不能让一个lambda成为朋友,因为(根据定义)你不能命名它的类型(你需要一个朋友声明)。

你不能随意

std::function朋友,因为你在编写朋友声明时不知道它的值是什么。

正如Jesper所说,你也不能让lambda成为朋友。

你可以做的是在调用函数时将内部状态传递给函数(通过引用)。

如果要公开多个内部成员,则可以将它们包装在一个结构中,以保持参数列表的可管理性。

例如。

class foo
{
public:
    struct state {
        int value;
        // any other internal values here
    };
    foo(std::function<void(state&)> fun) : f(fun) {}
    void run() { f(s); }
private:
    state s;
    std::function<void(state&)> f;
};

如果你真的想要在你的调用站点使用一个空(零参数)函数,你可以先bind参数:

class foo
{
    // ...
    foo(std::function<void(state*)> fun) : f(std::bind(fun, &s)) {}
    void run() { f(); }
private:
    state s;
    std::function<void(void)> f;
};

(注意在第二个版本中,我只是传递了一个指向内部状态的指针以避免reference_wrapper)。