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