1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

Add hashing support for std::tuple

Summary:
All tuple values are passed directly to hash_combine. This is inspired by the implementation used for Swift:

4a1b4edbe1
845f3829b9

Reviewers: gribozavr2

Reviewed By: gribozavr2

Subscribers: dexonsmith, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D83887
This commit is contained in:
Michael Forster 2020-07-16 18:48:34 +02:00 committed by Dmitri Gribenko
parent 9c302c2155
commit 070c7b821a
2 changed files with 36 additions and 0 deletions

View File

@ -52,6 +52,7 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <tuple>
#include <utility> #include <utility>
namespace llvm { namespace llvm {
@ -112,6 +113,10 @@ template <typename T> hash_code hash_value(const T *ptr);
template <typename T, typename U> template <typename T, typename U>
hash_code hash_value(const std::pair<T, U> &arg); hash_code hash_value(const std::pair<T, U> &arg);
/// Compute a hash_code for a tuple.
template <typename... Ts>
hash_code hash_value(const std::tuple<Ts...> &arg);
/// Compute a hash_code for a standard string. /// Compute a hash_code for a standard string.
template <typename T> template <typename T>
hash_code hash_value(const std::basic_string<T> &arg); hash_code hash_value(const std::basic_string<T> &arg);
@ -645,6 +650,26 @@ hash_code hash_value(const std::pair<T, U> &arg) {
return hash_combine(arg.first, arg.second); return hash_combine(arg.first, arg.second);
} }
// Implementation details for the hash_value overload for std::tuple<...>(...).
namespace hashing {
namespace detail {
template <typename... Ts, std::size_t... Indices>
hash_code hash_value_tuple_helper(const std::tuple<Ts...> &arg,
std::index_sequence<Indices...> indices) {
return hash_combine(std::get<Indices>(arg)...);
}
} // namespace detail
} // namespace hashing
template <typename... Ts>
hash_code hash_value(const std::tuple<Ts...> &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<Ts...>());
}
// Declared and documented above, but defined here so that any of the hashing // Declared and documented above, but defined here so that any of the hashing
// infrastructure is available. // infrastructure is available.
template <typename T> template <typename T>

View File

@ -101,6 +101,17 @@ TEST(HashingTest, HashValueStdPair) {
hash_value(std::make_pair(obj1, std::make_pair(obj2, obj3)))); 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) { TEST(HashingTest, HashValueStdString) {
std::string s = "Hello World!"; std::string s = "Hello World!";
EXPECT_EQ(hash_combine_range(s.c_str(), s.c_str() + s.size()), hash_value(s)); EXPECT_EQ(hash_combine_range(s.c_str(), s.c_str() + s.size()), hash_value(s));