Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- struct Base
- {
- struct IFormat
- {
- virtual int formatVal(string &) = 0;
- };
- void addFmt(IFormat * fmt)
- {
- if (!fmts.contains(fmt))
- fmts.push_back(fmt);
- }
- void removeFmt(IFormat * fmt)
- {
- auto it = fmts.find(fmt);
- if (it != fmts.end())
- fmts.erase(it);
- }
- int getValueFromFmts(string & input)
- {
- // this is getting called once in a while
- int ret(0);
- for (auto fmt : fmts)
- ret += fmt->formatVal(input);
- }
- virtual ~Base()
- {
- // what now? something probably has a reference to me.
- }
- private:
- vector<IFormat *> fmts;
- };
- struct Editor : public Base::IFormat
- {
- Editor(Base * base)
- : base(base)
- {
- base->addFmt(this);
- }
- ~Editor()
- {
- // base might be deleted!
- base->removeFmt(this);
- }
- virtual int formatVal(string &) override { ... }
- private:
- Base * base;
- };
- template<typename Derived>
- class DestructionServer
- {
- public:
- typedef Derived type;
- class ObjectProxy
- {
- public:
- ObjectProxy(const Derived * serverToPresent)
- : server(serverToPresent)
- {}
- bool operator == (const Derived * other) const
- {
- return server == other;
- }
- bool operator != (const Derived * other) const
- {
- return server != other;
- }
- private:
- const Derived * server;
- };
- class Client
- {
- friend class DestructionServer<Derived>;
- public:
- Client()
- : server(nullptr)
- {
- }
- typedef DestructionServer Server;
- virtual ~Client()
- {
- if (server)
- server->removeClientDestructor(this);
- }
- virtual void onObjectDestruction(const ObjectProxy & destroyedObject) = 0;
- private:
- void onDestruction(const Derived * derivedServer)
- {
- if (!server)
- throw std::runtime_error("Fatal error: DestructionServer::Client has no server!");
- // derivedServer should be able to downcast to server, without conversion
- if (derivedServer != server)
- throw std::runtime_error("Fatal error: derivedServer does not derive from server!");
- // forget reference to server
- server = nullptr;
- // return an unmodifiable reference to the server
- onObjectDestruction(derivedServer);
- }
- Server * server;
- };
- void removeClientDestructor(Client * client)
- {
- auto it = std::find(clients.begin(), clients.end(), client);
- if (it != clients.end())
- {
- clients.erase(it);
- }
- }
- void addClientDestructor(Client * client)
- {
- if (client && !std::contains(clients, client))
- {
- clients.push_back(client);
- // this only happens if a client is loaded into multiple servers
- // or the client is trying to add itself multiple times to the same server.
- if (client->server)
- throw std::runtime_error("Fatal error: Client already has a server!");
- client->server = this;
- }
- }
- virtual ~DestructionServer()
- {
- for (Client * client : clients)
- {
- // would like to use a dynamic_cast here to check the upcast,
- // but it is not possible since
- // ((Derived*)this) is actually deconstructed at this point...
- // or can static_cast handle this?
- // in effect this is UB, but it 'works'
- if (const Derived * derivedServer = static_cast<const Derived *>(this))
- {
- client->onDestruction(derivedServer);
- }
- else
- {
- // in fact, the typeid() shouldn't work as well, here?
- throw std::runtime_error(
- std::string("Fatal error: ") + typeid(this).name() +
- " doesn't derive from " + typeid(DestructionServer<Derived> *).name()
- );
- }
- }
- }
- protected:
- // make it impossible to construct this class without
- // deriving from this class.
- DestructionServer() {};
- private:
- std::vector<Client *> clients;
- };
- struct Base : public DestructionServer<Base>
- {
- struct IFormat : public Client
- {
- virtual int formatVal(string &) = 0;
- };
- void addFmt(IFormat * fmt)
- {
- if (!fmts.contains(fmt))
- fmts.push_back(fmt);
- }
- void removeFmt(IFormat * fmt)
- {
- auto it = fmts.find(fmt);
- if (it != fmts.end())
- fmts.erase(it);
- }
- int getValueFromFmts(string & input)
- {
- // this is getting called once in a while
- int ret(0);
- for (auto fmt : fmts)
- ret += fmt->formatVal(input);
- }
- virtual ~Base()
- {
- // DestructionServer automatically notifies all
- // objects that set a formatter to this class.
- }
- private:
- vector<IFormat *> fmts;
- };
- struct Editor : public Base::IFormat
- {
- Editor(Base * base)
- : base(base)
- {
- base->addFmt(this);
- }
- ~Editor()
- {
- // base is now null if it is deleted
- if(base)
- base->removeFmt(this);
- }
- virtual int formatVal(string &) override { ... }
- virtual void onObjectDestruction(const Base::ObjectProxy & object)
- {
- if (object == base)
- {
- // ok, base is destructed now. set it to null and go kill our self
- base = nullptr;
- delete this;
- }
- }
- private:
- Base * base;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement