Last active
June 30, 2022 04:27
-
-
Save JSH32/de6ac7d3ede18f499ba1587af43b7c2e to your computer and use it in GitHub Desktop.
Reactive State
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
template <class Container, class F> | |
auto erase_where(Container& c, F&& f) { | |
return c.erase(std::remove_if(c.begin(), c.end(), std::forward<F>(f)), | |
c.end()); | |
} | |
/** | |
* @brief Reactive state. Listeners will be registered as callbacks to state | |
* changes on T | |
* | |
* @tparam T state type (inherit on T, crtp pattern) | |
*/ | |
template <class T> | |
class State { | |
public: | |
/** | |
* @brief Listen to state changes triggered by State<T> | |
* | |
* @tparam T state type | |
*/ | |
class Listener { | |
T* state; | |
public: | |
Listener(T* state) : state(state) { | |
state->listeners.push_back(this); | |
} | |
virtual ~Listener() { | |
erase_where(state->listeners, | |
[this](auto* instance) { return this == instance; }); | |
} | |
T* getState() { return state; } | |
virtual void onStateUpdate(T* state) = 0; | |
}; | |
protected: | |
void dispatchUpdate() { | |
for (auto* listener : this->listeners) | |
listener->onStateUpdate(static_cast<T*>(this)); | |
} | |
private: | |
std::vector<Listener*> listeners; | |
friend Listener; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment