I have read in few different places that using C++11's new string literals it might be possible to compute a string's hash at compile time. However, no one seems to be ready to come out and say that it will be possible or how it would be done.
I'm particularly interested use cases like this.
void foo( const std::string& value ) { switch( std::hash(value) ) { case "one"_hash: one(); break; case "two"_hash: two(); break; /*many more cases*/ default: other(); break; } }
Note: the compile time hash function doesn't have to look exactly as I've written it. I did my best to guess what the final solution would look like, but meta_hash<"string"_meta>::value
could also be a viable solution.
With C++20, std::vector and std::string are becoming constexpr. It doesn't seem like too much of a stretch to imagine that the other containers , e.g unordered_map, might also become constexpr. Making unordered_map constexpr will require a constexpr std::hash.
If you just want to have a good hash function, and cannot wait, djb2 is one of the best string hash functions i know. it has excellent distribution and speed on many different sets of keys and table sizes. you are not likely to do better with one of the "well known" functions such as PJW, K&R[1], etc.
This is a little bit late, but I succeeded in implementing a compile-time CRC32 function with the use of constexpr
. The problem with it is that at the time of writing, it only works with GCC and not MSVC nor Intel compiler.
Here is the code snippet:
// CRC32 Table (zlib polynomial) static constexpr uint32_t crc_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, ... }; template<size_t idx> constexpr uint32_t crc32(const char * str) { return (crc32<idx-1>(str) >> 8) ^ crc_table[(crc32<idx-1>(str) ^ str[idx]) & 0x000000FF]; } // This is the stop-recursion function template<> constexpr uint32_t crc32<size_t(-1)>(const char * str) { return 0xFFFFFFFF; } // This doesn't take into account the nul char #define COMPILE_TIME_CRC32_STR(x) (crc32<sizeof(x) - 2>(x) ^ 0xFFFFFFFF) enum TestEnum { CrcVal01 = COMPILE_TIME_CRC32_STR("stack-overflow"), };
CrcVal01
is equal to 0x335CC04A
Hope this will help you!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With