0

The question title might not be the most clear one, but here is the explanation:

Basically I want to call a member function to which I pass a lambda, and I want to access class members from the lambda like if the lambda itself was a class member.

I came up with this code which works as expected but which does not exactly what I want.

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

There are two things that bother me:

  1. in the lambda I need to mention explicitly the captured class instance.
  2. but more importantly: in the lambda there is no way to access private class members

I'd like to be able to write:

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

instead of:

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

and even:

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

Is there some way to do this?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • lambdas are sugar syntax for functors, therefore `this` inside them, is the functor itself – Alberto Sinigaglia May 05 '21 at 10:20
  • 1
    you can do something like this: https://stackoverflow.com/questions/21646999/how-to-make-the-lambda-a-friend-of-a-class.... but it's not quite nice since you have to add a friend relation every time you need a function – Alberto Sinigaglia May 05 '21 at 10:31
  • 1
    You can never access private members outside the class. If you create the lambda inside the class you can access the private members there. – super May 05 '21 at 10:58

1 Answers1

0

This works with GCC 10.3 using --std=c++20. Instead of capturing the instance when defining your lambda just pass it to the functor as a reference (this way you can reuse it). As for accessing private members just forget about it, it's not worth the time, and defeats the meaning of private. Just make the member public. Passing the functor as a non-type template argument is optional (it could be a function argument, avoiding the need for 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);
}