0

I've been considering the best way to implement delegates in C++, and so far I'm inclined to using std::function callbacks. However, some of my classes issue several delegate notifications (such as opened, closed, and changed_state). Instances interested in getting delegate notifications should assign one of its own methods (the fact that it can be private is a plus) to the event it's interested in listening to. It would be expected, however, that when some instance subscribes to any of the delegates, it would subscribe to all of them. This means that it wouldn't happen that event Foo is being issued to one instance, while event Bar is being issued to a different one. Is there a way I could enforce this condition? At no point should the callbacks be assigned to different instances (assume atomicity).

I know I could consider having a single callback with calling codes or something, but in this case that's not an option (for several reasons, one of them being that it would imply an unreasonable amount of refactoring at this point).

Note: I know that are other discussions on the topic of C++ delegates, but these usually consider a single event type, not several.

An example of what I'm considering:

class Connector
{
public:

  typedef struct
  {
     std::function<void()> opened;
     std::function<void()> closed;
     std::function<void()> changed_state;
  } Delegate;

  Delegate delegate;
};

// Somewhere else
Connector c;
Listener l;

// This should not be manual. Ideally: c.delegate = l;
c.delegate.opened = l.handle_opened;
c.delegate.closed = l.handle_closed;
c.delegate.changed_state = l.handle_changed_state;
André Fratelli
  • 5,920
  • 7
  • 46
  • 87

1 Answers1

0

Add operator= for that:

class Connector
{
public:
  struct Delegate
  {
     Delegate& operator = (const Listener& l)
     {
        opened = l.handle_opened;
        closed = l.handle_closed;
        changed_state = l.handle_changed_state;
        return *this;
     }

     std::function<void()> opened;
     std::function<void()> closed;
     std::function<void()> changed_state;
  };

  Delegate delegate;
};

and then you can have your syntax:

c.delegate = l;
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • This requires the listener's methods to be public, which I was trying to avoid. Honestly I've been thinking about this and I don't think I'll find a solution. I think I'll need some sort of compromise – André Fratelli Dec 17 '15 at 13:52
  • You may provide conversion operator inside `Listener` to convert to `Delegate` but one of `Deleguate` or `Listener` should provide some public access. – Jarod42 Dec 17 '15 at 16:18