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 @@ -113,13 +113,14 @@ 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); -/// Compute a hash_code for a tuple. -template hash_code hash_value(const std::tuple &arg); - /// Override the execution seed with a fixed value. /// /// This hashing library uses a per-execution seed designed to change on each @@ -648,40 +649,13 @@ return hash_combine(arg.first, arg.second); } -// Declared and documented above, but defined here so that any of the hashing -// infrastructure is available. -template -hash_code hash_value(const std::basic_string &arg) { - return hash_combine_range(arg.begin(), arg.end()); -} - // Implementation details for the hash_value overload for std::tuple<...>(...). namespace hashing { namespace detail { -// The indices of a tuple (0..n-1) are collected as the Indices template -// parameter of the TupleIndexSet template. -template struct TupleIndexSet {}; - -// Collecting the indices uses recursive template metaprogramming via the -// MakeTupleIndexSet struct. The I template parameter recursively -// counts up to N-1. The values are collected in the Indices template parameter -// and then returned in the second template specialization when I reaches N. -template -struct MakeTupleIndexSet { - typedef typename MakeTupleIndexSet::Type Type; -}; - -template -struct MakeTupleIndexSet { - typedef TupleIndexSet Type; -}; - -// The indices are then expanded in the hash_value_tuple_helper function into -// std::get<...>(...) calls. -template +template hash_code hash_value_tuple_helper(const std::tuple &arg, - TupleIndexSet indices) { + std::index_sequence indices) { return hash_combine(std::get(arg)...); } @@ -689,9 +663,16 @@ } // namespace hashing template hash_code hash_value(const std::tuple &arg) { - typename ::llvm::hashing::detail::MakeTupleIndexSet<0, sizeof...(Ts)>::Type - indices; - return hash_value_tuple_helper(arg, indices); + // 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 +hash_code hash_value(const std::basic_string &arg) { + return hash_combine_range(arg.begin(), arg.end()); } } // namespace llvm 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 @@ -105,6 +105,11 @@ 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) {