使用GCC 4.4(通常是适用于Android和IOS的最大值)有一种方法可以对字符串进行编译时散列。
我们有一个资源管理器将字符串键映射到资源。虽然查找速度很快,但散列和字符串创建速度很慢。类似的东西:
ResourcesManager::get<Texture>("someKey");
花费大量时间分配字符串“someKey”然后对其进行散列。
我想知道是否有一个技巧可以在编译时使用它来散列它。
答案 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等。