c++boostboost-signals

boost signal-slot generalisation


I am searching for a way to implement something like this, using boost

class GenBoost{
  boost::signal<void(void)> m_signal;
  std::function<void (bool)> m_function

  public:
    void setSignal(boost::signal<void(void)> sigArg)
    {
       m_signal = sigArg;
    }

    void setFunction(std::function<void (bool)> &functionArg)
    {
       m_function = functionArg;
       m_signal.connect(boost::bind(&GebBoost::onSignal,this,_1));

    }

    void onSignal(){
        //do something
    }
 };

How can this be achieved. signal copying is not possible!?


Solution

  • I am not 100% sure of your intent, but assuming that onSignal() will not need to interact with m_signal (and that you only need one connection to m_signal), it appears that you can decouple m_signal from your class entirely. For example, if you really do not want the body of 'onSignal()' to be called until a 'm_function' has been set, you could do something like:

    class GenBoost{
        std::function<void (bool)> m_function;
        boost::signals::scoped_conection m_connection;
    
      public:
        void setSignal(boost::signal<void(void)>& sigArg)
        {
            m_connection = sigArg.connect(boost::bind(&GebBoost::onSignal,this));
        }
    
        void setFunction(std::function<void (bool)> &functionArg)
        {
            m_function = functionArg;
        }
    
        void onSignal()
        {
            if ( m_function )
                do_work();
        }
    
        void do_work()
        {
            //do something
        }
    };
    

    Note that I stripped the last _1 from m_signal.connect(boost::bind(&GebBoost::onSignal,this,_1)); because the signal is declared as type void(void) so should be connected to a void callback. I also added the scoped_connection so that if the object of type GenBoost is destroyed before the signal it is connected to, it will automatically disconnect rather than allow the signal to retain an invalid pointer.

    Alternatively, if you needed to retain a reference to the original signal, you could add back your original signal member, but as a pointer boost::signal<void(void)>* m_signal;. Then setSignal becomes:

    void setSignal(boost::signal<void(void)>& sigArg)
    {
        m_signal = &sigArg;
        m_connection = m_signal->connect(boost::bind(&GebBoost::onSignal,this));
    }
    

    I still recommend using the scoped connection and connecting in setSignal so that you ensure you only have one connection to one signal (If setSignal is called twice, the connection to the first signal is automatically disconnected). If you go the pointer route, you must externally ensure that the passed-in signal has a lifetime longer than the GenBoost object.