您好我正在尝试编写一个委托类,它可以采用类似于标准函数签名的模板参数,并为成员函数指针创建委托,如下面的main中所示。代码可能过于简单,但我正在寻找的是一个简单而快速的解决方案,尽可能减少开销。我认为这个实现非常接近于实现我想要的,如果我可以在没有运行时多态性等的情况下获得类中的类型T.
template<class T>
struct FastDelegate {};
template<class R, class... Args>
struct FastDelegate<R (Args...)>
{
template <typename T>
FastDelegate(T* t, R (T::*f)(Args...)) : m_t(t), m_f(f) {}
R operator()(Args... p)
{
return (m_t->*m_f)(std::forward<Args>(p)...);
}
T* m_t; // How can I capture T as a type in this partial specialization?
R (T::*m_f)(Args...);
};
struct Test
{
int add ( int x, int y ) { return x+y; }
};
int main ()
{
int x = 5;
int y = 4;
Tester t;
FastDelegate<int (int,int)> d (&t, &Test::calc );
int z = d(x,y);
}
答案 0 :(得分:4)
您可以将对象捕获为void*
,将成员函数存储在随机成员函数类型中,并使用函数恢复必要的类型。这种方法避免在堆上分配任何内存。有问题的步骤是从某种类型的成员函数转换到另一个成员函数。但是,根据5.2.10 [expr.reinterpret.cast]第10段,只要成员函数在使用之前被转换回其原始类型,就可以安全地使用这种方法:
[...]此转换的结果未指定,但以下情况除外:
- 将“指向成员函数的指针”类型的prvalue转换为指向成员函数类型的不同指针,并返回其原始类型,从而生成指向成员值的原始指针。
以下是实现此方法的示例。但请注意,使用合适的lambda可能更容易使用std::function<R(Args...)>
,因为标准库很可能首先实现这样的方法。
#include <iostream>
#include <utility>
template<class T>
struct FastDelegate {};
template<class R, class... Args>
struct FastDelegate<R (Args...)>
{
struct dummy {};
template <typename T>
FastDelegate(T* t, R (T::*f)(Args...))
: m_t(t)
, m_f(reinterpret_cast<void (dummy::*)()>(f))
, m_call([](void(dummy::*d)(), void* v, Args... a){
typedef R (T::*mem)(Args...);
T* t = static_cast<T*>(v);
mem f = reinterpret_cast<mem>(d);
return (t->*f)(std::forward<Args>(a)...);
}) {
}
R operator()(Args... p) {
return (this->m_call)(this->m_f, this->m_t, std::forward<Args>(p)...);
}
void* m_t;
void (dummy::*m_f)();
R (*m_call)(void (dummy::*)(), void*, Args...);
};
struct Tester
{
int add ( int x, int y ) {
std::cout << "add(" << x << ", " << y << ")\n";
return x+y;
}
};
int main ()
{
int x = 5;
int y = 4;
Tester t;
FastDelegate<int (int,int)> d (&t, &Tester::add);
int z = d(x,y);
}
答案 1 :(得分:3)
您无需捕获T类型,因为您可以将t->*m_f
用作function<R(Args...)>
template<class R, class... Args>
struct FastDelegate<R (Args...)>
{
template <typename T>
FastDelegate(T* t, R (T::*f)(Args...))
: m_f([=](Args... v){ return (t->*f)(std::forward(v)...); }) {}
R operator()(Args... p)
{
return m_f(std::forward<Args>(p)...);
}
std::function<R(Args...)> m_f;
};
如果您想通过比较t
和f
来比较2个FastDelegate实例,则仍然不需要输入类型信息,只需使用原始指针。