#ifndef CANVAS_SIGNAL_HPP #define CANVAS_SIGNAL_HPP #include "callable.hpp" #include #include namespace ce { /*! Observer-listener implementation */ template class Signal { std::vector> listeners{}; public: void connect(Callable callable); void disconnect(Callable callable); void invoke(Args...); }; template void Signal::connect(Callable callable) { this->listeners.push_back(callable); } template void Signal::disconnect(Callable callable) { std::erase_if(this->listeners, [&callable](Callable &listener) -> bool { return listener == callable; }); } template void Signal::invoke(Args... args) { for(Callable &listener : this->listeners) { listener.call(args...); } } #ifdef DEBUG static inline void TEST_signals() { struct A {inline void f(int val) { std::printf("A: %d\n", val); }}; struct B { inline void f(int val) { std::printf("B: %d\n", val); }}; A a_object; B b_object; Signal signal; Callable a_callable{Callable::make(&a_object, &A::f)}; Callable b_callable{Callable::make(&b_object, &B::f)}; signal.connect(a_callable); signal.invoke(5); signal.connect(b_callable); signal.invoke(12); signal.disconnect(a_callable); signal.invoke(10); } #endif } #endif // !CANVAS_SIGNAL_HPP