Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile time string hashing

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.

  • Is this possible?
  • What would the operator look like?

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.

like image 702
deft_code Avatar asked Jan 21 '10 18:01

deft_code


People also ask

Is std hash constexpr?

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.

Which string hashing is best?

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.


1 Answers

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!

like image 84
Clement JACOB Avatar answered Sep 28 '22 09:09

Clement JACOB