具有 class 成员函数作为模板参数的 C++ 函数调用包装器
C++ function call wrapper with class member function as template argument
我尝试使用 代码,但它不适用于 class 成员函数。有没有办法为 class 成员函数生成包装器并像非 class 成员的包装器一样调用它?
#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...);
}
};
成员函数的问题是它们需要调用 class 的对象。
假设你可以将 class 的对象连同指向成员函数的指针一起传递给构造函数,我想你可以按如下方式编写包装器
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...); }
};
以下是完整的可编译使用示例
#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;
}
观察到该示例适用于非常量成员函数。
对于 const 成员函数,您可能需要另一个包装器
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...); }
};
在这两种情况下,您可以稍微改进 operator()
添加完美转发
template <typename ... As>
Ret operator() (As && ... as) const
{ return m_f(std::forward<As>(as)...); }
我尝试使用
#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...);
}
};
成员函数的问题是它们需要调用 class 的对象。
假设你可以将 class 的对象连同指向成员函数的指针一起传递给构造函数,我想你可以按如下方式编写包装器
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...); }
};
以下是完整的可编译使用示例
#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;
}
观察到该示例适用于非常量成员函数。
对于 const 成员函数,您可能需要另一个包装器
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...); }
};
在这两种情况下,您可以稍微改进 operator()
添加完美转发
template <typename ... As>
Ret operator() (As && ... as) const
{ return m_f(std::forward<As>(as)...); }