【问题标题】:Lambda as "member" when class instance is captured捕获类实例时将 Lambda 作为“成员”
【发布时间】:2021-05-05 22:15:17
【问题描述】:

问题标题可能不是最清楚的,但这里是解释:

基本上我想调用一个传递 lambda 的成员函数,并且我想从 lambda 访问类成员,就像 lambda 本身是一个类成员一样

我想出了这个代码,它按预期工作,但不完全符合我的要求。

#include <iostream>

class MyClass
{
  int member = 123;

public:
  void SomeFunction()
  {
    std::cout << "SomeFunction()\n";
  }

  template<typename Functor>
  void Test(Functor functor, int val)
  {
    functor();
    std::cout << val << " " << member;
  }
};


int main()
{
  MyClass instance;
  instance.Test([&instance] {std::cout << "Lambda\n"; instance.SomeFunction(); }, 42);
}

有两件事困扰我:

  1. 在 lambda 中,我需要明确提及捕获的类实例。
  2. 但更重要的是:在 lambda 中无法访问私有类成员

我希望能够写作:

{std::cout << "Lambda\n"; instance.SomeFunction(); }

代替:

{std::cout << "Lambda\n"; SomeFunction(); }

甚至:

{std::cout << "Lambda\n"; instance.member; }  // access private members from lambda

有没有办法做到这一点?

【问题讨论】:

  • lambdas 是函子的糖语法,因此其中的 this 是函子本身
  • 你可以这样做:stackoverflow.com/questions/21646999/….... 但这不太好,因为每次需要函数时都必须添加朋友关系
  • 你永远不能访问班级之外的私人成员。如果你在类中创建 lambda,你可以在那里访问私有成员。

标签: c++ lambda


【解决方案1】:

这适用于使用 --std=c++20 的 GCC 10.3。而不是在定义你的 lambda 时捕获实例,只需将它作为引用传递给仿函数(这样你就可以重用它)。至于访问私有成员就不管了,这不值得花时间,并且破坏了私有的含义。只需将成员设为公开即可。 将函子作为非类型模板参数传递是可选的(它可以是函数参数,避免使用 C++20)

#include <iostream>

class MyClass
{
public:
  int member = 123;
  void SomeFunction()
  {
    std::cout << "SomeFunction()\n";
  }

  template<auto functor>
  void Test(int val)
  {
    functor(*this);
    std::cout << val << " " << member << std::endl;
  }
};


int main()
{
  MyClass instance;
  auto lambda = [](auto& _instance) {std::cout << "Lambda\n"; _instance.SomeFunction(); };
  instance.Test<lambda>(42);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多