質問

I am trying to create some kind of event handler in c++. So I have got the following:

template<class W> 
delegate<W>* bind(W* obj, void (W::*f)(char*))
{
        return new delegate<W>(obj,f);
}

The delegate class and this function works perfectly. The problem is how to store the delegate object which with the bind function returns? I know that with boost and c++ 11 it is quite easy but how can I solve this without using them? I'm sure that it has to be possible because it was possible before these sophisticated things like boost and c++11.

(And they did it somehow in the boost as well).

So what I want to do:

class Test1
{
    Test1(){}
    ~Test1(){}

    template<class W> 
    bind(W* obj, void (W::*f)(char*))
    {
            myCallBack = new delegate<W>(obj,f);
    }

    private:
        delegate * myCallBack;  //this does not work because I have to define the template but I dont know it know it could be anything

}

class Test2
{
    Test2()
    {
        Test1 t;
        t.bind(this, &Test2::callit);
    }
    ~Test2(){}
    void callit(char*)
    {
    }
}
役に立ちましたか?

解決

Ok, I understood what exactly you need. You need just a simple callback operator, with fixed calling signature.

This example demonstrates how it is done for your specific case :

#include <iostream>
#include <utility>
#include <type_traits>
#include <vector>
#include <algorithm>



struct Cb {
    virtual ~Cb(){}
    virtual void call(const char*) = 0;
};
template<class C>
struct CmCb : Cb {
    CmCb( C& c_, void (C::*fn_)(const char*) ) : c(c_),fn(fn_)
    {
    }
    virtual void call(const char* s) {
        (c.*fn)(s);
    }
    C& c;
    void (C::*fn)(const char*);
};

struct A {
    void foo( const char* s ) {
        std::cout<<s<<std::endl;
    }
};

class Test1
{
public:
    Test1(){}
    ~Test1(){delete cb;}

    template<class W> 
    void bind(W* obj, void (W::*f)(const char*))
    {
            cb=new CmCb<W>(*obj,f);
    }
    
    void callit(const char* s ){
        cb->call(s);
    }

    private:
        Cb* cb;
};

int main()
{
    Test1 t;
    
    A a;
    t.bind(&a, &A::foo );
    
    t.callit("hey");
}

If you need more complex solution (generic signature) then you can use some kind of type erasure with boost::any.

他のヒント

There are indeed more sophisticated implementations for smart pointers than they were provided with the original standard (std::auto_ptr). But they're all involving a bit more complex concepts (regarding reference counting for shared pointers mainly). What's the hinder to use these?

If you need a more lightweight smart pointer implementation for a environment, Andrei Alexandrescu's Loki Library might be useful for you. I have managed to integrate it seamlessly for limited system environments at least (better and easier than using boost).

Don't even try to do this completely on your own, there are many many pitfalls ... If you're able to enable standards, just use these!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top