compile time hash (Adler-32)
-
EDIT: falschrum durch den string zu gehen, war nicht so schlau.
Jetzt fehlt mir noch etwas, mit dem ich das parameter pack umdrehen kann.#include <iostream> #include <boost/preprocessor/repetition/repeat.hpp> #define GET_STR_AUX(_, i, str) (sizeof(str) > (i) ? str[(i)] : 0), // BOOST_PP_REPEAT verwendet hier 3 wegen des Beispiels // So kann ich den hash nachprüfen, sonst würden noch weitere nullen reingeschoben #define GET_STR(str) BOOST_PP_REPEAT(3,GET_STR_AUX,str) 0 #define MOD_ADLER 65521 template <char C, char... List> struct const_hash { const static uint32_t s1 = (const_hash<List...>::s1 + C) % MOD_ADLER; const static uint32_t s2 = (const_hash<List...>::s2 + s1) % MOD_ADLER; const static uint32_t value = (s2 << 16) | s1; }; template <char C> struct const_hash <C> // C = '\0' { const static uint32_t s1 = 1; const static uint32_t s2 = 0; const static uint32_t value = (s2 << 16) | s1; }; #define HASH(STRING) const_hash<GET_STR(STRING)>::value int main() { std::cout << std::hex << HASH("CBA"); // CBA für ABC, jetzt muss ich noch was zum umdrehen basteln return 0; }
-
Du brauchst hier kein Boost.PP! Das ist ein Zweizeiler, den du selber schreibst!
-
Ich habe versehentlich rauseditiert, dass ich kein constexpr habe
Sonst wäre das Kindergarten.
-
Ich habe versehentlich rauseditiert, dass ich kein constexpr habe
Das brauchst du dafür auch nicht. Das sind zwei Makros in diesem Beispiel, sonst ein paar mehr.
-
Zunächst erstmal zu meinem eigentlichen Problem:
#include <iostream> #include <boost/preprocessor/repetition/repeat.hpp> #define GET_STR_AUX(_, i, str) (sizeof(str) > (i)+1 ? str[sizeof(str)-(i)-2] : 0), #define GET_STR(str) BOOST_PP_REPEAT(64,GET_STR_AUX,str) 0 #define MOD_ADLER 65521 template <char C, char... List> struct const_hash { const static uint32_t s1 = (C!=0)?((const_hash<List...>::s1 + C) % MOD_ADLER):(1); const static uint32_t s2 = (C!=0)?((const_hash<List...>::s2 + s1) % MOD_ADLER):(0); const static uint32_t value = (s2 << 16) | s1; }; template <char C> struct const_hash <C> { const static uint32_t s1 = 1; const static uint32_t s2 = 0; const static uint32_t value = (s2 << 16) | s1; }; #define HASH(STRING) const_hash<GET_STR(STRING)>::value int main() { std::cout << std::hex << HASH("ABCDEF") << "\n"; return 0; }
Dies reversed die Anordnung automatisch und ignoriert folgende Nullen.
Das mit dem Makro überlege ich mir. Ich finde den Präprozessor ein wenig... anstrengend
EDIT: ich plane nicht strings zu hashen, die ein '\0' in der Mitte haben.
EDIT 2: Hat sich sowieso erledigt. Ein kleiner Test hat ergeben, dass
__const_adler32<"str"[sizeof("str")-(0)-2]>::value;
für Visual Studio 2013 nicht gültig ist, da "str"[sizeof("str")-(0)-2]
keine compile-time constant expression ist
-
keine compile-time constant expression ist
Ist natürlich falsch.
Der Möglichkeit nach hast du noch eine andere Option, die ist aber relativ ungünstig: Global ein char-Array deklarieren, und dann einen Zeiger darauf an das Template übergeben.