Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile Time Hashing C++0x

Using GCC 4.4 (generally the max available for Android and IOS) is there a way to do compile time hashing of strings.

We have a resource manager that maps string keys to resources. While the lookup is fast the hashing and string creation is slow. Something like:

 ResourcesManager::get<Texture>("someKey");

Spends a lot of time allocating the string "someKey" and then hashing it.

I'm wondering if there is a trick I can use to hash it at compile time.

like image 361
Halsafar Avatar asked Jul 09 '12 18:07

Halsafar


2 Answers

You'd have to implement the right hashing algorithm, but this could work using C++11's constexpr functions:

#include <iostream>

// Dummy hashing algorithm. Adds the value of every char in the cstring.
constexpr unsigned compile_time_hash(const char* str) {
    // Modify as you wish
    return (*str == 0) ? 0 : (*str + compile_time_hash(str + 1));
}   

int main() {
    unsigned some_hash = compile_time_hash("hallou");
    std::cout << some_hash << std::endl;
}

Then you could have an overload of ResourcesManager::get which takes the result of compile_time_hash(an unsigned, in this case).

This obviously depends on which hashing algorithm you're applying. Implementing something like SHA* using constexpr will be pretty painful.

Note that you require GCC >= 4.6 or clang >= 3.1 in order to use constexpr.

like image 114
mfontanini Avatar answered Oct 23 '22 11:10

mfontanini


In order to do compile-time hashing, all your keys will need to be compile-time constants.

The usual way of indexing with compile-time constants is not to use strings, but to use an enumeration type. This has the advantage of not requiring hashing at all, since the constants are sequential and can index an array directly.

enum KeyType
{
    someKey,
    someOtherKey
};

ResourcesManager::get<Texture>(someKey);

If there's a need to get the key as a string, just keep a table of strings that can be indexed by the enumeration constants.

static char * keyNames = 
{
    "someKey",
    "someOtherKey"
};
like image 30
Mark Ransom Avatar answered Oct 23 '22 11:10

Mark Ransom