《STL源码剖析》的5.7.7 hash function一节中介绍了<stl_hash_fun.h>中定义了数个现成的hash函数,全都是仿函数。这些hash函数支持的模板类型包括:char*, const char*, char, unsigned char, signed char, short, unsigned short, int , unsigned int, long, unsigned long。这些不同类型的hash函数是通过对一下类模板实例化得到的:
template<class T> struct hash { }
__STL_TEMPLATE_NULL struct hash<short> { size_t operator() (short x) const { return x; } };
inline size_t __stl_hash_string(const char *s) { unsigned long h = 0; for ( ; *s; ++s) h = 5*h + *s; return size_t(h); } __STL_TEMPLATE_NULL struct hash<char *> { size_t operator() (const char * s) const { return __stl_hash_string(s); } };
由此可见,SGI STL的hashtable无法处理除上述类型以外的元素,例如string, double, float等。也就是说,如果定义unordered_set<string>,并向其中添加string对象时,编译无法通过。因为unordered_set内部使用的就是hashtable,并且没有内置的hash函数来处理string类型。
unordered_set的类定义如下:
template <class Value, class HashFcn = hash<Value>, class EqualKey = equal_to<Value>, class Alloc = alloc> class unordered_set { };
#include <unordered_set> #include <iostream> #include <string> #include <assert.h> using namespace std; template<> //模板实例化 struct hash<string> { size_t operator()(string str) { unsigned long h = 0; for(string::size_type i = 0; i != str.size(); i++) { h = 5*h + str[i]; } return size_t(h); } }; int main () { unordered_multiset<string> ihs; string str; cout << ihs.bucket_count() << endl; ihs.insert(string("abc")); ihs.insert(string("def")); str.assign("kkk"); ihs.insert(str); ihs.insert("abc"); assert(ihs.find(str) != ihs.end()); for(unordered_multiset<string>::iterator it = ihs.begin(); it != ihs.end(); it++) { cout << *it << endl; } system("pause"); }
原文地址:http://blog.csdn.net/lc_910927/article/details/45286859