Skip to main content
edited body
Source Link
iavr
  • 2.3k
  • 1
  • 15
  • 25
  • (private) observers: std::list or some associative container of std::function<R(A...)>

  • add()/remove() (oror connect()/disconnect()) to manage the content of observers. remove() would need some form of identification of existing observers, hence the need for an associative container.

  • operator()(A&&... a) so that signal behaves like a function object. Arguments a... are passed without forwarding to underlying functions, so that they are copied if needed, and not invalidated between subsequent calls.

  • additional management like clear()/empty().

Your example usage would be rather like

signal<void(int, int)> s;
s.connect([=](int a, int b){whatever});
s(4, 5);

Isn't that better? Since everything is non-static, the user controls how many instances there are, and names them properly. In fact, a single object may have e.g. ten methods, each with its own observers. Each such method is then a signal and behaves like a function object.

  • (private) observers: std::list or some associative container of std::function<R(A...)>

  • add()/remove() (or connect()/disconnect()) to manage the content of observers. remove() would need some form of identification of existing observers, hence the need for an associative container.

  • operator()(A&&... a) so that signal behaves like a function object. Arguments a... are passed without forwarding to underlying functions, so that they are copied if needed, and not invalidated between subsequent calls.

  • additional management like clear()/empty().

Since everything is non-static, the user controls how many instances there are, and names them properly. In fact, a single object may have e.g. ten methods, each with its own observers. Each such method is then a signal and behaves like a function object.

  • (private) observers: std::list or some associative container of std::function<R(A...)>

  • add()/remove() or connect()/disconnect() to manage the content of observers. remove() would need some form of identification of existing observers, hence the need for an associative container.

  • operator()(A&&... a) so that signal behaves like a function object. Arguments a... are passed without forwarding to underlying functions, so that they are copied if needed, and not invalidated between subsequent calls.

  • additional management like clear()/empty().

Your example usage would be rather like

signal<void(int, int)> s;
s.connect([=](int a, int b){whatever});
s(4, 5);

Isn't that better? Since everything is non-static, the user controls how many instances there are, and names them properly. In fact, a single object may have e.g. ten methods, each with its own observers. Each such method is then a signal and behaves like a function object.

edited body
Source Link
iavr
  • 2.3k
  • 1
  • 15
  • 25
  • The current static behaviour is not intuitive (what does int ev really mean? why numbers and not names?), not efficient (why search in an unordered map rather that direct access?) and not thread-safe (instance is shared among all threads).

  • A list wouldmight be more appropriate to store observers of one event, enabling easier management like removing an observer.

  • Catching all exceptions in such a generic tool is a limitation. If needed, it could be at least parametrized.

  • Parameter pack Args... does not take into account return types.

  • Your Notify takes its arguments by value. Forwarding is not appropriate when calling multiple functions, but at least arguments should be passed by reference.

  • The current static behaviour is not intuitive (what does int ev really mean? why numbers and not names?), not efficient (why search in an unordered map rather that direct access?) and not thread-safe (instance is shared among all threads).

  • A list would be more appropriate to store observers of one event, enabling easier management like removing an observer.

  • Catching all exceptions in such a generic tool is a limitation. If needed, it could be at least parametrized.

  • Parameter pack Args... does not take into account return types.

  • Your Notify takes its arguments by value. Forwarding is not appropriate when calling multiple functions, but at least arguments should be passed by reference.

  • The current static behaviour is not intuitive (what does int ev really mean? why numbers and not names?), not efficient (why search in an unordered map rather that direct access?) and not thread-safe (instance is shared among all threads).

  • A list might be more appropriate to store observers of one event, enabling easier management like removing an observer.

  • Catching all exceptions in such a generic tool is a limitation. If needed, it could be at least parametrized.

  • Parameter pack Args... does not take into account return types.

  • Your Notify takes its arguments by value. Forwarding is not appropriate when calling multiple functions, but at least arguments should be passed by reference.

added 51 characters in body
Source Link
iavr
  • 2.3k
  • 1
  • 15
  • 25
  • (private) observers: std::list or some associative container of std::function<R(A...)>

  • add()/remove() (or connect()/disconnect()) to manage the content of observers. remove() would need some form of identification of existing observers, hence the need for an associative container.

  • operator()(A&&... a) so that signal behaves like a function object. Arguments a... are passed without forwarding to underlying functions, so that they are copied if needed, and not invalidated between subsequent calls.

  • additional management like clear()/empty().

  • (private) observers: std::list or some associative container of std::function<R(A...)>

  • add()/remove() (or connect()/disconnect()) to manage the content of observers. remove() would need some form of identification of existing observers, hence the need for an associative container.

  • operator()(A&&... a) so that signal behaves like a function object. Arguments a... are passed without forwarding to underlying functions, so that they are copied if needed, and not invalidated between subsequent calls.

  • (private) observers: std::list or some associative container of std::function<R(A...)>

  • add()/remove() (or connect()/disconnect()) to manage the content of observers. remove() would need some form of identification of existing observers, hence the need for an associative container.

  • operator()(A&&... a) so that signal behaves like a function object. Arguments a... are passed without forwarding to underlying functions, so that they are copied if needed, and not invalidated between subsequent calls.

  • additional management like clear()/empty().

added 958 characters in body
Source Link
iavr
  • 2.3k
  • 1
  • 15
  • 25
Loading
Source Link
iavr
  • 2.3k
  • 1
  • 15
  • 25
Loading