Commit b3410b78 authored by Aaryaman Sagar's avatar Aaryaman Sagar Committed by Facebook Github Bot

Make folly::Hash work with pointer and pointer-like types

Summary:
folly::Hash did not work with pointer-like types like std::unique_ptr<T>,
std::shared_ptr<T> and T*.  Add specializations for those

Reviewed By: yfeldblum

Differential Revision: D16134842

fbshipit-source-id: 78d3cf9c6f5ef4f49b008c0d1c489d3c6203ba89
parent 83a5c644
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <limits> #include <limits>
#include <memory>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
...@@ -535,6 +536,33 @@ struct hasher<std::tuple<Ts...>> { ...@@ -535,6 +536,33 @@ struct hasher<std::tuple<Ts...>> {
} }
}; };
template <typename T>
struct hasher<T*> {
using folly_is_avalanching = hasher<std::uintptr_t>::folly_is_avalanching;
size_t operator()(T* key) const {
return Hash()(bit_cast<std::uintptr_t>(key));
}
};
template <typename T>
struct hasher<std::unique_ptr<T>> {
using folly_is_avalanching = typename hasher<T*>::folly_is_avalanching;
size_t operator()(const std::unique_ptr<T>& key) const {
return Hash()(key.get());
}
};
template <typename T>
struct hasher<std::shared_ptr<T>> {
using folly_is_avalanching = typename hasher<T*>::folly_is_avalanching;
size_t operator()(const std::shared_ptr<T>& key) const {
return Hash()(key.get());
}
};
// combiner for multi-arg tuple also mixes bits // combiner for multi-arg tuple also mixes bits
template <typename T, typename K> template <typename T, typename K>
struct IsAvalanchingHasher<hasher<std::tuple<T>>, K> struct IsAvalanchingHasher<hasher<std::tuple<T>>, K>
......
...@@ -23,7 +23,9 @@ ...@@ -23,7 +23,9 @@
#include <unordered_set> #include <unordered_set>
#include <utility> #include <utility>
#include <folly/Conv.h>
#include <folly/MapUtil.h> #include <folly/MapUtil.h>
#include <folly/Random.h>
#include <folly/Range.h> #include <folly/Range.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
...@@ -625,6 +627,57 @@ TEST(Hash, Strings) { ...@@ -625,6 +627,57 @@ TEST(Hash, Strings) {
EXPECT_EQ(h2(a4), h2(a4.str())); EXPECT_EQ(h2(a4), h2(a4.str()));
} }
namespace {
void deletePointer(const std::unique_ptr<std::string>&) {}
void deletePointer(const std::shared_ptr<std::string>&) {}
void deletePointer(std::string* pointer) {
delete pointer;
}
template <template <typename...> class PtrType>
void pointerTestWithFollyHash() {
std::unordered_set<PtrType<std::string>, folly::Hash> set;
for (auto i = 0; i < 1000; ++i) {
auto random = PtrType<std::string>{
new std::string{folly::to<std::string>(folly::Random::rand64())}};
set.insert(std::move(random));
}
for (auto& pointer : set) {
EXPECT_TRUE(set.find(pointer) != set.end());
deletePointer(pointer);
}
}
template <typename T>
using Pointer = T*;
} // namespace
TEST(Hash, UniquePtr) {
pointerTestWithFollyHash<std::unique_ptr>();
}
TEST(Hash, SharedPtr) {
pointerTestWithFollyHash<std::shared_ptr>();
}
TEST(Hash, Pointer) {
pointerTestWithFollyHash<Pointer>();
EXPECT_TRUE(
(std::is_same<
folly::hasher<std::string*>::folly_is_avalanching,
folly::hasher<std::unique_ptr<std::string>>::folly_is_avalanching>::
value));
EXPECT_TRUE(
(std::is_same<
folly::hasher<std::string*>::folly_is_avalanching,
folly::hasher<std::shared_ptr<std::string>>::folly_is_avalanching>::
value));
}
struct FNVTestParam { struct FNVTestParam {
std::string in; std::string in;
uint64_t out; uint64_t out;
......
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