Использовать тип данных (тип класса) в качестве ключа на карте
У меня есть класс Base
и классы Derived_1
, Derived_2
...
Мне нужны производные классы, чтобы иметь id. Эти идентификаторы используются для дальнейших поисков и т.д. И, следовательно, должны быть последовательными (не просто некоторые случайные числа). Поскольку производные классы создаются пользователем, идентификатор не может быть членом Derived_N
. Поэтому я придумал класс DerivedType
.
class DerivedType
{
static unsigned id;
unsigned m_id;
public:
DerivedType() : m_id(id++) { }
}
Теперь я хочу создать сопоставление между Derived_N
и DerivedType
.
Всякий раз, когда создается Derived_N
, это сопоставление выглядит, если DerivedType
для конкретного Derived_N
уже существует и возвращает его, в противном случае создавайте новые и сохраняйте на карте.
Актуальный вопрос:
Можно ли использовать std::map
с типом данных как ключ на карте?
Я не боюсь никакого решения шаблона-метапрограммы.
Или есть элегантный способ достижения моей цели?
изменить Тип даты → Тип данных, я имею в виду как ClassType, извините:)
Я хочу использовать его как:
Derived_5 d;
DerivedType dt = getType(d); //Derived_5 is looked up in map, returning particular DerivedType
dt.getId();
каждый экземпляр Derived_N
(с тем же "N" ) должен иметь один и тот же идентификатор DerivedType
EDIT2 - МОЙ ОТВЕТ
Я нашел лучшее решение для своей проблемы... Это примерно так:
atomic_counter s_nextEventClassID;
typedef int cid_t;
template<class EventClass>
class EventClassID
{
public:
static cid_t getID()
{
static cid_t classID = EventClassID::next();
return classID;
}
static cid_t next() { return ++s_nextEventClassID; }
};
так как мой вопрос заключался в том, как использовать тип данных на карте, я отмечу некоторые ваши ответы, спасибо
Ответы
Ответ 1
С++ 11 разрешает это, предоставляя std::type_index
, в <typeindex>
, который является копируемым, сопоставимым и хешируемым объектом, построенным из объекта std::type_info
, который может использоваться как ключ в ассоциативных контейнерах.
(Реализация довольно проста, поэтому, даже если у вас нет С++ 11, вы можете украсть реализацию, скажем, GCC 4.7, и использовать ее в своем собственном коде.)
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
typedef std::unordered_map<std::type_index, int> tmap;
int main()
{
tmap m;
m[typeid(main)] = 12;
m[typeid(tmap)] = 15;
}
Ответ 2
Вы можете напрямую использовать typeid(object)
, так как существует type_info::before
, который может использоваться как компаратор, если вы используете key_info как ключ на карте, см. Что такое` type_info:: до `полезно для?. Не нужно получать .name()
.
Ответ 3
Вы можете использовать любой тип или класс в качестве ключа для std::map
, если вы дадите аргументам шаблона функцию сравнения, которая сообщает ему, как сортировать базовое дерево.
Проще всего сделать IMHO для представления дат как ключей, это преобразовать их в временные метки unix, но независимо от их представления класса просто предоставить функцию сравнения для определения карты, и вы хорошо перейти.