编译时间Hashing C ++ 0x

时间:2012-07-09 18:34:19

标签: c++ compiler-construction hash

使用GCC 4.4(通常是适用于Android和IOS的最大值)有一种方法可以对字符串进行编译时散列。

我们有一个资源管理器将字符串键映射到资源。虽然查找速度很快,但散列和字符串创建速度很慢。类似的东西:

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

花费大量时间分配字符串“someKey”然后对其进行散列。

我想知道是否有一个技巧可以在编译时使用它来散列它。

3 个答案:

答案 0 :(得分:7)

您必须实现正确的散列算法,但这可以使用C ++ 11的constexpr函数:

#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;
}

然后你可能有ResourcesManager::get的重载,它取compile_time_hash的结果(在这种情况下是无符号的)。

这显然取决于您正在应用的散列算法。使用constexpr实现SHA *之类的东西会非常痛苦。

请注意,您需要GCC&gt; = 4.6或clang&gt; = 3.1才能使用constexpr。

答案 1 :(得分:2)

为了进行编译时散列,所有密钥都需要是编译时常量。

使用编译时常量进行索引的常用方法不是使用字符串,而是使用枚举类型。这样做的好处是根本不需要散列,因为常量是顺序的,可以直接索引数组。

enum KeyType
{
    someKey,
    someOtherKey
};

ResourcesManager::get<Texture>(someKey);

如果需要将密钥作为字符串获取,只需保留一个可由枚举常量索引的字符串表。

static char * keyNames = 
{
    "someKey",
    "someOtherKey"
};

答案 2 :(得分:0)

您始终可以编译程序来散列字符串并输出合适的源代码......

我自己,我实际上并没有对字符串进行哈希处理,我只是枚举项目并输出带枚举的头文件。好,容易,没有collisons等。