Как написать класс-оболочку для Sigc ++? - PullRequest
0 голосов
/ 29 августа 2011

хотел бы иметь центральное место для регистрации новых сигналов, подключения к сигналам и так далее.теперь я подумал использовать 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;
};

что я должен заменить ???с помощью, чтобы сделать карту общей, но при этом иметь возможность извлекать соответствующий сигнал для данного идентификатора и выдавать сигнал с заданным параметром - который я тоже не знаю, как с ним обращаться.

Ответы [ 2 ]

1 голос
/ 29 августа 2011

Вам понадобится базовый класс с функцией 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.

0 голосов
/ 30 августа 2011

вот что у меня есть. это работает ... но похоже на мерзость. как я могу улучшить это дальше? например, как избавиться от 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;
...