由于无序关联容器仅对内置类型进行了模版特化,自定义类型直接使用无序关联容器存储会出错,故此时需要对无序关联容器的希类模版进行重载(特化)。
构造函数
由其构造函数可知其基本构造方式,可以直接传入类型,适用于内置类型;或传入类型,以及自定义的哈希函数、判等函数(由于其无序排列,故只需判等)、内存分配器。
VS中哈希函数源码
一层一层拨开他的心后可以看见默认哈希函数的源码,其实就是进行了自异或和自乘操作,最终得出索引。
VS中equal_to源码
equal_to源码则更多简略,直接对两个对象进行判等。
代码实例
#include <iostream>
#include <unordered_set>
using std::cout;
using std::endl;
using std::ostream;
using std::unordered_set;
template <typename Container>
void display(const Container& con)
{
for (auto& elem : con)
{
cout << elem << " ";
}
cout << endl;
}
//测试用类
class Point
{
public:
Point(int ix = 0, int iy = 0) : _ix(ix), _iy(iy) {}
double getDistance() const
{
return hypot(_ix, _iy);
}
int getX() const
{
return _ix;
}
int getY() const
{
return _iy;
}
friend ostream& operator<<(ostream& os, const Point& cls);
private:
int _ix;
int _iy;
};
ostream& operator<<(ostream& os, const Point& cls)
{
os << "(" << cls._ix
<< ", " << cls._iy
<< ")";
return os;
}
//哈希函数,函数对象特化
#if 1
namespace std
{
template <>
struct hash<Point>
{
size_t operator()(const Point& rhs) const
{
cout << "size_t operator()(const Point &) const" << endl;
//不可描述的操作,反正返回索引。
return (rhs.getX() << 1) ^ (rhs.getY() << 2);
}
};//end of struct hash
}//end of namespace std
#endif
//自定义哈希方法,函数对象形式
struct HashPoint
{
size_t operator()(const Point& rhs) const
{
cout << "size_t HashPoint::operator()(const Point &) const" << endl;
return (rhs.getX() << 1) ^ (rhs.getY() << 2);
}
};
//判等,函数对象特化
#if 0
namespace std
{
template <>
struct equal_to<Point>
{
bool operator()(const Point& lhs, const Point& rhs) const
{
cout << "bool equal_to::operator()(const Point &, const Point &) const" << endl;
return ((lhs.getX() == rhs.getX()) && (lhs.getY() == rhs.getY()));
}
};
}//end of namespace std
#endif
//==运算法重载
#if 0
bool operator==(const Point& lhs, const Point& rhs)
{
cout << "bool operator==(const Point &, const Point &)" << endl;
return ((lhs.getX() == rhs.getX()) && (lhs.getY() == rhs.getY()));
}
#endif
//自定义判等方法,函数对象形式
struct HashEqualTo
{
bool operator()(const Point& lhs, const Point& rhs) const
{
cout << "bool HashEqualTo::operator()(const Point &, const Point &) const" << endl;
return ((lhs.getX() == rhs.getX()) && (lhs.getY() == rhs.getY()));
}
};
void test()
{
// unordered_set<Point, HashPoint, HashEqualTo> number
unordered_set<Point> number = {
Point(1, 2),
Point(-1, 2),
Point(1, -2),
Point(1, 2),
Point(3, 4),
Point(-3, 5),
};
display(number);
//结果
/*
size_t operator()(const Point &) const
size_t operator()(const Point &) const
size_t operator()(const Point &) const
bool equal_to::operator()(const Point &, const Point &) const
size_t operator()(const Point &) const
bool equal_to::operator()(const Point &, const Point &) const
size_t operator()(const Point &) const
bool equal_to::operator()(const Point &, const Point &) const
size_t operator()(const Point &) const
bool equal_to::operator()(const Point &, const Point &) const
bool equal_to::operator()(const Point &, const Point &) const
(1, -2) (1, 2) (-3, 5) (3, 4) (-1, 2)
*/
}
int main(void)
{
test();
return 0;
}