C/C++ Arena

Step 3 of 7

Observers with weak_ptr

In the Observer pattern, a subject (a stock ticker, a button, a scoreboard) notifies a list of listeners when something happens. The hard part in C++ is lifetime: if a listener is destroyed while the subject still holds a raw pointer to it, the next notification uses a dangling pointer and the program crashes, or worse.

Storing std::weak_ptr solves it. The subject doesn't keep listeners alive, and lock() tells it whether each one still exists.

#include <iostream>
#include <memory>
#include <string>
#include <vector>

struct Screen {
    std::string name;
    void show(double price) const { std::cout << name << " shows " << price << "\n"; }
};

class Ticker {
public:
    void attach(const std::shared_ptr<Screen>& s) { screens_.push_back(s); }
    void update(double price) {
        for (const auto& w : screens_) {
            if (auto s = w.lock()) s->show(price);      // alive: notify
        }
    }
    std::size_t attached() const { return screens_.size(); }

private:
    std::vector<std::weak_ptr<Screen>> screens_;
};

int main() {
    Ticker t;
    auto lobby = std::make_shared<Screen>(Screen{"lobby"});
    t.attach(lobby);
    {
        auto phone = std::make_shared<Screen>(Screen{"phone"});
        t.attach(phone);
        t.update(101.5);
    }                                 // phone is destroyed here
    t.update(99.0);                   // skipped safely: lock() returns empty
    std::cout << t.attached() << " entries still stored\n";
}
lobby shows 101.5
phone shows 101.5
lobby shows 99
2 entries still stored

How it works

The leftover entry

Notice the ticker still stores 2 entries after phone died. The dead weak_ptr is harmless, but over time a long-running subject would collect thousands of them. Your task fixes this: remove expired entries while publishing. std::erase_if(listeners_, [](const auto& w) { return w.expired(); }) does it in one call, or you can build a new vector of the live ones as you notify.

Your turn: implement Scoreboard::subscribe and Scoreboard::publish. publish notifies every living listener in subscription order, removes expired ones, and returns how many were notified.

Previous: A factory registry Next: Pimpl