I tried to use this code but it does not work with class member functions. Is there a way to generate a wrapper for class member function and call it like wrapper for non-class member?
#include <functional>
template <typename F>
class wrapper;
template <typename F, typename... Args>
typename std::result_of<F(Args...)>::type execute_helper (F&& f, Args&&... args) {
return std::forward<F>(f)( std::forward<Args>(args)...);
}
template<typename Ret, typename... Args>
class wrapper <std::function<Ret(Args...)>>
{
std::function<Ret(Args...)> m_f;
public:
wrapper( std::function<Ret(Args...)> f ): m_f(f) {}
Ret operator()(Args... args) const {
return execute_helper (m_f, args...);
}
};
The problem with member function is they need an object of the class to be called.
Supposing you can pass the object of the class, together with the pointer to the member function, to the constructor, I suppose you can write the wrapper as follows
template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...)>
{
private:
std::function<Ret(Args...)> m_f;
public:
wrapper (Cl cl, Ret(Cl::*m)(Args...))
: m_f{ [=](Args... as) mutable { return (cl.*m)(as...); } }
{ }
Ret operator() (Args... args) const
{ return m_f(args...); }
};
The following is a full compilable example of use
#include <functional>
#include <iostream>
template <typename F>
class wrapper;
template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...)>
{
private:
std::function<Ret(Args...)> m_f;
public:
wrapper (Cl cl, Ret(Cl::*m)(Args...))
: m_f{ [=](Args... as) mutable { return (cl.*m)(as...); } }
{ }
Ret operator() (Args... args) const
{ return m_f(args...); }
};
struct foo
{
long long bar (int a, long b, long long c)
{ return a+b+c; }
};
int main ()
{
foo f;
wrapper<decltype(&foo::bar)> wfb{f, &foo::bar};
std::cout << wfb(1, 2l, 3ll) << std::endl;
}
Observe that the example works for a not-const member functions.
For const member functions, you could need another wrapper
template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...) const>
{
private:
std::function<Ret(Args...)> m_f;
public:
wrapper (Cl const & cl, Ret(Cl::*m)(Args...) const)
: m_f{ [=](Args... as) { return (cl.*m)(as...); } }
{ }
Ret operator() (Args... args) const
{ return m_f(args...); }
};
In both cases, you could improve a little the operator()
adding perfect forwarding
template <typename ... As>
Ret operator() (As && ... as) const
{ return m_f(std::forward<As>(as)...); }