1

Is it possible to obtain a C style function pointer of a capturing lambda using static local variables?

I am trying to bind the first the argument of the derived function to the original parameter

template <typename F>
class entry_hook
{
public:
  entry_hook(void* original, F&& hook)
  {
    static auto bound = [&](auto&&... args)
    {
      return hook(original, std::forward<decltype(args)>(args)...);
    };

    auto* function_ptr = +[](auto&&... args) // -> decltype(bound(std::forward<decltype(args)>(args)...))
    {
      return bound(std::forward<decltype(args)>(args)...);
    };
  }
};

Using:

const auto hook = entry_hook(nullptr, [](void* original)
{
  // ...
});

Fails to compile - unable to convert closure to function pointer

Removing the parameter pack from the wrapping lambda (by changing the following lines):

  • auto* function_ptr = +[](auto&&... args) to auto* function_ptr = +[]()
  • return bound(std::forward<decltype(args)>(args)...); to return bound();

Succesfully compiles and runs, although I would have assumed that by using a parameter pack that can be inferred at compile time on a lambda, wouldn't result in that lambda becoming a closure as such (being unconvertable to a function pointer as it requires a context)


I'm ideally trying to achieve:

const auto hook = entry_hook(nullptr, [](auto original, int param1, double param2)
{
  // ...
});

Where original is of type void(*)(int, double) and entry_hook can expose a function pointer to the passed in lambda


Reference:

This answer converts a capturing lambda into a function pointer C++ lambda with captures as a function pointer

This answer converts a lambda into a function pointer Obtaining function pointer to lambda?

max66
  • 65,235
  • 10
  • 71
  • 111
Adam W
  • 317
  • 1
  • 3
  • 15

1 Answers1

1

No: it's impossible.

Because the lambda that you trying to convert to a function pointer

[](auto && ... args) { /* something */ }

is a generic (and variadic; but the point is that is a generic one) lambda.

So is almost as a (variadic) template function (more exactly: as a struct with a variadic template operator() in it) as

template <typename ... As>
SomeRetType func (As && ... as)
 { /* do something */ }

and you can't have a pointer from func()

auto fp = &func;  // same problem

because func() isn't an object but a set of objects.

max66
  • 65,235
  • 10
  • 71
  • 111
  • is this not achieved in the first answer I referenced? – Adam W Dec 23 '19 at 11:45
  • 1
    @AdamW - Do you mean inside `lambda_traits`? Isn't the same thing. In that class, the `Args...` (and also `R`) types are template types of the `struct`; so, inside the struct, the `Args...` types are defined, not template types. If you transform the `auto && ... args` values in `Args && ... args` where `Args...` are template arguments of the class/struct (or of the method), yes, inside the class/struct (or method) you can do something similar. But not when the template types are free types for the function/lambda. – max66 Dec 23 '19 at 12:00