2010-11-12 15 views
7

Chcę zadeklarować kilka rodzajów (wewnętrznych do klasy matrycy na K i V i zapewniając pewne zachowanie buforowania):Jak przełamać ten okrągły typedef?

typedef std::map< 
    long long, 
    typename key_to_value_type::iterator // Ooops... not declared yet 
> timestamp_to_key_type; 

typedef std::map< 
    K, 
    std::pair<V,typename timestamp_to_key_type::iterator> 
> key_to_value_type; 

Oczywiście nie jest to możliwe, jak jest, bo z definicji kołowej . Mogę to zhakować za pomocą void*, ale zastanawiam się, czy jest jakaś magia do przekazywania zgłoszeń lub inna technika, która lepiej wykona zadanie.

(Tak, wiem, że boost::bimap odsunąłby problem).

+0

Czy próbujesz utworzyć mapę z danymi, a następnie indeks tej mapy w innej kolejności? (Przypuszczalnie dla szybkiego wyszukiwania) –

+0

Pojawiło się pytanie, podczas gdy wygłupiałem się z jakimś działającym już kodem LRU-caching (w zasadzie mapą klucz-wartość uzupełnioną o śledzenie, więc najmniej używane ostatnio rekordy można oczyścić w razie potrzeby). Oryginalna wersja ma wartość każdej mapy, która zawiera typ klucza drugiej mapy, ale niektóre dostępy O (log n) mogą zostać zmiażdżone w celu bezpośredniego dostępu do iteratora za pomocą powyższego formularza. Ale nie chcę, aby to pytanie zmieniło się w debatę na temat zalet implementacji pamięci podręcznej LRU! To bardziej, że zdałem sobie sprawę, że nie wiem, jak najlepiej radzić sobie z tego rodzaju problemu typedef/forward-declaration. – timday

+0

+1 To dobre pytanie. Gdybym tylko wiedział, jaki typ chcesz wyrazić. – wilhelmtell

Odpowiedz

7

To nie jest możliwe, należy rozważyć jakie byłyby typy:

timestamp_to_key_type 
= map< long long, key_to_value_type::iterator > 
= map< long long, map< K, pair< V, timestamp_to_key_type::iterator > >::iterator > 
= map< long long, map< K, pair< V, map< long long, map< K, pair< V, map< long long, map< K, pair < V ... 

To nie jest problem z przodu deklaracji, jesteś prosty próbuje opisać typ, który jest zdefiniowany rekurencyjnie na siebie. Nie różni się od:

struct A { B b; }; 
struct B { A a; }; 

Jedynym sposobem obejścia tego problemu jest utrata informacji statycznych. Jak już powiedziałeś, możesz użyć void* lub możesz spróbować zdefiniować swój własny, abstrakcyjny interfejs z wymazywanym typem. Twój wybór.

+0

nie jest to bardziej jak o każdej strukturze mają wskaźniki do innej struktury? Ma iteratory, a nie typ sam w sobie, więc nie sądzę, że problem leży w tym, że iteratory – rtpg

+2

niekoniecznie są wskaźnikami. Mogą być i często są klasami. Peter ma rację w swojej analizie. –

+0

Ma T = map , gdzie typ B jest zdefiniowany w terminach T. Nie jest strukturalnie rekurencyjny jak moja analogia, ale typy są rekursywne, a C++ nie obsługuje typów rekursywnych. –

1

Break okrągły z definicji tylko jeden z nich zawierający V, a drugi zawierający iterator:

typedef map<K, V> KVMap; 
typedef map<long long, typename KVMap::iterator> TSMap; 

Jeśli trzeba użyć klucza patrzeć znacznik czasu, a timestamp nie jest przechowywany w V, a następnie można powielać, że w KVMap:

typedef map<K, pair<V, long long> > KVMap; 

z K, można użyć KVMap :: znaleźć, uzyskać znacznik czasu, a następnie użyj TSMap :: znaleźć i uzyskać uchwyt na odpowiedniej pozycji (np. aby go wymazać).