Search code examples
c++constexprconsteval

Calculate 'const char *' string hash at compile-time


I have a function that calculates the hash of a string literal:

inline consteval uint64_t HashLiteral(const char* key)
{
   // body not important here...
   return 0;
}

In another function I need both the literal string, and its hash which I want to have calculated at compile-time:

void function(const char* s)
{
   worker(s, HashLiteral(s));
}

It seems however be impossible to make such a call like function("string") and have the hash calculated in its body at compile-time. The best I came up for now is using a macro, and redefine the function:

#define MakeHashParms(s)   s,HashLiteral(s)
void function(const char* s, const uint64_t hash)
{
   worker(s, hash);
}
function(MakeHashParms("string"));

Is a more straightforward solution possible?


Solution

  • You could modify function to accept a "hashed string" structure which can be implicitly constructed from a const char*. If you make the conversion constructor consteval, you can guarantee that the hash is always computed at compile time.

    #include <cstdint>
    
    inline consteval std::uint64_t HashLiteral(const char*)
    {
       // body not important here...
       return 0;
    }
    
    struct HashedString {
        const char* str;
        std::uint64_t hash;
    
        consteval HashedString(const char* s)
            : str{s}, hash{HashLiteral(s)} {}
    };
    
    void worker(const char*, std::uint64_t) {};
    
    void function(HashedString s)
    {
        worker(s.str, s.hash);
    }
    
    int main() 
    {
        function("string");  // OK: hash computed at compile time
    
        const char* x = "runtime string";
        // function(x);      // error: x is not constant expression
    }
    

    Try it online on godbolt