如何编写sigc++的包装器类

how to write a wrapper class for sigc++?

本文关键字:包装 何编写 sigc++      更新时间:2023-10-16

希望有一个中心位置来注册新的信号,连接到信号,等等。现在我想用sigc++。但是,我不知道如何为这个基于模板的库编写包装器类。类似以下语句:

class EventManager {
public:
    ... singleton stuff ...
    template<typename ReturnType, typename Params>
    bool registerNewSignal( std::string &id )
    {
        sigc::signal<ReturnType, Params> *sig = new sigc::signal<ReturnType, Params>();
        // put the new sig into a map
        mSignals[ id ] = sig;
    }
    // this one should probably be a template as well. not very
    // convenient.
    template<typename ReturnType, typename Params>
    void emit( id, <paramlist> )
    {
        sigc::signal<ReturnType, Params> *sig = mSignals[ id ];
        sig->emit( <paramlist> );
    }
private:
    std::map<const std::string, ???> mSignals;
};

我应该怎么替换??为了使映射通用,但仍然能够检索给定id的相应信号,并使用给定的参数列表发出信号——我也不知道如何处理。

你需要一个基类,它有emit()函数:

template<class Ret>
class SigBase {
public:
  virtual Ret emit()=0;
};

和它的一些实现:

template<class Ret, class Param1>
class SigDerived : public SigBase<Ret>
{ 
public:
  SigDerived(sigc::signal<Ret, Param1> *m, Param1 p) : m(m), p(p){ }
  Ret emit() { return m->emit(p); }
private:
  sigc::signal<Ret, Param1> *m;
  Param1 p;
};

那么映射就是指向基类的指针:

std::map<std::string, SigBase<Ret> *> mymap;

编辑:如果SigBase没有Ret值,而是只支持void返回,可能会更好。

这是我目前所做的。它有效……但感觉很恶心。我怎样才能进一步改进它?例如,如何摆脱reinterpret_cast?

@dimitri:谢谢你关于互斥锁的提示,我会添加的。

class Observer {
public:
    static Observer* instance()
    {
        if ( !mInstance )
            mInstance = new Observer();
        return mInstance;
    }
    virtual ~Observer() {}
    template<typename ReturnType, typename Params>
    sigc::signal<ReturnType, Params>* get( const std::string &id )
    {
        SignalMap::const_iterator it = mSignals.find( id );
        if ( it == mSignals.end() )
            return 0;
        return reinterpret_cast<sigc::signal<ReturnType, Params>*>( (*it).second );
    }
    template<typename ReturnType, typename Params>
    bool registerSignal( const std::string &id )
    {
        SignalMap::const_iterator it = mSignals.find( id );
        if ( it != mSignals.end() ) {
            // signal with the given id's already registered
            return false;
        }
        // create a new signal instance here
        sigc::signal<ReturnType, Params> *sig = new sigc::signal<ReturnType, Params>();
        mSignals[ id ] = reinterpret_cast<sigc::signal<void>*>(sig);
        return true;
    }
private:
    Observer()
    {
    }
    SignalMap           mSignals;
    static Observer*    mInstance;
};
Observer* Observer::mInstance = 0;