Consider the following code. I want to specialize std::hash<> used in a Map, according to the value of a static data member of the Array class. Note that Array depends on Map itself.
// Array.h
#include <unordered_map>
using namespace std;
class Array;
typedef pair<int, int> Point;
namespace std {
template <> struct hash<Point> {
size_t operator()(const Point & p) const {
return p.second * Array::C + p.first; // error: incomplete type ‘Array’ used in nested name specifier
}
};
}
typedef unordered_map<Point, Array, hash<Point> > Map;
class Array {
public:
static const int R = 5, C = 5;
Map compute() {/*...*/}
};
Of course, in the above specialization Array is not complete yet, so the compiler complains. However, if I move the specialization below the class definition, I obtain another error:
error: specialization of ‘std::hash<std::pair<int, int> >’ after instantiation
I think you pretty much know the reason why you’re getting that error, so I wouldn’t explain that. However, if you want to explore that part also, then I will definitely explain that.
As for how to solve this problem, alright, I would do three things:
First, I wouldn’t specialize
std::hashto begin with!Second, I would write my own
MyHashclass template, which I would instantiate withArraytype, instead ofPointtype. Also note that the parameter type tooperator()isn’tArray, rather it isPoint, as it should be.Third, I would move the
typedefofMapinside the classArray.Here is what I mean:
Online demo : http://ideone.com/hwLIT