views:

459

answers:

5

I get why boost::signal is noncopyable (it's because copying a signal doesn't have a clear meaning), but I need a version of it that does provide some sort of copy ctor (either a no-op or one that copies all connections).

The reason I need this is because in my project many objects become noncopyable just by virtue of featuring signals, and to treat them with comfortable value semantics (shared_ptrs are not as comfortable) I need to manually provide copy-ctors, violating DRY. Clearly a sort of quasi-copyable signal would be a good workaround for C++'s ugliness here.

First solution that comes to mind is inheriting signal and providing a copy ctor in the derived class, but that's a no-go because signal doesn't have a virtual dtor.

Thoughts?

+1  A: 

Can you not have a proxy object for your signals? The proxy will maintain both a signal and a reference count. Instead of creating copies of signals, talk to the proxy which will in turn increase/decrease the count. Does that work?

You may want to refer to the Decorator pattern as well.

dirkgently
That's great but how would I forward the appropriate number of args to signalN::operator()()?
Does N vary in your case?
dirkgently
Yes, it's 0, 1 or 2.
Pass a policy object to the proxy which will forward the suitable object(s) if any.
dirkgently
Hmm what policy object? Like, a Forwarder that has been specialized for 10 arities, and, at signal invocation site, instantiated for the needed argcount?
See http://en.wikipedia.org/wiki/Policy-based_designDon't take the letters of that pattern, but the word of it.
dirkgently
+2  A: 

Try hold pointers ( or shared_ptr ) on singals instead signals.

bb
+1  A: 

Don't derive. It's a bad idea, and it won't do you any good - your derived class won't be copyable, either. Whatever parts of signal you want to expose, and whatever behaviors you want to implement, do it with your own class, and just use boost::signal behind the scenes.

namespace Iraimbilanja {

// the copy constructor doesn't copy the signal, so it doesn't copy the connections...
struct EmptyOnCopySignal
{
private:
    boost::shared_ptr<boost::signal> _signal;
};

// the copy constructor references the same signal, so it copies the connections...
struct CopyableSignal
{
private:
    boost::shared_ptr<boost::signal> _signal;
};

} // namespace Iraimbilanja
Matt Cruikshank
A: 

I would go for holding the signals internally in shared_ptr. That way your objects will directly be copyable and you can use value semantics.

David Rodríguez - dribeas
A: 

Definitely you can use boost::ref. This is the main purpose of this class. It was also used in previous versions of boost when threads could not be copied. The only drawback is that signals may be managed outside the class, so that references stored on all the copied classes are always valid.

Diego Sevilla