1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
#include <iostream>
#include <unordered_map>
// should take double or long double
template < typename T > struct custom_struct { T a, b, c; /* ... */ };
// if int, then use explicit structure
template <> struct custom_struct<int>{ int a, b, c; /* ... */ };
// custom hash_function
struct hash_custom {
template < typename T >
std::size_t operator()( const custom_struct<T>& x ) const {
static const std::hash<T> hash ;
return hash(x.a) ^ hash()(x.b) ^ hash(x.c); // *** not a good way to combine hash values
}
};
// a better custom hash_function ( lifted from boost hash_combine)
struct hash_custom_2 {
template < typename T >
static std::size_t combine( std::size_t& seed, const T& v ) {
return seed ^= std::hash<T>{}(v) + 0x9e3779b9 + ( seed << 6U ) + ( seed >> 2U );
}
template < typename T >
std::size_t operator()( const custom_struct<T>& x ) const {
std::size_t hash_val = std::hash<T>{}( x.a ) ;
combine( hash_val, x.b ) ;
return combine( hash_val, x.c ) ;
}
};
int main() {
std::unordered_map< custom_struct<int>, double, hash_custom > int_map; // uses explicit custom struct
std::unordered_map< custom_struct<double>, long, hash_custom > double_map; // uses template custom struct
std::unordered_map< custom_struct<int>, double, hash_custom_2 > int_map2 ; // uses explicit custom struct
std::unordered_map< custom_struct<double>, long, hash_custom_2 > double_map2 ; // uses template custom struct
}
|