#ifndef OBJECT_CONTAINER_HPP_25SOHVUH #define OBJECT_CONTAINER_HPP_25SOHVUH #include #include #include #include #include namespace vanetza { class ObjectContainer { private: struct object_handle { template object_handle(std::unique_ptr obj) : object(obj.release()), deleter([](void* ptr) { std::default_delete()(static_cast(ptr)); }) { } ~object_handle() { deleter(object); object = nullptr; } void* object; std::function deleter; }; using container_type = std::map; public: ObjectContainer() = default; // no copy ObjectContainer(const ObjectContainer&) = delete; ObjectContainer& operator=(const ObjectContainer&) = delete; // allow move ObjectContainer(ObjectContainer&&) = default; ObjectContainer& operator=(ObjectContainer&&) = default; bool empty() const { return m_container.empty(); } std::size_t size() const { return m_container.size(); } void clear() { m_container.clear(); } template void erase() { m_container.erase(std::type_index(typeid(T))); } template T* find() { T* result = nullptr; auto found = m_container.find(std::type_index(typeid(T))); if (found != m_container.end()) { result = static_cast(found->second.object); } return result; } template const T* find() const { const T* result = nullptr; auto found = m_container.find(std::type_index(typeid(T))); if (found != m_container.end()) { result = static_cast(found->second.object); } return result; } template bool insert(std::unique_ptr obj) { static_assert(std::is_object() && !std::is_const(), "Only non-const objects are supported by ObjectContainer"); return m_container.emplace(std::type_index(typeid(T)), std::move(obj)).second; } template T& get() { static_assert(std::is_default_constructible(), "Only default constructible types are accessible through ObjectContainer::get"); T* result = find(); if (!result) { std::unique_ptr obj { new T() }; result = obj.get(); if (!insert(std::move(obj))) result = nullptr; } assert(result); return *result; } private: container_type m_container; }; } // namespace vanetza #endif /* OBJECT_CONTAINER_HPP_25SOHVUH */