2012-03-25 14 views
20

Mam klasy Base i klasy Derived_1, Derived_2 ... Potrzebuję klas pochodnych, aby mieć identyfikator. Te identyfikatory są używane do dalszych wyszukiwań itp., A zatem muszą być kolejne (nie tylko niektóre liczby losowe). Ponieważ klasy pochodne są tworzone przez użytkownika, identyfikator nie może być członkiem Derived_N. Więc wymyśliłem klasę DerivedType.Użyj typu danych (typ klasy) jako klucza na mapie

class DerivedType 
{ 
    static unsigned id; 
    unsigned m_id; 
public: 
    DerivedType() : m_id(id++) { } 
} 

Teraz chcę utworzyć odwzorowanie pomiędzy Derived_N i DerivedType. Po utworzeniu Derived_N to mapowanie wygląda, jeśli DerivedType dla konkretnej Derived_N już istnieje i zwraca je, w przeciwnym razie utwórz nowe i zapisuje na mapie.

Rzeczywiste pytanie: Czy jest jakiś sposób na wykorzystanie std::map z rodzaju danych jak klucza w mapie? Nie boję się żadnego rozwiązania szablon-metaprogram. Czy istnieje elegancki sposób na osiągnięcie mojego celu?

edit Data type -> Typ danych, to znaczy jak ClassType, przykro mi :)

Chcę go używać jak:

Derived_5 d; 
DerivedType dt = getType(d); //Derived_5 is looked up in map, returning particular DerivedType 
dt.getId(); 

każdy przypadek Derived_N (z tego samego " N ") powinny mieć ten sam identyfikator throu DerivedType

EDIT2 - moja odpowiedź znalazłem lepsze rozwiązanie dla mojego problemu ... to li ke to:

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

gdyż moje pytanie było jak używać typu danych w mapie, będę oznaczyć niektóre z twoich odpowiedzi, dziękuję

Odpowiedz

43

C++ 11 rozwiązuje ten problem przez dostarczenie std::type_index w <typeindex>, który jest copyable, porównywalne hashable przedmiot zbudowany z std::type_info obiektu, który może być użyty jako klucz w asocjacyjne.

(Implementacja jest dość prosta, więc nawet jeśli sam nie masz C++ 11, możesz wykraść implementację od, powiedzmy GCC 4.7, i użyć jej we własnym kodzie.)

#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; 
} 
+1

to powinna być zaakceptowana odpowiedź – jupp0r

+0

Bardzo dobra odpowiedź, która wykorzystuje nowoczesne C++ – Anonymous

0

Można użyć dowolnego typu lub klasy chcesz jako klucz do std::map , pod warunkiem podania argumentów szablonu funkcji porównania, która powie mu, jak posortować dane drzewo.

Najłatwiej zrobić IMHO, aby przedstawić daty jako klucze, to przekonwertować je na znaczniki czasu uniksowego, ale bez względu na to, jaka jest ich reprezentacja w klasie, po prostu podaj funkcję porównania z definicją mapy i jesteś dobry iść.

13

Można użyć typeid(object) bezpośrednio, ponieważ nie ma type_info::before, który może być używany jako komparatora jeśli używasz type_info jako klucz w mapie, patrz What is `type_info::before` useful for?. Nie musisz dostawać .name().

Powiązane problemy