ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – std :: function就像委托模板类一样

2019-07-28 18:05:29  阅读:201  来源: 互联网

标签:c c11 templates variadic-templates delegates


您好我正在尝试编写一个委托类,可以采取类似于标准函数签名的模板参数,并为成员函数指针创建一个委托,如下面的主要部分所示.代码可能过于简单,但我正在寻找的是一个简单而快速的解决方案,尽可能减少开销.我认为如果我可以在没有运行时多态性的情况下获得类中的类型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,c11,templates,variadic-templates,delegates
来源: https://codeday.me/bug/20190728/1564370.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有