简体   繁体   中英

C++ questions about hashtable

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;
}

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...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM