Solution: Observer

#pragma once

#include <socialdb.h>

#include <set>


class SocialDB_Observable : public SocialDB
{
public:
    class ObserverAlreadyRegistered : public std::exception 
    {
    public:
        virtual const char* what() const noexcept { return "Observer already registered"; }
    };
    class ObserverNotRegistered : public std::exception 
    {
    public:
        virtual const char* what() const noexcept { return "Observer not registered"; }
    };

public:
    class NewCitizenObserver
    {
    public:
        virtual ~NewCitizenObserver() {}
        virtual void new_citizen_added(const std::string& svnr) = 0;
    };

public:
    void insert(const std::string& svnr, const std::string& firstname, const std::string& lastname);

    void register_new_citizen_notification(NewCitizenObserver*);
    void unregister_new_citizen_notification(NewCitizenObserver*);

private:
    std::set<NewCitizenObserver*> _new_citizen_observers;
};
#include "social-db-observable.h"


void SocialDB_Observable::insert(
    const std::string& svnr, 
    const std::string& firstname, 
    const std::string& lastname)
{
    SocialDB::insert(svnr, firstname, lastname);
    for (auto observer: _new_citizen_observers)
        observer->new_citizen_added(svnr);
}

void SocialDB_Observable::register_new_citizen_notification(
    NewCitizenObserver* o)
{
    if (_new_citizen_observers.find(o) != _new_citizen_observers.end())
        throw ObserverAlreadyRegistered();

    _new_citizen_observers.insert(o);
}

void SocialDB_Observable::unregister_new_citizen_notification(
    NewCitizenObserver* o)
{
    auto num_erased = _new_citizen_observers.erase(o);
    if (num_erased == 0)
        throw ObserverNotRegistered();
}