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++
Odpowiedz
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.
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.
* 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. –
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.
Mam wielkiego fana, który mnie ociąga, nie komentując nigdy .. –
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 ...). –
- 1. Którą strukturę danych należy użyć do geokodowania?
- 2. Którą strukturę danych powinienem tu użyć?
- 3. Którą bazę danych należy użyć w pliku node.js?
- 4. Którą wartość błędu należy użyć?
- 5. Którą instalację Pythona należy użyć?
- 6. Trwałe vs nietrwałe - Którą powinienem użyć?
- 7. Którą bazę danych bazy danych w chmurze powinienem użyć w mojej aplikacji na Androida?
- 8. Którą ORM mam użyć zamiast Linq do Sql?
- 9. Którą bibliotekę wykresów .net powinienem użyć?
- 10. Usuwanie ogromnych ilości danych z ogromnego stołu
- 11. kopiowanie danych z ogromnego stołu produkcyjnego
- 12. Którą z zewnętrznych klas Imageview powinienem użyć?
- 13. Którą strukturę testów jednostkowych powinienem zacząć dla C# w Visual Studio 2008? (Aplikacja Windows Forms)
- 14. Którą metodę hashowania hasłem należy użyć?
- 15. Którą metodę należy użyć do ręcznego uruchomienia mojego AngularJS?
- 16. Konwersja słownika do kolekcji listy w C#
- 17. Zweryfikuj strukturę bazy danych? (SQLite w C++/Qt)
- 18. Lazy właściwości słownika w C#
- 19. obj-c dodaj c-struct do słownika
- 20. Czy mogę "rozszerzyć" strukturę w C?
- 21. Pad strukturę C++ do potęgi dwóch
- 22. Tworzenie ogromnego pliku dummy w masie sekund w C#
- 23. Prawidłowy sposób definiowania stałego ciągu C w C++?
- 24. Ramka danych pandy do zamówionego słownika
- 25. Czytanie słownika C# w JavaScript
- 26. Jak spłaszczyć strukturę w iskrowegowej ramce danych?
- 27. Elegancki sposób tworzenia zagnieżdżonego słownika w C#
- 28. Dopasuj wyrażenie regularne ze słownika w C#
- 29. Którą implementację zestawu bitów należy użyć dla uzyskania maksymalnej wydajności?
- 30. Nie można wyśledzić źródła ogromnego użycia pamięci
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. –
@Oli: zawsze można włączyć # pliki. –
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. –