/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2019 Danny Robson */ #pragma once #include "log.hpp" #include "introspection.hpp" #include #include namespace cruft { template class registry { public: struct cookie { explicit cookie (KeyT const &_key) : m_key (_key) { ; } explicit cookie (KeyT &&_key) : m_key (std::move (_key)) { ; } cookie (cookie &&rhs) noexcept : m_key (std::move (rhs.key)) { ; } cookie& operator= (cookie &&rhs) noexcept { std::swap (rhs.m_key, m_key); return *this; } cookie (cookie const&) = delete; cookie& operator= (cookie const&) = delete; ~cookie () { registry::remove (m_key); } private: KeyT m_key; }; static cookie add [[nodiscard]] (KeyT key, FactoryT &&factory) { auto const &[pos, success] = store ().insert ( { key, std::move (factory) } ); if (success) { LOG_INFO ("Registered %! for %!", key, cruft::type_name ()); return cookie { key }; } { LOG_ERROR ("Unable to register %! for %!", key, cruft::type_name ()); throw std::runtime_error ("Unable to register type"); } } static FactoryT remove (KeyT const &key) { auto &s_factory = store (); auto pos = s_factory.find (key); if (pos == s_factory.cend ()) throw std::invalid_argument ("Key not found"); auto val = s_factory.extract (pos); return std::move (val.mapped ()); } static FactoryT& at (KeyT const &key) { return store ().at (key); } private: static auto& store (void) { static std::map s_factory; return s_factory; } }; }