Generik Hash untuk Tuples dalam unordered_map/unordered_set
S: Mengapa tidak std::unordered_map
Dalam standard C , untuk menggunakan tupel sebagai kunci dalam bekas bersekutu seperti unordered_map atau unordered_set, anda perlu menentukan fungsi cincang tersuai.
S: Bolehkah ini diautomatikkan untuk tuple C 0x tanpa menggunakan templat variadic?
Ya, menggunakan kod berikut:
namespace std{ namespace { template <class T> inline void hash_combine(std::size_t& seed, T const& v) { seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<Tuple, Index-1>::apply(seed, tuple); hash_combine(seed, std::get<Index>(tuple)); } }; template <class Tuple> struct HashValueImpl<Tuple,0> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; } template <typename ... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...> const& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...> >::apply(seed, tt); return seed; } }; }
S: Adakah terdapat penyelesaian yang lebih mudah ?
Penyelesaian Tidak Mematuhi Standard (ADL Didayakan):
#includenamespace std{ namespace { template <class T> inline void hash_combine(std::size_t& seed, T const& v) { seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<Tuple, Index-1>::apply(seed, tuple); hash_combine(seed, std::get<Index>(tuple)); } }; template <class Tuple> struct HashValueImpl<Tuple,0> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; } template <typename ... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...> const& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...> >::apply(seed, tt); return seed; } }; }
Penyelesaian Pematuhan Standard (Tiada ADL):
Untuk mencapai pematuhan standard yang ketat, anda mesti mengalihkan kod di atas ke ruang nama yang berasingan (cth., hash_tuple) dan mengubah suai sintaks untuk menentukan fungsi cincang tersuai secara eksplisit.
namespace hash_tuple{ // Forward non-tuple types to std::hash template <typename TT> struct hash { size_t operator()(TT const& tt) const { return std::hash<TT>()(tt); } }; }
Ganti hash_combine dan HashValueImpl daripada penyelesaian tidak akur dengan rakan sejawat hash_tuple mereka. Akhir sekali, gunakan sintaks berikut:
unordered_set<tuple<double, int>, hash_tuple::hash<tuple<double, int>>> test2;
Atas ialah kandungan terperinci Bagaimana untuk Membuat `std::unordered_map` Berfungsi Tanpa Menentukan Fungsi Hash Tersuai?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!