Specializing std::hash to derived classes
c++11, gcc, hash, stdhash, template-specialization
Solution
It seems like there is no proper way to do what I wanted to do. I have decided to just write separate specializations for each derived class, using the following macro:
// macro to conveniently define specialization for a class derived from Hashable
#define DEFINE_STD_HASH_SPECIALIZATION(hashable) \
namespace std { \
template<> \
struct hash<hashable> { \
std::size_t operator()(const hashable& object) const { \
return object.Hash(); \
} \
}; \
}
and then
// specialization of std::hash for Derived
DEFINE_STD_HASH_SPECIALIZATION(Derived);
Problem
I have an abstract base class `Hashable` that classes that can be hashed derive from. I would now like to extend `std::hash` to all classes that derive from `Hashable`. The following code is supposed to do exactly that. ``` #include <functional> #include <type_traits> #include <iostream> class Hashable { public: virtual ~Hashable() {} virtual std::size_t Hash() const =0; }; class Derived : public Hashable { public: std::size_t Hash() const { return 0; } }; // Specialization of std::hash to operate on Hashable or any class derived from // Hashable. namespace std { template<class C> struct hash { typename std::enable_if<std::is_base_of<Hashable, C>::value, std::size_t>::type operator()(const C& object) const { return object.Hash(); } }; } int main(int, char**) { std::hash<Derived> hasher; Derived d; std::cout << hasher(d) << std::endl; return 0; } ``` The above code works exactly as expected with gcc 4.8.1, but when I try to compile it with gcc 4.7.2, I get the following: ``` $ g++ -std=c++11 -o test test_hash.cpp test_hash.cpp:22:8: error: redefinition of ‘struct std::hash<_Tp>’ In file included from /usr/include/c++/4.7/functional:59:0, from test_hash.cpp:1: /usr/include/c++/4.7/bits/functional_hash.h:58:12: error: previous definition of ‘struct std::hash<_Tp>’ /usr/include/c++/4.7/bits/functional_hash.h: In instantiation of ‘struct std::hash<Derived>’: test_hash.cpp:31:24: required from here /usr/include/c++/4.7/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type ``` Can anybody think of a way to make this specialization of `std::hash` work for any class derived from `Hashable` with gcc 4.7.2?