Implement hash for custom class C++ - c++

I have a circle defined like so:
class Circle {
public:
int x;
int y;
int r;
Circle() : x(0), y(0), r(0) {}
Circle(int x, int y, int r) {
this->x = x;
this->y = y;
this->r = r;
}
double area() {
return PI * pow(r, 2);
}
};
I want to be able to add it to a set, based on the hash of its center (x and y)
What's the correct and idiomatic way of doing this in C++ 11?
My question is two-fold
(1) Is there a way I can ask C++ to hash it for me? In Kotlin, there is the notion of a dataclass which automatically hashes the class attributes. I am looking for something similar.
(2) If not, how do I hash it myself, and relatedly - what are operators I need to overload?

I want to be able to add it to a set, based on the hash of its center (x and y)
If you wan't to put your circle in the std::set, you don't need to provide a hash function. You need to provide it only if you'd like to use std::unordered_set or any other unordered associative container (more info in hash).
As it goes for the most idiomatic way of implementation, I would go with something like this (taken from the std::hash example):
#include <cmath>
#include <unordered_set>
#include <set>
class Circle {
public:
int x;
int y;
int r;
Circle() : x(0), y(0), r(0) {}
Circle(int x, int y, int r) {
this->x = x;
this->y = y;
this->r = r;
}
double area() {
return 3.1415 * pow(r, 2);
}
};
bool operator==(const Circle& lhs, const Circle& rhs) {
return lhs.x == rhs.x && lhs.y == rhs.y;
}
template<> struct std::hash<Circle> {
std::size_t operator()(Circle const& s) const noexcept {
std::size_t h1 = std::hash<int>{}(s.x);
std::size_t h2 = std::hash<int>{}(s.y);
return h1 ^ (h2 << 1); // or use boost::hash_combine (see Discussion) https://en.cppreference.com/w/Talk:cpp/utility/hash
}
};
int main() {
std::unordered_set<Circle> circles;
return 0;
}
Link to example
EDIT:
(1) Is there a way I can ask C++ to hash it for me? In Kotlin, there is the notion of a dataclass which automatically hashes the class attributes. I am looking for something similar.
There is hash function for the basic types (list is on std::hash). You need to provide hashing function for your custom type. You can take an inspiration from the cppreference or create an own hashing function.

Related

Doing conditional replacement using c++ macro?

