problem
problem

Reputation: 13

Writing classes to be used with unordered_map.

I want to use the boost map and the documentation says I need an equality function and a hash function. I think understand what they should do but since I can't find any examples I'm not sure how to do it so I am looking for a trivial example, like a point class with members x, y or something close.

Edit: Finally got it working. Wish I hadn't had to waste so much time for this. Thanks anyway guys.

#include <boost/functional/hash.hpp>
#include <boost/unordered_map.hpp>
#include <boost/foreach.hpp>
#include <iostream>

namespace test { // class whose source i can't edit
    class point
    {
    public:
        float x;
        float y;
        point() : x(0), y(0) {}
        point(int x, int y) : x(x), y(y) {}
        point(float x, float y) : x(x), y(y) {}
        point(double x, double y) : x((float) x), y((float) y) {}

        bool operator==(point const& other) const
        {
            return x == other.x && y == other.y;
        }
    };
}

namespace test { // my source file
    std::size_t hash_value(point const &p) {
        boost::hash<int> hasher;
        return hasher(p.x) + hasher(p.y);
    }
} 

int main() {
    boost::unordered_map<test::point, std::string> myMap;
    test::point p1(1, 2);
    myMap[p1] = "1"; //now it works
    std::cout << myMap[p1] << std::endl;
    return 0;
}

Upvotes: 1

Views: 912

Answers (2)

6502
6502

Reputation: 114481

This is right from boost documentation...

class point
{
    int x;
    int y;
public:
    point() : x(0), y(0) {}
    point(int x, int y) : x(x), y(y) {}

    bool operator==(point const& other) const
    {
        return x == other.x && y == other.y;
    }
};

class point
{
    ...

    friend std::size_t hash_value(point const& p)
    {
        std::size_t seed = 0;
        boost::hash_combine(seed, p.x);
        boost::hash_combine(seed, p.y);

        return seed;
    }

    ...
};

Upvotes: 3

Puppy
Puppy

Reputation: 146910

Equality and hash aren't too tough to define. Equality:

class Point {
    int x, y;
    bool operator==(const Point& p) {
        return (x == p.x && y == p.y);
    }
};

Hashing tends to involve specializing a function or class.

template<> class boost::hash<Point> {
public:
    size_t operator()(const Point& p) {
        return boost::hash<int>(p.x) + boost::hash<int>(p.y);
    }
};

You may need to read up on the specifics of your hash_map implementation for details, and you may also want to define a different hash algorithm.

Upvotes: 3

Related Questions