Reputation: 497
I am trying to write a program that uses hashtable in C++. The basic idea is that I have many data points, and I want to use a hashtable so that given a new point, I could know if it already exists or not. But there is some bug in it and I really don't how to fix it. (Error message : passing 'const Point' as 'this' argument of 'bool Point::operator==(const Point&)' discards qualifiers) Thanks in advance.
#include <iostream>
#include <unordered_map>
using namespace std;
class Point {
public:
Point(int _x, int _y):x(_x), y(_y) {}
bool operator==(const Point& lhs)
{ return this->x==lhs.x && this->y ==lhs.y; }
private:
int x;
int y;
};
int main ()
{
Point p1=Point(1,2);
Point p2=Point(2,3);
Point p3=Point(4,5);
unordered_map<Point,bool> mymap = {{p1,true},{p2,true},{p3,true} };
Point p4=Point(1,2);
unordered_map<Point,bool>::const_iterator got = mymap.find(p4);
if (got == mymap.end())
cout << "not found";
else
cout << "already exists";
cout<<endl;
return 0;
}
Upvotes: 2
Views: 175
Reputation: 17936
Declare operator==
itself as const
.
bool operator==(const Point& lhs) const // add this 'const' at the end
The const
qualifier on the operator's function tells the compiler that this
will also be treated as const
.
Once you've done that, you need to write a hashing function for class Point
. You can do that one of two ways. One is to make a dedicating hashing class, and the other is to specialize std::hash<>. Both methods are described here: http://en.wikipedia.org/wiki/Unordered_associative_containers_%28C%2B%2B%29#Custom_hash_functions
Edit: Here's an example of providing a template specialization for hash<Point>
that calls back to a hashing method in Point
. Note that the hashing function I wrote is arbitrary—you should experiment and figure out a good hashing function for your purposes.
class Point {
public:
Point(int _x, int _y):x(_x), y(_y) {}
bool operator==(const Point& lhs) const
{ return this->x==lhs.x && this->y ==lhs.y; }
size_t hash() const
{
return (x * 0xAAAA) ^ (y * 0x5555);
}
private:
int x;
int y;
};
namespace std
{
template <> class hash<Point>
{
public:
size_t operator()( const Point &p ) const
{
return p.hash();
}
};
}
The reason std::hash<Point>::operator()
calls back to the Point::hash()
method is that the members being hashed (x
and y
) are private
to Point
. There are other ways to handle the access control policies, but this seems fairly clean.
This particular protocol (hashing member in a class forwarded to by a specialization of std::hash<>
) seems like it'd lend itself to an adaptor paradigm. I unfortunately don't have my copy of Josuttis' C++11 reference handy ( http://www.cppstdlib.com/ ) to see if I'm reinventing the wheel...
Upvotes: 3