C++ std::类似于委托模板类的函数

C++ std::类似于委托模板类的函数,c++,templates,c++11,delegates,variadic-templates,C++,Templates,C++11,Delegates,Variadic Templates,您好,我正在尝试编写一个委托类,该类可以接受一个类似于标准函数签名的模板参数,并为成员函数指针创建一个委托,如下图所示。代码可能过于简单,但这正是我所寻找的一个简单而快速的解决方案,以尽可能少的开销来解决这个问题。我认为这个实现非常接近我想要的,如果我可以在类中获得类型T而不需要运行时多态性等 template<class T> struct FastDelegate {}; template<class R, class... Args> struct FastDel

您好,我正在尝试编写一个委托类,该类可以接受一个类似于标准函数签名的模板参数,并为成员函数指针创建一个委托,如下图所示。代码可能过于简单,但这正是我所寻找的一个简单而快速的解决方案,以尽可能少的开销来解决这个问题。我认为这个实现非常接近我想要的,如果我可以在类中获得类型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);
}
模板
结构FastDelegate{};
模板
结构FastDelegate
{
模板
FastDelegate(T*T,R(T::*f)(Args…):m_T(T),m_f(f){}
R运算符()(Args…p)
{
返回(mut->*muf)(标准:向前(p)…);
}
T*m\T;//如何在这个部分专门化中捕获T作为类型?
R(T::*m_f)(Args…);
};
结构测试
{
intadd(intx,inty){返回x+y;}
};
int main()
{
int x=5;
int y=4;
测试仪t;
FastDelegate d&t和测试::calc);
intz=d(x,y);
}

您不需要捕获类型t,因为您可以将
t->*m\u f
用作
函数

模板
结构FastDelegate
{
模板
FastDelegate(T*T,R(T::*f)(参数…)
:muf([=](Args…v){return(t->*f)(std::forward(v)…);}{}
R运算符()(Args…p)
{
返回m_f(标准:向前(p)…);
}
std::函数m_f;
};

如果您想通过比较
t
f
来比较2个FastDelegate实例,仍然不需要类型信息,只需获取原始指针。

您可以将对象捕获为
void*
,将成员函数存储为随机成员函数类型,并使用函数还原必要的类型。这种方法避免在堆上分配任何内存。有问题的步骤是从某种类型的成员函数转换为另一个成员函数。然而,根据5.2.10[expr.reinterpret.cast]第10段,只要在使用前将成员函数转换回其原始类型,则可以安全地使用该方法:

[…]此转换的结果未指定,以下情况除外:

  • 将“指向成员函数的指针”类型的prvalue转换为指向成员函数类型的不同指针并返回其原始类型将生成指向成员值的原始指针
下面是实现此方法的示例。但是,请注意,使用合适的lambda使用
std::function
可能更容易,因为标准库可能首先实现类似的方法

#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);
}
#包括
#包括
模板
结构FastDelegate{};
模板
结构FastDelegate
{
结构虚拟{};
模板
FastDelegate(T*T,R(T::*f)(参数…)
:m_t(t)
,m_f(重新解释铸造(f))
,m_调用([](void(dummy::*d)(),void*v,Args…a){
类型定义R(T::*mem)(参数…);
T*T=静态压力(v);
mem f=重新解释铸件(d);
返回(t->*f)(标准:向前(a)…);
}) {
}
R运算符()(Args…p){
return(this->m_call)(this->m_f,this->m_t,std::forward(p)…);
}
无效*m_t;
无效(虚拟::*MUF)();
R(*m_调用)(void(dummy::*)(),void*,Args;
};
结构测试仪
{
整数相加(整数x,整数y){

std::cout呃,委托的全部目的是在编译时删除类型,因此如果删除了类型,就无法真正访问该类型……此外,我认为“虚拟继承”的意思可能是“运行时多态性”,因为虚拟继承实际上与此无关。是的,这正是我的意思。更正了Wesome!永远不知道你可以这样玩lambda!这看起来很棒,我会接受它作为解决方案。不过,快速跟进问题,这个类是可分配的还是安全复制的?@bjackfly:这个类没有存储任何有趣的东西:只是一个妙招指针的集合。没有任何东西会使类不可复制。但是它不会复制对象(当然也可以这样做).有没有办法检查两个实例是否相等?我看不出有什么办法,因为类型隐藏在lamdaIn中。换句话说,他问的是不可能的。你只是将多态性隐藏在
std::function
下。这很好,但你应该提到它与他所寻找的明显矛盾。
#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);
}