// (1)
template
<
typename D,
typename S,
typename F
>
Observer<D> Observe(const Signal<D,S>& subject, F&& func);
// (2)
template
<
typename D,
typename E,
typename F
>
Observer<D> Observe(const Events<D,E>& subject, F&& func);
// (3)
template
<
typename D,
typename F,
typename E,
typename ... TDepValues
>
Observer<D> Observe(const Events<D,E>& subject,
const SignalPack<D,TDepValues...>& depPack, F&& func);(1) When the signal value s of subject changes, func(s) is called.
(2) For every event e in subject, func(e) is called.
(3) Similar to (2), but the synchronized values of signals in depPack are passed to func as additional arguments. Changes of signals in depPack do not trigger an update - only received events do.
The signature of func should be equivalent to:
TRet func(const S&)TRet func(const E&)TRet func(const E&, const TDepValues& ...)TRet can be either ObserverAction or void.
The event parameter const E& can also be replaced by an event range, i.e. TRet func(EventRange<E> range, const TDepValues& ...) for case (3).
This allows for explicit batch processing of events of a single turn.
By returning ObserverAction::stop_and_detach, the observer function can request its own detachment.
Returning ObserverAction::next keeps the observer attached. Using a void return type is the same as
always returning ObserverAction::next.
(1)

(2)

(3)
