Используйте тип данных (тип класса) в качестве ключа на карте - PullRequest
27 голосов
/ 25 марта 2012

У меня есть класс Base и классы Derived_1, Derived_2 ... Мне нужны производные классы, чтобы иметь идентификатор.Эти идентификаторы используются для дальнейших поисков и т. Д. И, следовательно, должны быть последовательными (а не просто случайными числами).Поскольку производные классы создаются пользователем, идентификатор не может быть членом 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 с типом данных как ключ на карте?Я не боюсь ни одного шаблона-метапрограммы.Или есть элегантный способ достижения моей цели?

edit Тип даты -> Тип данных, я имею в виду, как 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 - МОЙ ОТВЕТ Iнашел лучшее решение для моей проблемы ... Это так:

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; }
};

, поскольку мой вопрос был о том, как использовать тип данных на карте, я отмечу некоторые из ваших ответов, спасибо

Ответы [ 3 ]

62 голосов
/ 25 марта 2012

C ++ 11 решает эту проблему, предоставляя std::type_index в <typeindex>, который является копируемым, сопоставимым и хэшируемым объектом, созданным из объекта std::type_info, который может использоваться в качестве ключа в ассоциативных контейнерах.

(Реализация довольно проста, поэтому, даже если вы сами не имеете C ++ 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;
}
14 голосов
/ 25 марта 2012

Вы можете использовать typeid(object) напрямую, поскольку есть type_info::before, который можно использовать в качестве компаратора, если вы используете type_info в качестве ключа на карте, см. Для чего полезна `type_info :: before`? .Не нужно получать .name().

0 голосов
/ 25 марта 2012

Вы можете использовать любой тип или класс в качестве ключа для std::map, если вы передаете аргументам шаблона функцию сравнения, которая сообщает ему, как сортировать базовое дерево.

Самый простой способ сделать IMHO для представления дат в виде ключей - это преобразовать их в метки времени Unix, но независимо от их представления в классе, просто предоставьте функцию сравнения с определением карты, и вы хорошо идти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...