diff --git a/llvm/include/llvm/ADT/Hashing.h b/llvm/include/llvm/ADT/Hashing.h --- a/llvm/include/llvm/ADT/Hashing.h +++ b/llvm/include/llvm/ADT/Hashing.h @@ -52,6 +52,7 @@ #include #include #include +#include #include namespace llvm { @@ -112,6 +113,10 @@ template hash_code hash_value(const std::pair &arg); +/// Compute a hash_code for a tuple. +template +hash_code hash_value(const std::tuple &arg); + /// Compute a hash_code for a standard string. template hash_code hash_value(const std::basic_string &arg); @@ -645,6 +650,26 @@ return hash_combine(arg.first, arg.second); } +// Implementation details for the hash_value overload for std::tuple<...>(...). +namespace hashing { +namespace detail { + +template +hash_code hash_value_tuple_helper(const std::tuple &arg, + std::index_sequence indices) { + return hash_combine(std::get(arg)...); +} + +} // namespace detail +} // namespace hashing + +template +hash_code hash_value(const std::tuple &arg) { + // TODO: Use std::apply when LLVM starts using C++17. + return ::llvm::hashing::detail::hash_value_tuple_helper( + arg, typename std::index_sequence_for()); +} + // Declared and documented above, but defined here so that any of the hashing // infrastructure is available. template diff --git a/llvm/unittests/ADT/HashingTest.cpp b/llvm/unittests/ADT/HashingTest.cpp --- a/llvm/unittests/ADT/HashingTest.cpp +++ b/llvm/unittests/ADT/HashingTest.cpp @@ -101,6 +101,17 @@ hash_value(std::make_pair(obj1, std::make_pair(obj2, obj3)))); } +TEST(HashingTest, HashValueStdTuple) { + EXPECT_EQ(hash_combine(), hash_value(std::make_tuple())); + EXPECT_EQ(hash_combine(42), hash_value(std::make_tuple(42))); + EXPECT_EQ(hash_combine(42, 'c'), hash_value(std::make_tuple(42, 'c'))); + + EXPECT_NE(hash_combine(43, 42), hash_value(std::make_tuple(42, 43))); + EXPECT_NE(hash_combine(42, 43), hash_value(std::make_tuple(42ull, 43ull))); + EXPECT_NE(hash_combine(42, 43), hash_value(std::make_tuple(42, 43ull))); + EXPECT_NE(hash_combine(42, 43), hash_value(std::make_tuple(42ull, 43))); +} + TEST(HashingTest, HashValueStdString) { std::string s = "Hello World!"; EXPECT_EQ(hash_combine_range(s.c_str(), s.c_str() + s.size()), hash_value(s));