c++ - std::function 类似委托(delegate)模板类

标签 c++ templates c++11 delegates variadic-templates

您好,我正在尝试编写一个委托(delegate)类,它可以采用类似于标准函数签名的模板参数,并为成员函数指针创建一个委托(delegate),如下所示代码可能过于简化了,但这正是我一直在寻找的一种简单快速的解决方案,而且开销尽可能小。如果我可以在没有运行时多态性等的情况下获得类中的类型 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);
}

最佳答案

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

[...] The result of this conversion is unspecified, except in the following cases:

  • converting a prvalue of type “pointer to member function” to a different pointer to member function type and back to its original type yields the original pointer to member value.

下面是一个实现这种方法的例子。但是请注意,使用 std::function<R(Args...)> 可能更容易使用合适的 lambda 作为标准库很可能首先实现类似的方法。

#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);
}

关于c++ - std::function 类似委托(delegate)模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20714286/

相关文章:

c++ - std::hash 可以用来散列函数指针吗?

c++ - gcc 奇怪的转换警告(从 ‘A<B>::count_type {aka short unsigned int}’ 转换到 ‘int’ 可能会改变它的值)

c++ - 将 LPSTR 转换为 LPCTSTR

c++ - 在这种情况下,有没有办法用一个解决方案替换两个仅类型不同的相似功能?

c++ - 变量模板的显式特化

c++ - 从可变参数模板类中特化一个函数

c++ - 循环直到整数输入在要求的范围内无法处理非数字字符输入

c++ - 为什么隐式转换的结果是 -128?

c++ - 遇到 Mergesort 的比较和排序部分的问题 (c++)

c++ - 模板中定义的类型用于定义类的模板方法