Skip to content

Instantly share code, notes, and snippets.

@DrkWithT
Created May 3, 2025 03:48
Show Gist options
  • Save DrkWithT/cb6d0bd07c0a00360a4317e3c98254df to your computer and use it in GitHub Desktop.
Save DrkWithT/cb6d0bd07c0a00360a4317e3c98254df to your computer and use it in GitHub Desktop.
Attempt of Observer Pattern using CRTP
#include <string>
#include <unordered_map>
#include <print>
/// CRTP example for observer pattern
template <typename Derived>
class ObserverBase {
public:
ObserverBase() = default;
void update(int button_id) {
static_cast<Derived*>(this)->update(button_id);
}
};
template <typename Derived>
class ControlBase {
public:
ControlBase() = default;
template <typename ObserverKind>
void set(ObserverKind* observer) noexcept {
static_cast<Derived*>(observer)->set(observer);
}
void notify() {}
};
class ControlObserver : public ObserverBase<ControlObserver> {
private:
std::unordered_map<int, bool> m_control_states; // represents on or off switches...
void report() {
for (const auto& [id, state] : m_control_states) {
std::print("Switch {} is {}, ", id, state);
}
std::print("\n\n");
}
public:
ControlObserver()
: m_control_states {} {}
void update(int control_id) {
m_control_states[control_id] = !m_control_states[control_id];
report();
}
};
class ToggleControl : public ControlBase<ToggleControl> {
private:
ControlObserver* m_observer_ref;
int m_id;
public:
explicit ToggleControl(int id) noexcept
: m_observer_ref {nullptr}, m_id {id} {}
template <typename ObserverKind>
void set(ObserverKind* observer) noexcept {
m_observer_ref = observer;
}
void notify() {
if (!m_observer_ref) {
return;
}
m_observer_ref->update(m_id);
}
};
int main() {
// Create fake UI observer...
ControlObserver toggle_sensor;
// Create fake UI controls (switches)...
ToggleControl toggler_1 {1}; // switch 1
ToggleControl toggler_2 {2}; // switch 2
// Register observer for fake controls...
toggler_1.set(&toggle_sensor);
toggler_2.set(&toggle_sensor);
toggler_1.notify(); // turn switch 1 on
toggler_1.notify(); // turn switch 1 off
toggler_2.notify(); // turn switch 2 on
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment