From: Hans Fugal Date: Wed, 17 Jul 2013 01:34:51 +0000 (-0700) Subject: tuple hashing X-Git-Tag: v0.22.0~924 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b71e31a5fe51724cd9b05fbb4bbf87510f01e45f;p=folly.git 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 --- 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]); +}