Search code examples
c++boost-signals

multi-signatures signal management in user classes


I'm very familiar with Qt and I know that we cannot have a similar synthax because we don't have the MOC part here. However I'm trying to have a signal creation management to simplify the declaration of a signal and the connection to it, inside my classes.

this is schematicly what I'm doing now


    class Foo
    {
       public:
          void connectMove(boost::signal<void(int)>::slot_type slot)
          void connectRotate(boost::signal<void(double)>::slot_type slot)

       private:
          boost::signal<void(int)> m_signalMove;
          boost::signal<void(double)> m_signalRotate;
    };

and this is basicaly what I would like to do (UPPERCASE = missing part)



    class SignalManager 
    {
       public:
          typedef boost::unrodered_map<std::string, GENERIC_SIGNAL *> MapSignal;
       public:
          template <typename Sig>
          bool connect(const std::string& strSignalName, boost::signal<Sig>::slot_type slot)
          {
             // simplyfied... :
             (*m_mapSignal.find(strSignalName))->connect(slot);
          }

          template <typename Sig>
          bool disconnect(const std::string& strSignalName, boost::signal<Sig>::slot_type slot)
          {
             // simplyfied... :
             (*m_mapSignal.find(strSignalName))->disconnect(slot);
          }

       protected:
          bool call(const std::string& strSignalName, SIGNAL_ARGS)
          {
             (*m_mapSignal.find(strSignalName))(SIGNAL_ARGS);
          }

          template <typename Sig>
          void delareSignal(const std::string& strSignalName)
          {
             m_mapSignals.insert(MapSignal::value_type(strSignalName, new boost::signal<Sig>()));
          }

          void destroySignal(const std::string& strSignalName)
          {
             // simplyfied... :
             auto it = m_mapSignal.find(strSignalName);
             delete *it;
             m_mapSignal.erase(it);
          }

       private:
          MapSignal m_mapSignals;
    };

    class Foo : public SignalManager
    {
       public:
          Foo(void)
          {
             this->declareSignal<void(int)>("Move");
             this->declareSignal<void(double)>("Rotate");
          }
    };


    class Other : public boost::signals::trackable
    {
       public:
          Other(Foo *p)
          {
             p->connect("Move", &Other::onMove);
             p->connect("Rotate", &Other::onRotate);
          }

          void onMove(int i)
          {
             /* ... */
          }

          void onRotate(double d)
          {
             /* ... */
          }
    };


I think I could resolve the "SIGNAL_ARGS" part with boost::functions_traits<>, but i don't know how to go around the abstract signal type.

1/ Is what I want even possible ?

2/ Is this a good approach ? (I know I will have some overhead due to the unordered_map.find, esspecily when I use this->call("signalname", ...), but I think it shouldn't be too significant)

3/ If this is not possible or not a good approach, do you have any other suggestions ?


Solution

  • I resolved my problem by wrapping boost::signals and having a boost::shared_ptr<IWrapperSignal> instead of my GENERIC_SIGNAL.

    The arguments probnlem was also resolved using boost::function_traits<T>::arg_type.

    I don't know if it's the best way to do that, but it's working fine, and it is more simple for the user to declare signals in the classes that inherit this SignalManager.