如何让 lambda 函数成为 class 的朋友?

How to make a lambda function friend of a class?

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

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 };
    }
}

现在我希望该函数与 class 成为朋友,但我找不到实现它的方法。

你不能让 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;
};

如果你真的想在你的调用点有一个无效的(zero-argument)函数,你可以先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)。

How to make a lambda function friend of a class?

你不能。这是一个陷阱 22 问题。


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

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};
}

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

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;} };
}