我需要使用字符串作为ID来获取某个对象。在运行时实现这一点,并且运行良好。但由于显而易见的原因,这使得静态类型检查变得不可能。
我已经用Google搜索了在编译时计算字符串哈希值的算法:C++ compile-time string hashing with Boost.MPL。
这似乎是我问题的完美解决方案,除了算法所必需的sring应该被分成4个字符或逐个字符,原因显而易见。
,而不是ID的通常当前记录,我将不得不这样写:
hash_cstring<boost::mpl::string<'obje', 'ct.m', 'etho', 'd'>>::value
这绝对无法使用。
问题是,如何正确地将"object.method"
之类的字符串传递给此算法?
谢谢大家。
答案 0 :(得分:8)
使用gcc-4.6的解决方案:
#include <iostream>
template<size_t N, size_t I=0>
struct hash_calc {
static constexpr size_t apply (const char (&s)[N]) {
return (hash_calc<N, I+1>::apply(s) ^ s[I]) * 16777619u;
};
};
template<size_t N>
struct hash_calc<N,N> {
static constexpr size_t apply (const char (&s)[N]) {
return 2166136261u;
};
};
template<size_t N>
constexpr size_t hash ( const char (&s)[N] ) {
return hash_calc<N>::apply(s);
}
int main() {
char a[] = "12345678";
std::cout << std::hex << hash(a) << std::endl;
std::cout << std::hex << hash("12345678") << std::endl;
}
http://liveworkspace.org/code/DPObf
我很高兴!
答案 1 :(得分:5)
我不知道使用预处理器或模板的方法。我怀疑你最好的办法是创建一个单独的预编译步骤(比如用perl或者这样)来从一组源语句中生成hash_cstring
语句。然后,至少你不必在添加新字符串时手动拆分字符串,并且生成完全自动化且可重复。
答案 2 :(得分:1)
可以使用任何外部符号实例化模板,因此这应该按预期工作:
external char const* object_method = "object.method";
... = hash_cstring<object_method>::value;
(假设模板hash_cstring<>
能够处理指针值)。
答案 3 :(得分:1)
如果有人感兴趣,我将介绍如何使用C ++ 11 constexpr函数和变量模板在这里创建Murmur3_32的编译时哈希:
http://roartindon.blogspot.sg/2014/10/compile-time-murmur-hash-in-c.html
我见过的大多数示例都是处理基于一次消耗字符串的一个字符的哈希值。 Murmur3_32哈希值更有趣一点,它一次消耗4个字符,需要一些特殊的大小写代码来处理剩余的0,1,2或3个字节。