Hash Map有两个关键方法:哈希值计算方法和比较方法。以STLPort为例,通过Hash Map的模版定义可以看出,其缺省的哈希Functor是hash,比较functor为equal_to:
- template <class _Key, class _Tp, _STLP_DFL_TMPL_PARAM(_HashFcn,hash<_Key>),
- _STLP_DFL_TMPL_PARAM(_EqualKey,equal_to<_Key>),
- _STLP_DEFAULT_PAIR_ALLOCATOR_SELECT(_STLP_CONST _Key, _Tp) >
- class hash_map
在_hash_fun.h中有针对各种类型的哈希值计算特化版本,下面仅摘录针对C字符串的代码:
- inline size_t __stl_hash_string(const char* __s) {
- _STLP_FIX_LITERAL_BUG(__s)
- unsigned long __h = 0;
- for ( ; *__s; ++__s)
- __h = 5*__h + *__s;
-
- return size_t(__h);
- }
-
- _STLP_MOVE_TO_STD_NAMESPACE
-
- _STLP_TEMPLATE_NULL
- struct hash<char*> {
- size_t operator()(const char* __s) const {
- _STLP_FIX_LITERAL_BUG(__s)
- return _STLP_PRIV __stl_hash_string(__s);
- }
- };
-
- _STLP_TEMPLATE_NULL
- struct hash<const char*> {
- size_t operator()(const char* __s) const {
- _STLP_FIX_LITERAL_BUG(__s)
- return _STLP_PRIV __stl_hash_string(__s);
- }
- };
__stl_hash_string实现了一个简单的哈希算法,因为算法中使用了字符的ASCII码,为了达到大小写不敏感的目的,可将每个字符转换成小写/大写来计算。对于hash functor,我们也需要一个string的特化版。
在_function_base.h中定义了equal_to functor:
- template <class _Arg1, class _Arg2, class _Result>
- struct binary_function {
- typedef _Arg1 first_argument_type;
- typedef _Arg2 second_argument_type;
- typedef _Result result_type;
- #if !defined (__BORLANDC__) || (__BORLANDC__ < 0x580)
- protected:
- /* See unary_function comment. */
- ~binary_function() {}
- #endif
- };
-
- template <class _Tp>
- struct equal_to : public binary_function<_Tp, _Tp, bool> {
- bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; }
- };
通过定制一个string版本的equal_to,使用stricmp进行字符串比较。下面列出实现及测试代码:
Test Codes
- #include <hash_map>
- #include <string>
- #include <algorithm>
- #include <cctype>
-
- inline size_t __stl_hash_string(const char* __s)
- {
- unsigned long __h = 0;
- for ( ; *__s; ++__s)
- __h = 5*__h + tolower(*__s);
-
- return size_t(__h);
- }
-
- template<>
- struct stlport::hash<stlport::string>
- {
- size_t operator()(const stlport::string& __s) const
- {
- return __stl_hash_string(__s.c_str());
- }
- };
-
- template<>
- struct stlport::equal_to<stlport::string>
- : public stlport::binary_function<stlport::string , stlport::string , bool>
- {
- bool operator()(const stlport::string& __x, const stlport::string& __y) const
- {
- return !_stricmp(__x.c_str() , __y.c_str());
- }
- };
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- stlport::hash_map<stlport::string , int> map;
-
- map.insert(stlport::make_pair("Test" , 123));
-
- stlport::hash_map<stlport::string , int>::iterator iter = map.find("teSt");
- if(iter != map.end())
- printf("Found!\n");
-
- return 0;
- }