std::function/bind like type-erasure without Standard C++ library

前端 未结 3 592
暖寄归人
暖寄归人 2021-02-02 03:12

I\'m developing a simple event driven application in C++11 based on the publish/subscribe pattern. Classes have one or more onWhateverEvent() method invoked by the

3条回答
  •  执念已碎
    2021-02-02 04:16

    Your 1st idea is your typical object oriented solution to the problem. It's perfectly fine, but a bit heavy-handed - not quite as usable as std::function. Your 3rd idea is undefined behavior. Nope nope nope.

    Your 2nd idea - now there's something we can work with! This is close to how std::function is actually implemented. We can write a class that can take any object that is callable with int and returns void:

    class IntFunc {
    private:
        struct placeholder {
            virtual ~placeholder() = default;
            virtual void call(int ) = 0;
        };
    
        template 
        struct holder : placeholder {
            holder(F f) : func(f) { }
            void call(int i) override { func(i); }
            F func;
        };
    
    
        // if you wrote your own unique_ptr, use it here
        // otherwise, will have to add rule of 5 stuff
        placeholder* p;
    public:
        template 
        IntFunc(F f)
        : placeholder(new holder(f))
        { }
    
        template 
        IntFunc(Cls* instance, void (Cls::*method)(int )) {
            auto lambda = [=](int i){ (instance->*method)(i); };
            placeholder = new holder(lambda);
        }
    
        void operator()(int i) {
            p->call(i);
        }
    };
    

    With that, you basically have std::function in a usable, generic way.

    Now a 4th idea might be to just extend your 3rd idea to something usable. Actually use function pointers:

    using Pfn = void (*)(void*, int);
    

    And then use lambdas to make such things:

    Pfn buttonOnTick = [](void* ctxt, int i){
        static_cast(ctxt)->onTick(i);
    };
    

    But then you have to hold on to the contexts somehow - which adds extra work.

提交回复
热议问题