Vanetza
 
Loading...
Searching...
No Matches
object_container.hpp
1#ifndef OBJECT_CONTAINER_HPP_25SOHVUH
2#define OBJECT_CONTAINER_HPP_25SOHVUH
3
4#include <functional>
5#include <map>
6#include <memory>
7#include <typeindex>
8#include <type_traits>
9
10namespace vanetza
11{
12
14{
15private:
17 {
18 template<typename T>
19 object_handle(std::unique_ptr<T> obj) :
20 object(obj.release()),
21 deleter([](void* ptr) { std::default_delete<T>()(static_cast<T*>(ptr)); })
22 {
23 }
24
26 deleter(object);
27 object = nullptr;
28 }
29
30 void* object;
31 std::function<void(void*)> deleter;
32 };
33 using container_type = std::map<std::type_index, object_handle>;
34
35public:
36 ObjectContainer() = default;
37
38 // no copy
39 ObjectContainer(const ObjectContainer&) = delete;
40 ObjectContainer& operator=(const ObjectContainer&) = delete;
41
42 // allow move
44 ObjectContainer& operator=(ObjectContainer&&) = default;
45
46 bool empty() const { return m_container.empty(); }
47
48 std::size_t size() const { return m_container.size(); }
49
50 void clear() { m_container.clear(); }
51
52 template<typename T>
53 void erase()
54 {
55 m_container.erase(std::type_index(typeid(T)));
56 }
57
58 template<typename T>
59 T* find()
60 {
61 T* result = nullptr;
62 auto found = m_container.find(std::type_index(typeid(T)));
63 if (found != m_container.end()) {
64 result = static_cast<T*>(found->second.object);
65 }
66 return result;
67 }
68
69 template<typename T>
70 const T* find() const
71 {
72 const T* result = nullptr;
73 auto found = m_container.find(std::type_index(typeid(T)));
74 if (found != m_container.end()) {
75 result = static_cast<const T*>(found->second.object);
76 }
77 return result;
78 }
79
80 template<typename T>
81 bool insert(std::unique_ptr<T> obj)
82 {
83 static_assert(std::is_object<T>() && !std::is_const<T>(),
84 "Only non-const objects are supported by ObjectContainer");
85 return m_container.emplace(std::type_index(typeid(T)), std::move(obj)).second;
86 }
87
88 template<typename T>
89 T& get()
90 {
91 static_assert(std::is_default_constructible<T>(),
92 "Only default constructible types are accessible through ObjectContainer::get");
93 T* result = find<T>();
94 if (!result) {
95 std::unique_ptr<T> obj { new T() };
96 result = obj.get();
97 if (!insert(std::move(obj)))
98 result = nullptr;
99 }
100 assert(result);
101 return *result;
102 }
103
104private:
105 container_type m_container;
106};
107
108} // namespace vanetza
109
110#endif /* OBJECT_CONTAINER_HPP_25SOHVUH */
111