For a struct point{float x,y,z;}, i want to define many functions, in each function, i do the same thing to x, y and z. For example, float size = 1 * x*y*z, float edge = 0+x+y+z...
So I'm wondering that, i could write a macro, or something, like
#define forxyz(codes) ???????
that when i write
forxyz(res=res+d;)
it calls res=res+x; res=res+y;res=res+z;
Urrr, lemme make it more clear. I have about 20 functions, each one is called for only one time, so I don't want to attach them to the struct. Moreover, it's not as simple as '+'. for example, i might have
x_in_middle(point a, point b, point c, float d){
if(b.x<a.x && a.x<c.x){
if(d>0) return a.x;
if(d<0) return a.x*a.x;
if(d==0) return 0;
}
}
and I'm finding a way to not to write
if(b.x<a.x && a.x<c.x){
if(d>0) return a.x;
if(d<0) return a.x*a.x;
if(d=0) return 0;
}
three times!
In this case res=res+d is pretty simple, but in my case it might be several lines of codes...and sometime i would want to call set_x, set_y, set_z functions...
So far, the best idea i could have is to make res=res+d another macro, namely
#define add(d) res=res+d
and then
add(x);
add(y);
add(z);
But this would obviously create too much macros, and i think it's not elegant...
A simple method is to write a freestanding function that takes points as parameters:
point add(const point& a, const point& b)
{
point c;
c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;
return c;
}
You would use this like:
point a, b, c;
//...
c = add(a, b);
You could also overload operator +:
point operator+(const point& a, const point& b)
{
point c;
c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;
return c;
}
Your usage may look like this:
point a, b, c;
//...
c = a + b;
This is the answer that answers the macro part and I would advise to provide operators overloads if possible and not to use macros in C++.
So first create your own small overloaded foreach macro that will apply a function on each argument:
#define M_FOREACH_1(func,_1) \
func(_1)
#define M_FOREACH_2(func,_1,_2) \
M_FOREACH_1(func,_1)func(_2)
#define M_FOREACH_3(func,_1,_2,_3) \
M_FOREACH_2(func,_1,_2)func(_3)
/// etc.
#define M_FOREACH_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) \
M_FOREACH_##N
#define M_FOREACH(func, ...) \
M_FOREACH_N(__VA_ARGS__,9,8,7,6,5,4,3,2,1)(func, __VA_ARGS__)
Then let's abstract it for some argument braced list that needs to be escaped, for verbosity:
#define M_FOREACHLIST_ESCAPE(...) \
__VA_ARGS__
#define M_FOREACHLIST_IN(func, ...) \
M_FOREACH(func, __VA_ARGS__)
#define M_FOREACHLIST(func, list) \
M_FOREACHLIST_IN(func, M_FOREACHLIST_ESCAPE list)
// now we can
// M_FOREACHLIST(some_macro, (x, y, z))
After that it's typicall to define a function for expansion, apply it foreach some arguments list:
#define list() (x, y, z)
#define add(arg) res = res + arg;
M_FOREACHLIST(add, list())
// generates res = res + x;res = res + y;res = res + z;
#undef add
#define sub(arg) res = res - arg;
M_FOREACHLIST(sub, list())
// generates res = res - x;res = res - y;res = res - z;
#undef sub
// etc.
and I'm finding a way to not to write ... three times!
Pass member pointer to the function...
float generic_in_middle(point a, point b, point c, float d, float point::* mp){
if (b.*mp < a.*mp && a.*mp < c.*mp){
if (d > 0) return a.*mp;
if (d < 0) return a.*mp * a.*mp;
if (d == 0) return 0;
}
// TODO: add code here so that function returns something
}
float x_in_middle(point a, point b, point c, float d) {
return generic_in_middle(a, b, c, d, &point::x);
}
// etc.
Delegate axis-specific public API functions to a common helper function or operator
As the three data members are all of the same type, and you want to implement re-usable, say, arithmetic operations applied on a single one of them, you could wrap the common arithmetic functionality in a private helper, and delegate publically expose axis-specific functions to the helper.
#include <iostream>
struct Point {
Point(float x, float y, float z) : x_(x), y_(y), z_(z) {}
float addX(const float a) const { return add(x_, a); }
float addY(const float a) const { return add(y_, a); }
float addZ(const float a) const { return add(z_, a); }
private:
static float add(const float lhs, const float rhs) {
// Long complex arithmetic code.
return lhs + rhs;
}
float x_;
float y_;
float z_;
};
int main() {
const Point p{1., 2., 3.};
std::cout << p.addY(0.5); // 2.5
return 0;
}
You could likewise resort to implementing the helper as a member function template with a a single pointer to member function non-type template parameter, and delegate calls to this function.
#include <iostream>
struct Point {
Point(float x, float y, float z) : x_(x), y_(y), z_(z) {}
float addX(const float a) const { return add<&Point::x_>(a); }
float addY(const float a) const { return add<&Point::y_>(a); }
float addZ(const float a) const { return add<&Point::z_>(a); }
private:
template <float Point::* lhs>
float add(const float rhs) const {
// Long complex arithmetic code
// on lhs.
return rhs + (this->*lhs);
}
float x_;
float y_;
float z_;
};
int main() {
const Point p{1., 2., 3.};
std::cout << p.addY(0.5); // 2.5
return 0;
}
(C++20) Looping over a known number of public members: structured bindings in a range-based for loop initialization statement
Another alternative, as a simple POD-type such as a point data type is likely to have data members with public access modifiers, as of C++20 we may combine structured bindings with range-based for loop initialization statements (the latter is a C++20 feature):
Grammar
for ( init-statement(optional) range-declaration : range-expression ) ...
Specifically, using structured bindings as the init-statement in a range-based for loop:
#include <iostream>
struct Point {
float x;
float y;
float z;
};
float add(const float lhs, const float rhs) {
// Long complex arithmetic code.
return lhs + rhs;
}
int main() {
const Point p{1., 2., 3.};
// For all members, do ...
for (auto [x, y, z] = p; auto e : {x, y, z}) {
std::cout << add(0.5, e) << " ";
} // 1.5 2.5 3.5
return 0;
}

