【问题标题】:Member function class without stl and dynamic memory allocation没有stl和动态内存分配的成员函数类
【发布时间】:2017-01-26 08:28:45
【问题描述】:

我编写了下面的示例,它不使用标准库来调用类成员函数。这按预期工作,但我想让它更通用。这适用于具有 8 位微控制器的嵌入式系统。我不想引发关于是否将 C++ 用于这种架构的讨论。

代码的工作方式如下: 不能对类成员函数或函数使用 void 指针。虽然可以为单个函数使用 void 指针,但这不是明确定义的行为。

在这种情况下,我使用静态函数来调用类成员。方法调用函数是一个静态模板函数,它接受对象类型和成员函数指针作为模板参数。

bind函数将对象指针存储为void指针,并将类内部的callingFunction设置为具体的静态方法。当使用 () 运算符进行调用时,调用函数指针会使用特定对象和所有参数进行调用。

所有这些都按预期工作,并且由于可变参数模板,可以在启用 C++11 的情况下进行编译。我的目的是让 api 更舒适。一直使用 f.bind(&t) 似乎有点长,但我不知道有什么更好的方法来做到这一点。有任何想法吗?

另一点是存储不属于类的函数。

#include <iostream>

class testclass {
public:
    virtual char test(void){
        return '.';
    }
};

class testclass2 : public testclass{
public:
    char test(void){
        return '@';
    }
};

template<typename signature>
class Function;

template<typename TReturn, typename ...TParam>
class Function<TReturn(TParam...)> {
public:
    template<typename TObject, TReturn (TObject::*TMethod)(TParam...)>
    void bind(TObject *obj){
        this->obj = obj;
        this->callingFunction = &methodCaller<TObject, TMethod>;
    }

    TReturn operator()(TParam... params){
        return callingFunction(this->obj, params...);
    }
private:
    void *obj;
    TReturn (*callingFunction)(void *obj, TParam...);

    template<typename TObject, TReturn (TObject::*TMethod)(TParam...)>
    static TReturn methodCaller(void *obj, TParam... params) {
        TObject *c = static_cast<TObject*>(obj);
        return (c->*TMethod)(params...);
    }
};

int main(){
    testclass t;

    Function<char(void)> f;
    f.bind<testclass, &testclass::test>(&t);
    std::cout << f();

    testclass2 t1 = testclass2();
    f.bind<testclass, &testclass::test>(&t1);
    std::cout << f();
}

【问题讨论】:

  • 你期待哪个界面?你想要std::bind(&amp;testclass::test, &amp;t /*, _1, _2 */);
  • 更好的接口是 f.bind(&t, &testclass::test)

标签: c++ function templates pointers


【解决方案1】:

以下允许您预期的界面

template<typename signature> class Function;

template<typename TReturn, typename ...TParam>
class Function<TReturn(TParam...)> {
private:
    template <typename Obj>
    struct Helper
    {
        Obj* obj;
        TReturn (Obj::*m)(TParam...);

        Helper(Obj* obj, TReturn (Obj::*m)(TParam...)) : obj(obj), m(m) {}

        template <typename ... Args>
        TReturn call(Args&&... args) { return (obj->*m)(std::forward<Args>(args)...); }
    };

public:
    template<typename TObject>
    void bind(TObject *obj, TReturn (TObject::*m)(TParam...)){
        this->obj = std::make_shared<Helper<TObject>>(obj, m);
        this->callingFunction = &methodCaller<TObject>;
    }

    TReturn operator()(TParam&&... params){
        return callingFunction(this->obj.get(), std::forward<TParam>(params)...);
    }
private:
    std::shared_ptr<void> obj;
    TReturn (*callingFunction)(void* obj, TParam...);

    template<typename TObject>
    static TReturn methodCaller(void *obj, TParam... params) {
        auto* c = static_cast<Helper<TObject>*>(obj);
        return c->call(std::forward<TParam>(params)...);
    }
};

Demo

我让你用自己的智能指针替换 std::shared_ptr 在你想摆脱标准库。

【讨论】:

  • 没有动态内存分配,根本无法使用std::。
  • 我使用 std::cout 仅用于测试输出,但最终代码将在 8 位处理器上运行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-26
  • 2011-07-18
  • 2020-09-03
  • 2017-03-22
  • 1970-01-01
  • 2011-07-16
相关资源
最近更新 更多