To narrow it down: I’m currently using Boost.Unordered. I see two possible solutions:
-
Define my own Equality Predicates and Hash Functions and to utilize templates (maybe
is_pointer) to distinct between pointers and instances; -
Simply to extend
boost::hashby providinghash_value(Type* const& x)as for hashing; and add==operator overload as free function with(Type* const& x, Type* const& y)parameters as for equality checking.
I’m not sure whether both variations are actually possible, since I didn’t test them. I would like to find out you handle this problem. Implementations are welcome 🙂
EDIT 1:
What about this?
template<class T>
struct Equals: std::binary_function<T, T, bool> {
bool operator()(T const& left, T const& right) const {
return left == right;
}
};
template<class T>
struct Equals<T*> : std::binary_function<T*, T*, bool> {
bool operator()(T* const& left, T* const& right) const {
return *left == *right;
}
};
EDIT 2:
I’ve just defined:
friend std::size_t hash_value(Base const& base) {
boost::hash<std::string> hash;
return hash(base.string_);
}
friend std::size_t hash_value(Base* const& base) {
return hash_value(*base);
}
And then:
Derived d1("x");
Derived d2("x");
unordered_set<Base*> set;
set.insert(&d1);
assert(set.find(&d2) == end());
Debugger says that friend std::size_t hash_value(Base* const& base) is never called (GCC 4.7). Why is that?
EDIT 3:
I found out that template <class T> std::size_t hash_value(T* const& v) in boost/functional/hash.hpp on line #215 (Boost 1.49) is Boost’s specialization for pointers and it simply masks your custom implementation of hash_value such as mine in EDIT 2.
Therefore, it seems like the only way here is to create a custom Hash Functor.
For the hash function, you have a choice between specializing
boost::hash(orstd::hashin the newer standard) or defining a new functor class. These alternatives work equally well.For the equality operator, you need to define a new functor, because you cannot redefine the equality operator over pointers. It’s a built-in operator (defined in functional terms as
bool operator==( T const *x, T const *y )) and cannot be replaced.Both of these can be defined generically by using a templated
operator()in a non-templated class.Follow a similar pattern for the hasher.