Во-первых, мне очень нравится шаблон ленивой инициализации синглетонов. Я использую его следующим образом для получения данных различного типа с различными типами значений (пример упрощен):
class A
{
template<typename T>
const T& getData() const
{
static T data;
return data;
}
}
Я знаю что data
Переменная не связана ни с какими экземплярами класса и существует она до завершения программы.
Но сейчас я хочу, чтобы каждый экземпляр класса A содержал переменные нестатическим образом, и все же должна быть гибкость вызова .getData<bool>()
или с любым другим типом данных, без необходимости указывать каждый возможный тип данных в определении класса.
Это возможно? У меня нет идеи реализовать это.
Я думал о чем-то с контейнером, как:
template<A*, typename T>
class DataContainer
{
T data;
}
С этим можно расширить код до:
class A
{
template<typename T>
const T& getData() const
{
static DataContainer<this, T> container;
return container.data;
}
}
Но это не компилируется.
У кого-нибудь из вас есть идея, как это реализовать?
Вот одна идея, используя Boost.any:
#include <typeinfo>
#include <type_index>
#include <unordered_map>
#include <boost/any.hpp>
struct ThingGetter
{
template <typename T>
T & get()
{
auto key = std::type_index(typeid(T));
auto it = things.find(key);
if (it == things.end())
{
it = things.emplace(key, boost::any(T())).first;
}
return boost::any_cast<T&>(*it);
}
std::unordered_map<std::type_index, boost::any> things;
};
Эта простая версия предполагает, что каждый тип может быть инициализирован значением, и создает значение, инициализированное значением, если не существует записи для запрошенного типа. Альтернативные реализации могут возвращать указатель, который может быть нулевым и иметь отдельный интерфейс вставки.
Использование:
ThingGetter mythings;
mythings.get<bool>() = true;
mythings.get<double>() = 1.5;
return mythings.get<int>();