Compile Time Hashing
1, Jul, 2015Compile time string hashing has been done to death since the AltDevBlogADay article and the Humus post. I couldn’t find an implementation that didn’t make it look far more complicated than it really is, so here’s my take:
#include <stdio.h> typedef unsigned int u32; // // Template version, evaluated at compile time in optimised builds // template <u32 N> constexpr u32 HashFNVConst(const char(&text)[N]) { return (HashFNVConst<N-1>((const char(&)[N - 1])text) ^ static_cast<u32>(text[N - 2])) * 16777619u; } template<> constexpr u32 HashFNVConst<1>(const char(&text)[1]) { return 2166136261u; } // // Loop version, evaluated at runtime // u32 HashFNV(const char* text) { u32 hash = 2166136261u; for (const char* c=text ; *c ; ++c) { hash = hash ^ static_cast<u32>(*c); hash *= 16777619u; } return hash; } int main() { const char * text = "Hello"; printf("0x%x (Loop version)\\n", HashFNV(text)); printf("0x%x (Template version)\\n", HashFNVConst("Hello")); return 0; }
This is a FNV1a hash. It uses constexpr so requires a C++11 compliant compiler (VS2015 or recent GCC / Clang). Here’s the obligatory disassembly:
printf("0x%x (Template version)n", HashFNVConst("Hello")); 0102106F push 0F55C314Bh <--- The hash 01021074 push 1022128h 01021079 call printf (01021010h)