Commit b71e31a5 authored by Hans Fugal's avatar Hans Fugal Committed by Sara Golemon

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
parent 982acaae
......@@ -21,6 +21,7 @@
#include <stdint.h>
#include <string>
#include <utility>
#include <tuple>
#include "folly/SpookyHashV1.h"
#include "folly/SpookyHashV2.h"
......@@ -348,6 +349,26 @@ template<> struct hasher<uint64_t> {
}
};
// recursion
template <size_t index, typename... Ts>
struct TupleHasher {
size_t operator()(std::tuple<Ts...> const& key) const {
return hash::hash_combine(
TupleHasher<index - 1, Ts...>()(key),
std::get<index>(key));
}
};
// base
template <typename... Ts>
struct TupleHasher<0, Ts...> {
size_t operator()(std::tuple<Ts...> 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 <typename... Ts>
struct hash<std::tuple<Ts...>> {
size_t operator()(std::tuple<Ts...> const& key) const {
folly::TupleHasher<
std::tuple_size<std::tuple<Ts...>>::value - 1, // start index
Ts...> hasher;
return hasher(key);
}
};
} // namespace std
#endif
......@@ -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<int64_t, std::string, int32_t> tuple3;
tuple3 t(42, "foo", 1);
std::unordered_map<tuple3, std::string> m;
m[t] = "bar";
EXPECT_EQ("bar", m[t]);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment