File emulator_context.hpp
File List > common > src > emulator_context.hpp
Go to the documentation of this file
#ifndef EMULATOR_CONTEXT_HPP
#define EMULATOR_CONTEXT_HPP
#include <any>
#include <map>
#include <memory>
#include <stdexcept>
#include <string>
#include <typeindex>
namespace emulator {
class EmulatorContext {
public:
static EmulatorContext &singleton() {
static EmulatorContext c;
return c;
}
template <typename T, typename... Args> T &create(Args &&...args) {
auto key = getKey<T>();
if (m_objects.find(key) != m_objects.end()) {
throw std::runtime_error(
"Error! Object with key '" + std::string(key.name()) +
"' was already created in the emulator context.\n");
}
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
m_objects[key] = std::any(ptr);
return *ptr;
}
template <typename T> const T &get() const {
auto key = getKey<T>();
auto it = m_objects.find(key);
if (it == m_objects.end()) {
throw std::runtime_error("Error! Object with key '" +
std::string(key.name()) +
"' not found in the emulator context.\n");
}
return *std::any_cast<std::shared_ptr<T>>(it->second);
}
template <typename T> T &getNonConst() {
auto key = getKey<T>();
auto it = m_objects.find(key);
if (it == m_objects.end()) {
throw std::runtime_error("Error! Object with key '" +
std::string(key.name()) +
"' not found in the emulator context.\n");
}
return *std::any_cast<std::shared_ptr<T>>(it->second);
}
template <typename T> bool has() const {
auto key = getKey<T>();
return m_objects.find(key) != m_objects.end();
}
void clean_up() { m_objects.clear(); }
private:
using key_type = std::type_index;
EmulatorContext() = default;
template <typename T> static key_type getKey() {
return std::type_index(typeid(T));
}
std::map<key_type, std::any> m_objects;
};
inline void cleanup_emulator_context() {
EmulatorContext::singleton().clean_up();
}
} // namespace emulator
#endif // EMULATOR_CONTEXT_HPP