您可能期望std::unordered_map 能夠輕鬆地使用開箱即用的元組鍵。然而,它需要為元組定義一個雜湊函數,如下所示:
template<> struct do_hash<tuple<int, int>> { size_t operator()(std::tuple<int, int> const& tt) const {...} };
這個過程可能會變得乏味,導致在不訴諸可變參數模板的情況下為C 0x 元組實現自動化的問題。
以下方法允許所有包含標準可雜湊類型的C 0x 元組成為unordered_map 和unordered_set 的一部分,而無需額外的努力:
#include <tuple> namespace std { namespace { template <class T> inline void hash_combine(std::size_t& seed, T const& v) { // Modified from Boost seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } // Recursive template for hashing tuples 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; } }; }
透過將函數放置在std 命名空間中,可以透過參數存取它-依賴名稱查找(ADL)。
專門化 std 命名空間中的物件是未定義的行為。因此,對於符合標準的解決方案,請將程式碼移至單獨的命名空間中並放棄ADL 的便利性:
namespace hash_tuple { // Forward non-tuple types to std::hash template <class TT> struct hash { size_t operator()(TT const& tt) const { return std::hash<TT>()(tt); } }; // Hash function combining values in a tuple 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)); } }; // Hash function for tuples 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; } }; } // namespace hash_tuple
在hash_tuple 命名空間中聲明一個哈希實現,以將所有非元組類型轉送到std: :hash 並修改hash_combine 以使用hash_tuple::hash 而不是std::hash。將剩餘的程式碼放在 hash_tuple 命名空間中。
要使用此解決方案,必須包含以下程式碼,這會放棄 ADL 的便利性:
unordered_set<tuple<double, int>, hash_tuple::hash<tuple<double, int>>> test2;
以上是如何在不編寫自訂雜湊函數的情況下使用元組作為無序映射中的鍵?的詳細內容。更多資訊請關注PHP中文網其他相關文章!