2011-09-17 11 views
5

Muszę użyć ogromnego słownika z całkowitymi (lub enum) kluczami i wartościami łańcuchów. Ale to jest całkowicie stałe. Nie ma możliwości zmiany w czasie wykonywania. Czy istnieje sposób (przy użyciu szablonów itp.) Do pobierania danych słownika podczas kompilacji zamiast korzystania z istniejącej struktury słownika?Którą strukturę danych użyć do ogromnego, ale stałego słownika w C++

+3

Skąd pochodzą dane? Szablony nie mogą na przykład odczytać z pliku. Tak więc najprawdopodobniej nie można tego zrobić w czasie kompilacji. –

+1

@Oli: zawsze można włączyć # pliki. –

+0

Nie mogą, ale może przed utworzeniem pliku można przekształcić plik konfiguracyjny w plik C++. automatyczne generowanie kodu może rozwiązać problem. –

Odpowiedz

5

Clang i LLVM rozwiązały twój problem, generując tabele zawierające ich obiekty, używając kombinacji generowania kodu i sztuczek preprocesora.

Można pominąć jeden krok, w zależności od konfiguracji. Na przykład:

// records.inc 
EXPAND_RECORD(Foo, "Foo", 4); 
EXPAND_RECORD(Bar, "Bar", 18); 
EXPAND_RECORD(Bar2, "Bar", 19); 

Teraz można wygenerować ENUM:

// records.h 
enum Record { 

#define EXPAND_RECORD(Name, String, Value) Name, 
#include "records.inc" 
#undef EXPAND_RECORD 

}; 

char const* getRecordName(Record r); 
int getRecordValue(Record r); 

// records.cpp 

char const* getRecordName(Record r) { 
    switch(r) { 
#define EXPAND_RECORD(Name, String, Value) case Name: return String; 
#include "records.inc" 
#undef EXPAND_RECORD 
    } 

    abort(); // unreachable, or you can return a "null" value 
} 

int getRecordValue(Record r) { 
    switch(r) { 
#define EXPAND_RECORD(Name, String, Value) case Name: return Value; 
#include "records.inc" 
#undef EXPAND_RECORD 
    } 

    abort(); // unreachable, or you can return a "null" value 
} 

W Clang i LLVM, faza generowania kodu jest używany do generowania .inc z przyjemniejszych plików definicji.

Działa całkiem nieźle ... ale należy pamiętać, że każda modyfikacja wyliczenia oznacza pełną rekompilację. Możesz chcieć przejść do podejścia "kodowania", w którym wyliczenie jest używane wewnętrznie, ale nigdy nie wyciekło na zewnątrz, a stabilne wartości (wyliczenia) są dostarczane klientowi (unsigned), tak aby dawni klienci mogli łączyć się z nowymi biblioteki bez rekompilacji: będą ograniczone do używania starego zestawu kodów, co nie stanowi problemu, jeśli jest stabilny.

3

pewnością można po prostu użyć sed do przekształcenia słownika w ciąg stałej indeksowanego przez parametr szablonu z pliku nagłówka jak:

template <int Index> struct Dictionary { static const char *entry; }; 

oraz pliku źródłowego z wielu wierszy o postaci:

template <> const char *Dictionary<5>::entry = "Entry for five"; 

Z drugiej strony, czy naprawdę chcesz to zrobić z perspektywy konserwacji? Pociąga za sobą rekompilację dla każdego zmienionego wpisu słownikowego i rozdętych rozmiarów plików wykonywalnych.

+0

* Bloated *: cóż, wpis musi być gdzieś, a przynajmniej mieć go w pamięci ROM oznacza, że ​​nie jest on duplikowany pomiędzy różnymi wystąpieniami programu (jeśli DLL). * Rekompilacja *: może to być problem, chyba że masz odpowiedni interfejs. –

0

Co powiesz na automatyczne generowanie kodu? Pobierz plik konfiguracyjny lub bazę danych lub jakiekolwiek inne źródło i wygeneruj z tego kod nagłówka C++. Może to wyglądać mniej więcej tak:

#define MYCONST_1 "#00ff00" 
#define MYCONST_10 "My other configuration string" 

można zrobić konwersję za pomocą prostego skryptu bash lub ruby ​​/ python (lub C++, jeśli jesteś masochistą), to zależy od złożoności pliku konfiguracyjnego.

Następnie napisz kilka reguł tworzenia, aby automatycznie tworzyć pliki nagłówkowe podczas zmiany pliku konfiguracyjnego.

+0

Mam wielkiego fana, który mnie ociąga, nie komentując nigdy .. –

+0

Oups przepraszam za to, gotowałem w tym czasie i obawiam się, że zapomniałem o komentarzu: x Po pierwsze, to nie adresuje enum <-> mapowania jednej joty. Drugi * proszę * nie używaj makr dla literałów/stałych, istnieją lepsze alternatywy (stała zewnętrzna, stała statyczna, itd ...). –

Powiązane problemy