Is there a way to compound functions in C++?

General question :
If there are two objects A and B with respective functions f_A(arg list) and f_B(arg list).
What's the best way to create an object C with a function compounded of f_A(...) and f_B(...) ?
for example : f_C() = f_A() + f_B() or f_C() = f_A(f_B())
Is it possible to overload the "+" operator such that we can create the object C doing something like that ?
auto object_c = object_a + object_b
Here is a sample of my code :
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
double covarianceFunction(
double X,
double Y
)
{
double result;
result = m_scale * exp(-norm(X - Y) / (m_sigma*m_sigma));
return result;
}
GaussianKernel operator+(const GaussianKernel& b) {
/*Here I would like to overload the + operator such that
I can create a kernel from two others kernels,
I mean with a covariance function compound of the previous ones
*/
}
private:
double m_sigma;
double m_scale;
};
Thanks you.
Given two methods f_A and f_B you can get f_C returning the sum of the others by using for example a lambda:
auto f_C = [](/*param*/){ return f_A(/*param*/) + f_B(/*param*/); };
auto sum_result = f_C(param);
To get the compound method it would be this:
auto f_C = [](/*param*/){ return f_B( f_A(/*param*/)); };
auto compound_result = f_C(param);
PS: I know that this is not directly applicable to your example, still trying to find out what exactly you want to do.
I would start with prototype solution like this:
class FooKernel : public Kernel {
public:
FooKernel (std::function<double(double, double)> fun) : fun_(fun) {}
double covarianceFunction(
double X,
double Y
) const {
return fun_(X, Y);
}
template<class T>
auto operator+(const T &b) const {
return FooKernel([b, this](double X, double Y){
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
private:
std::function<double(double, double)> fun_;
};
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
double covarianceFunction(
double X,
double Y
) const
{
double result;
result = m_scale * exp(-norm(X - Y) / (m_sigma*m_sigma));
return result;
}
template<class T>
auto operator+(const T &b) const {
return FooKernel([b, this](double X, double Y){
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
private:
double m_sigma;
double m_scale;
};
No longer lambdas are used, but now uses Your function as You wished.
Later on I would try to remove the std::function as it may have quite big performance impact. Instead I would make the FooKernel a class template, that stores callable by value.
I would suggest another subclass of Kernel:
class CompoundGaussianKernel : public Kernel {
public:
CompoundGaussianKernel(GaussianKernel const& kernel1, GaussianKernel const& kernel2)
: m_kernel1(kernel1), m_kernel2(kernel2)
{}
double covarianceFunction(double X, double Y)
{
return m_kernel1.covarianceFunction(X, Y) + m_kernel2.covarianceFunction(X, Y);
// or any other composition than "+"
}
private:
GaussianKernel m_kernel1;
GaussianKernel m_kernel2;
};
I recommend not to define operator+ inside of a class but as a free function.
CompoundGaussianKernel operator+(GaussianKernel const& kernel1, GaussianKernel const& kernel2)
{
return CompoundGaussianKernel(kernel1, kernel2);
}

Make a c++ class work with generic user defined inputs

I feel like this question must have been asked before but I couldn't find an answer from poking around on google. If it has please direct me to a link and I will remove this post.
Consider this minimal example that represents a larger problem I have. Say I created a simple "Point" and "Printer" class like so:
class Point {
public:
double x, y;
Point() {x = y = 0;}
Point(double x, double y) {
this->x = x; this->y = y;
}
};
template<typename T>
class Printer {
public:
T* mData;
int mSize;
// Constructor
Printer(std::vector<T> &input) {
mData = &input[0];
mSize = input.size();
}
// Simple Print function
void Print() {
printf(" - Showing %d items\n", mSize);
for (int i = 0; i < mSize; i++) {
const T &item = mData[i];
printf(" - Item %d: (%lf, %lf)\n", i, item.x, item.y);
}
}
};
I could use the printer class like this:
std::vector<Point> points; // fill the vector, and then...
Printer<Point> pointsPrinter(points); pointsPrinter.Print();
Now say someone else comes along and wants to use the Printer class with there own "Point" class declared like so:
class Pnt {
public:
double mX, mY;
// other stuff
};
If they try to do this:
vector<Pnt> pnts; // Fill the pnts, and then...
Printer<Pnt> pntsPrinter(pnts);
pntsPrinter.Print(); // COMPILE ERROR HERE!
Obviously this will fail because Pnt has no x or y members. Does there exist a way I can rewrite the Printer class to work with all generic user types? What I DONT want to do is copy a Pnt vector into a Points vector.
EDIT:
The only way I can think to make this work would be to pass in functions pointers. Something like this:
template<typename T>
class Printer {
public:
T* mData;
int mSize;
double* (*mXFunc) (T*);
double* (*mYFunc) (T*);
Printer(std::vector<T> &input,
double* (*xFunc) (T*),
double* (*yFunc) (T*))
{
mData = &input[0];
mSize = input.size();
mXFunc = xFunc;
mYFunc = yFunc;
}
void Print() {
printf(" - Showing %d items\n", mSize);
for (int i = 0; i < mSize; i++) {
T &item = mData[i];
printf(" - Item %d: (%lf, %lf)\n", i, *mXFunc(&item), *mYFunc(&item));
}
}
};
// Could then use it like so
inline double* getXPointVal(Point *point) {return &point->x;}
inline double* getYPointVal(Point *point) {return &point->y;}
inline double* getXPntVal(Pnt *point) {return &point->mX;}
inline double* getYPntVal(Pnt *point) {return &point->mY;}
Printer<Pnt> pntPrinter(pnts, getXPntVal, getYPntVal);
Printer<Point> pointsPrinter(points, getXPointVal, getYPointVal);
pntPrinter.Print();
pointsPrinter.Print();
The problem with this is that it looks ugly and also possibly introduces the function call overhead. But I guess the function call overhead would get compiled away? I was hoping a more elegant solution existed...
If you choose cout instead of printf to write your output, you can allow all printable types to define an overload for the << operator and use that generically inside Printer::print(). An overload could look like this:
std::ostream& operator<<(std::ostream &out, Point& p){
out << "Point(" << p.x << ", " << p.y << ")";
return out;
}
On a side note, I advise against storing a pointer to a vector's internal storage and size member. If the vector needs to reallocate, your pointer will be left dangling and invalid. Instead, you should pass the vector temporarily as a reference or keep a const reference.
You could define free (non-member) functions for each Point class you want to use. The advantage of this is that free functions can be defined later, without making changes to existing classes.
Example:
namespace A {
class Point {
public:
Point (int x, int y) : x_(x), y_(y) {}
int getX () const { return x_; }
int getY () const { return y_; }
private:
int x_, y_;
};
// in addition, we provide free functions
int getX (Point const & p) { return p.getX(); }
int getY (Point const & p) { return p.getY(); }
}
namespace B {
class Pnt {
public:
Pnt (int x, int y) : x_(x), y_(y) {}
int get_x () const { return x_; }
int get_y () const { return y_; }
private:
int x_, y_;
};
// Pnt does not have free functions, and suppose we
// do not want to add anything in namespace B
}
namespace PointHelpers {
// free functions for Pnt
int getX (Pnt const & p) { return p.get_x (); }
int getY (Pnt const & p) { return p.get_y (); }
}
// now we can write
template <class PointTy>
void printPoint (PointTy const & p) {
using PointHelpers::getX;
using PointHelpers::getY;
std::cout << getX (p) << "/" << getY (p) << std::endl;
}
A::Point p1 (2,3);
B::Pnt p2 (4,5);
printPoint (p1);
printPoint (p2);
If the free functions live in the same namespace as the corresponding class, they will be found by argument-dependent name lookup. If you do not want to add anything in that namespace, create a helper namespace and add the free functions there. Then bring them into scope by using declarations.
This approach is similar to what the STL does for begin and end, for instance.
Don't expect from the templates to know which members of given class/structure corresponds to your x and y...
If you want to create generic solution you could tell your printer function how to interpret given object as your Point class using e.g. lambda expression (c++11 solution):
#include <iostream>
class Point {
public:
double x, y;
Point() {x = y = 0;}
Point(double x, double y) {
this->x = x; this->y = y;
}
};
class Pnt {
public:
double mX, mY;
// other stuff
};
template <class P, class L>
void Print(const P &p, L l) {
Print(l(p));
}
void Print(const Point &p) {
std::cout << p.x << ", " << p.y << std::endl;
}
int main() {
Print(Point(1, 2));
Print(Pnt{4, 5}, [](const Pnt &p) -> Point {return Point(p.mX, p.mY);});
}

Named constructor idiom and new operator

I use the named constructor idiom to create objects, because I have lots of calls with identical parameters but the object shall be created differently.
The C++ FAQ tell us how to do this. It also tells us how to force objects being heap allocated. Yet it really fails to tell us how to use the named constructor idiom with the new operator.
Because new requires a constructor to be called we cannot directly call named constructors. So I found two workarounds to this problem:
I create an additional copy constructor and hope that optimizing compilers won't create a temporary object.
class point_t {
int X,Y;
point_t(int x, int y) : X(x), Y(y) { }
public:
point_t(const point_t &x) : X(x.X), Y(x.Y) { }
static point_t carthesian(int x, int y) { return point_t(x,y); }
static point_t polar(float radius, float angle) {
return point_t(radius*std::cos(angle), radius*std::sin(angle));
}
void add(int x, int y) { X += x; Y += y; }
};
int main(int argc, char **argv) {
/* XXX: hope that compiler doesn't create a temporary */
point_t *x = new point_t(point_t::carthesian(1,2));
x->add(1,2);
}
The other version is to create separate named constructors. Because function overloading doesn't work on return type I use two different names, which is ugly.
class point_t {
int X,Y;
point_t(int x, int y) : X(x), Y(y) { }
public:
/* XXX: function overloading doesn't work on return types */
static point_t carthesian(int x, int y) { return point_t(x,y); }
static point_t *carthesian_heap(int x, int y) { return new point_t(x,y); }
void add(int x, int y) { X += x; Y += y; }
};
int main(int argc, char **argv) {
point_t *x = point_t::carthesian_heap(1,2);
x->add(1,2);
}
Is there a prettier version that is equal to the example code?
You can avoid named constructor idiom for this completely, and do it using an additonal dummy enum parameter to select the constructor.
enum Carthesian {carthesian};
enum Polar {polar};
class point_t {
int X,Y;
public:
point_t(int x, int y) : X(x), Y(y) { } // may keep as a default
point_t(Carthesian, int x, int y) :X(x),Y(y){}
point_t(Polar, float radius, float angle)
: X (radius*std::cos(angle)), Y(radius*std::sin(angle)) {}
void add(int x, int y) { X += x; Y += y; }
};
int main(int argc, char **argv) {
point_t *x = new point_t(carthesian,1,2);
point_t *y = new point_t(polar,0,3);
x->add(1,2);
}
It is simple, portable, and the only overhead you will see is for the passing of the dummy enum values. In the rare case this overhead is too high for you it can be eliminated by wrapping a function call even when the construction itself is not inlined, as follows:
enum Carthesian {carthesian};
enum Polar {polar};
class point_t {
int X,Y;
void initCarthesian(int x, int y); // may be long, not inlined
void initPolar(float radius, float angle);
public:
point_t(int x, int y) : X(x), Y(y) { } // may keep as a default
point_t(Carthesian, int x, int y)
{initCarthesian(x,y);} // this is short and inlined
point_t(Polar, float radius, float angle) {initPolar(radius, angle);}
void add(int x, int y) { X += x; Y += y; }
};
Another approach is to use a derived class for construction. When using inner classes, it leads into quite a nice syntax I think:
class point_t {
int X,Y;
public:
struct carthesian;
struct polar;
point_t(int x, int y) : X(x), Y(y) { } // may keep as a default
void add(int x, int y) { X += x; Y += y; }
};
struct point_t::carthesian: public point_t
{
carthesian(int x, int y):point_t(x,y){}
};
struct point_t::polar: public point_t
{
polar(float radius, float angle):point_t(radius*std::cos(angle),radius*std::sin(angle)){}
};
int main(int argc, char **argv) {
point_t *x = new point_t::carthesian(1,2);
point_t *y = new point_t::polar(0,3);
x->add(1,2);
return 0;
}
You could write :
point_t *x = new point_t(point_t::carthesian(1,2));
It first calls carthesian() and then the copy-constructor.
Or, is there any problem in it? Perhaps, a bit slow?
By the way, there is one clear advantage in this code: the programmer can clearly see the new operator in his code (where he is using point_t written by someone else), so you can assume that its his responsibility to call delete once he is done with x.
Is this really a problem? In my experience classes tend to be either dynamically allocated most of the time or seldom, if at all. Classes that represent values, such as your point_t class here, belong to the second category, while classes that represent entities (i.e. something with identity) belong to the first one.
So my suggestion is to chose what you think is the best approach for each class and only provide that. Note that you could always return a small directly allocated object which has a private pointer to a larger one, as in the Handle-Body idiom.
On the other hand, other answers show how you may disambiguate among constructors that take arguments of the same number and types. In this line of thought, one alternative approach is to introduce specific types for the arguments as follows:
class radius_t {
float R;
public:
explicit radius_t(float r) : R(r) {}
operator float() const { return R; }
};
class angle_t {
float A;
public:
explicit angle_t(float a) : A(a) {}
operator float() const { return A; }
};
class point_t {
float X,Y;
public:
point_t(float x, float y) : X(x), Y(y) { }
point_t(radius_t radius, angle_t angle) :
X(radius*std::cos(angle)), Y((radius*std::sin(angle)) {
}
void add(int x, int y) { X += x; Y += y; }
};
int main(int argc, char **argv) {
point_t *x = new point_t(radius_t(1),angle_t(2));
x->add(1,2);
}
One approach that I haven't seen is overloading the constructor making the heap allocation use the last argument as an out one (Granted that the second function is not technically a constructor, it doesn't return an instance). The result would be something like (taken as base your second code fragment):
class point_t {
int X,Y;
point_t(int x, int y) : X(x), Y(y) { }
public:
/* XXX: function overloading doesn't work on return types */
static point_t carthesian(const int x, const int y) { return point_t(x,y); }
static void carthesian(const int x, const int y, point_t * & point) { point = new point_t(x,y); }
void add(int x, int y) { X += x; Y += y; }
void add(const point_t & point) { this->X += point.x; this->Y += point.y; }
};
int main(int argc, char **argv) {
point_t p1 = point_t::carthesion(1, 2);
point_t * p2;
point_t::carthesian(1, 2, p2);
p2->add(p1);
}
Can think of template allocator:
template<typename T>
struct Allocator : T
{
template<typename A1, typename A2>
Allocator(A1 a1, A2 a2) : T(a1, a2) {}
};
class point_t {
//...
template<typename T> friend struct Allocator;
};
int main(int argc, char **argv) {
point_t *x = new Allocator<point_t>(1,2);
x->add(1,2);
}
Now Allocator is friend of point_t. So it can access its private constructor. Also, you can add few more constructors like <A1, A2> inside Allocator to make it more generalized. Advantages are:
It doesn't look verbose.
You don't have to worry about compiler optimizations
The friendship is not exploited as, Allocator is a template
and we use it solely for heap allocation
Demo.

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