From b71e31a5fe51724cd9b05fbb4bbf87510f01e45f Mon Sep 17 00:00:00 2001 From: Hans Fugal Date: Tue, 16 Jul 2013 18:34:51 -0700 Subject: [PATCH] tuple hashing Summary: Add hash support for std::tuple. See also D490478 (where a first attempt was made) and D543586 (where that attempt was deemed broken and removed). Test Plan: unit test Reviewed By: chip@fb.com FB internal diff: D888796 --- folly/Hash.h | 33 +++++++++++++++++++++++++++++++++ folly/test/HashTest.cpp | 9 +++++++++ 2 files changed, 42 insertions(+) diff --git a/folly/Hash.h b/folly/Hash.h index 132ad846..cbd07b56 100644 --- a/folly/Hash.h +++ b/folly/Hash.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "folly/SpookyHashV1.h" #include "folly/SpookyHashV2.h" @@ -348,6 +349,26 @@ template<> struct hasher { } }; +// recursion +template +struct TupleHasher { + size_t operator()(std::tuple const& key) const { + return hash::hash_combine( + TupleHasher()(key), + std::get(key)); + } +}; + +// base +template +struct TupleHasher<0, Ts...> { + size_t operator()(std::tuple const& key) const { + // we could do std::hash here directly, but hash_combine hides all the + // ugly templating implicitly + return hash::hash_combine(std::get<0>(key)); + } +}; + } // namespace folly // Custom hash functions. @@ -361,6 +382,18 @@ namespace std { return folly::hash::hash_combine(x.first, x.second); } }; + + // Hash function for tuples. Requires default hash functions for all types. + template + struct hash> { + size_t operator()(std::tuple const& key) const { + folly::TupleHasher< + std::tuple_size>::value - 1, // start index + Ts...> hasher; + + return hasher(key); + } + }; } // namespace std #endif diff --git a/folly/test/HashTest.cpp b/folly/test/HashTest.cpp index aef8f226..6ed9a280 100644 --- a/folly/test/HashTest.cpp +++ b/folly/test/HashTest.cpp @@ -228,3 +228,12 @@ TEST(Hash, pair) { TEST(Hash, hash_combine) { EXPECT_NE(hash_combine(1, 2), hash_combine(2, 1)); } + +TEST(Hash, std_tuple) { + typedef std::tuple tuple3; + tuple3 t(42, "foo", 1); + + std::unordered_map m; + m[t] = "bar"; + EXPECT_EQ("bar", m[t]); +} -- 2.34.1