-1

Due to the fact that std::functional uses heap memory when combining it with an std::bind I wanted to replace the std::bind with a lambda expression but I do not quite know how to do this. Is this even possible?

#include <iostream>
#include <functional>
#include <utility>

template<typename Signature>
class Callback;

template<typename R, typename... Args>
class Callback<R(Args...)> final
{
public:
    Callback() noexcept : mFunc() {}
  
    template<typename Obj, typename Method,
             typename std::enable_if_t<std::is_invocable_r<R, Method, Obj, Args...>::value, int> = 0>
    Callback(Obj& obj, Method method)
    {
       // That does not work
        mFunc = [&obj](Args... args){ return obj.method(args); };
        // mFunc = std::bind(method, obj, std::placeholders::_1, std::placeholders::_1); would work
    }

    R operator()(Args... args) const { return mFunc(args...); }

private:
   std::function<R(Args...)> mFunc;
};

struct Foo
{
   Foo() {}

   void print(int a, int b)
   {
      std::cout << a << b << "\n";
   }
};

int main()
{
   Foo foo;

   Callback<void(int, int)> cb(foo, &Foo::print);

   cb(1,2);
}

Compiler throws the following error message:

main.cpp:19:46: error: expression contains unexpanded parameter pack 'args'
        mFunc = [&obj](Args... args){ return obj.method(args); };
                                             ^          ~~~~
main.cpp:19:19: warning: lambda capture 'obj' is not used [-Wunused-lambda-capture]
        mFunc = [&obj](Args... args){ return obj.method(args); };
EmbedEngineer
  • 93
  • 2
  • 7
  • Related or dup https://stackoverflow.com/questions/17363003/why-use-stdbind-over-lambdas-in-c14 – 康桓瑋 Sep 20 '22 at 08:31
  • @463035818_is_not_a_number Added an example. Yeah it is related but a little bit more complicated than that. – EmbedEngineer Sep 20 '22 at 08:50
  • why is it "more compilcated" ? What happened when you tried to replace `std::bind` with a lambda expression? Currently the problem seems to be that you didn't actually try to do it – 463035818_is_not_an_ai Sep 20 '22 at 08:56
  • the example you added does not compile https://godbolt.org/z/9nz3PKh9W – 463035818_is_not_an_ai Sep 20 '22 at 08:57
  • @463035818_is_not_a_number I updated the example. I did try it I with ```mFunc = [&obj](Args... args){ return obj.method(args); };```and some other options but they all didn't work – EmbedEngineer Sep 20 '22 at 09:09
  • you should post the code that does not work. We cannot know what mistake you made in code you do not show. Is it the variadic args that cause issues? Or the function pointer? For those specific issues there are already existing questions and answers. Please don't let us guess. Questions about non-working code should include the non working code and the compiler error message, while requests to write code are off-topic. – 463035818_is_not_an_ai Sep 20 '22 at 09:22

1 Answers1

1

If you really want to pass a member function pointer then you need to use syntax for calling the method via a member function pointer:

 mFunc = [&,method](Args...x){ return (obj.*method)(x...);};

However, it would be simpler if you'd accept free callables and let the caller bind the object to a member function if necessary.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185