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); };
CodePudding user response:
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.