【问题标题】:C++ Functor template for class member functions类成员函数的 C++ Functor 模板
【发布时间】:2018-01-28 17:52:36
【问题描述】:

我编写了一个小型仿函数类,它应该能够通过隐藏静态包装函数和指向对象的 void 指针来调用类成员函数。由于设置包装函数时出错,下面的示例无法编译。我想要的是一个类成员指针作为模板参数。有谁知道那里出了什么问题?

我认为调用成员函数时静态函数可能存在另一个问题。我不完全知道如何使用模板语法来做到这一点。最小示例使用启用 C++11 的 gcc 进行编译。

#include <iostream>

template<class TReturn, class... TParameter>
struct Functor {

    TReturn (*ptr)(void*, TParameter...);
    void     *object;

    template<class TObject, class TMemberFunction>
    static TReturn memberCaller(void *obj, TParameter... params) {
        TObject *c = static_cast<TObject*>(obj);
        return (c->*(TObject::TMemberFunction))(params...);
    }

    TReturn operator()(TParameter... params) {
        return ptr(object, params...);
    }
};

class Test {
public:
    void func(int a) {
        std::cout << a << std::endl;
    }
};

int main(int argc, const char **argv) {
    Functor<void, int> f;
    Test               t;

    f.object = &t;
    f.ptr    = &Functor<void, int>::memberCaller<Test, Test::func>;

    f(100);
}

【问题讨论】:

  • 您需要将指针传递给您要调用的Test 类的成员函数到FunctorTMemberFunction 不是类型名称。其实你可以看看std::function或者fastdelegate是怎么实现的。
  • 我忘了说在这种情况下没有可用的stl,因为我在嵌入式系统中使用它。
  • 这与嵌入式系统有什么关系?

标签: c++ c++11 embedded functor


【解决方案1】:

这样的东西对你有用吗?

#include <iostream>

template<class TObject, class T, class... TParameter>
struct Functor {

    using TMemberFunction = T (TObject::*)(TParameter...);
    TMemberFunction ptr;
    TObject     *object;


    T operator()(TParameter... params) {
        return (object->*ptr)(params...);
    }
};

class Test {
public:
    void func(int a) {
        std::cout << a << std::endl;
    }
};

template<typename T>
class TD;

int main() 
{
    Functor<Test, void , int> f;
    Test               t;

    f.object = &t;
    f.ptr = &Test::func;

    f(100);
}

【讨论】:

  • 不要把你的答案写成问题。并且可能会添加一些解释,而不仅仅是转储代码。
  • 效果很好,但我只能将 Functor 用于一个特定的类。在某些情况下,不是类类型而是函数原型。
  • 不同类的成员函数有不同的类型。所以我真的不明白“类类型不重要”是怎么回事
【解决方案2】:

抛开一些其他错误,您的代码不适用于TMemberFunction in:

template<class TObject, class TMemberFunction>
static TReturn memberCaller(void *obj, TParameter... params) {
    // ...
}

不能用于捕获指向成员函数的指针。 TMemberFunction 必须是一个类型,而你没有那样使用它。

您可以按如下方式定义您的类:

template<class>
struct Functor;

template<class TReturn, class... TParameter>
struct Functor<TReturn(TParameter...)> {
    TReturn (*ptr)(void*, TParameter...);
    void     *object;

    template<class TObject, TReturn(TObject::*TMemberFunction)(TParameter...)>
    static TReturn memberCaller(void *obj, TParameter... params) {
        TObject *c = static_cast<TObject*>(obj);
        return (c->*TMemberFunction)(params...);
    }

    TReturn operator()(TParameter... params) {
        return ptr(object, params...);
    }
};

并以这种方式使用它:

Functor<void(int)> f;
Test               t;

f.object = &t;
f.ptr    = &Functor<void(int)>::memberCaller<Test, &Test::func>;

f(100);

也就是说,您现在可以将成员函数用作memberCaller 的模板参数,并让它擦除类型并在调用后在内部使用它。

我还稍微修改了Functor的定义,将其用作:

Functor<void(int)>

当您计划将其与函数类型一起使用时,这比以下内容更明确:

Functor<void, int>

至少我的两分钱。


请参阅上面的示例并在 wandbox 上运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    • 1970-01-01
    相关资源
    最近更新 更多