Iraimbilanja
Iraimbilanja

Reputation:

How to make a copyable boost::signal?

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?

Upvotes: 3

Views: 2702

Answers (6)

Russell
Russell

Reputation: 2076

Holding the signal internally in a shared_ptr will (by default) result in the signal being shared by all the copied objects. Triggering the signal in one object will result in every slot connected to the signal on all copies being notified. This might not be the behavior you want.

If you don't want this to happen you could write your own copy constructor and copy assignment operator, you will then be able to specify what you want to happen when your objects are copied.

Upvotes: 1

Diego Sevilla
Diego Sevilla

Reputation: 29021

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.

Upvotes: 1

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.

Upvotes: 3

Matt Cruikshank
Matt Cruikshank

Reputation: 2968

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

Upvotes: 2

bayda
bayda

Reputation: 13581

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

Upvotes: 7

dirkgently
dirkgently

Reputation: 111150

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.

Upvotes: 1

Related Questions