There is a signal and several objects with slots. I want to implement the behavior when one object calls signal and blocks its own connection. I guess a small snippet will be more informative:
typedef boost::signal<void()> TSignal;
template<class TSignal>
class SlotObject
{
public:
void Connect(boost::shared_ptr<TSignal> pSignal, boost::function slot)
{
m_connection = pSignal->connect(slot);
m_pSignal = pSignal;
}
// How to define TSignal signature here?
VOID Call()
{
m_connection.block();
(*m_pSignal)();
m_connection.unblock();
}
boost::shared_ptr<TSignal> m_pSignal;
boost::signals::connection m_connection;
};
The questions:
- Is there a standard approach with some boost stuff? Do I reinventing the wheel?
- How to define Call method with TSignal signature?
For your first question: I’m not aware of a “standard boost way” to achieve what you want. You may post your question to the boost users mailing list.
For your second question: Without varidic templates and rvalue references, forwarding is always cumbersome.
A few suggestions, in no particular order:
1) You may look at the boost/signal.hpp and the files in boost/signals/ to get an idea of how this kind of stuff can be done with the preprocessor, but here’s a partial implementation to show the idea(warning: untested):
2) If you are willing to give up a bit of syntax nicety for the users of SlotObject, other things are possible. One is to wrap the call to the signal using the technique shown in boost::shared_ptr documentation (http://www.boost.org/doc/libs/1_40_0/libs/smart_ptr/sp_techniques.html#wrapper), ie, your Call() method would block the m_connection, and return a shared_ptr to m_signal having a custom deleter that unblocks m_connection.
Sadly, this does not give a nice syntax to the caller. It would look like:
3) Another alternative is to ask the user to package the arguments in a tuple (I’m using a boost::fusion::vector below) at the call site, and use boost::fusion:::fused to unpack them and call the signal.
This would be used as: