2011-02-12 23 views
12

我需要使用一个字符串作为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"这个算法?

谢谢大家。

+1

可以使用结构直接与静态字符串,而不是字符串?也许是一个宏也可以产生它们? – Anycorn 2011-02-12 04:19:24

+1

@aaa:宏不分割标记,它们可以串联或连接它们,但不能分割它们。 – 2011-02-12 10:26:19

回答

7

解决方案用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

我真的快乐!

5

我不知道的方式与预处理器或模板来做到这一点。我怀疑你最好的选择是创建一个单独的编译预处理步骤,产生从一组源语句的hash_cstring语句(与Perl或者这样说)。然后至少你不必在添加新字符串时手动分割字符串,并且这一代是完全自动化的,可重复的。

1

模板可以与任何外部符号被实例化,因此这应该按预期工作:

external char const* object_method = "object.method"; 
... = hash_cstring<object_method>::value; 

(给出的模板hash_cstring<>能够应对指针值)。

0

如果有人有兴趣,我通过了如何使用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个字节。