From 58007128979d739531bfdc983a2a41e0b28355aa Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Mon, 20 Aug 2018 13:26:45 +0200 Subject: [PATCH] Workaround a _GLIBCXX_DEBUG bug for std::hash This fixes the GN debug build on Linux. Change-Id: I847a8c67eda1f9069477de0af910f0cd520ccc2c --- src/common/HashUtils.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/common/HashUtils.h b/src/common/HashUtils.h index 4b0306cbba..e0cd6e7b80 100644 --- a/src/common/HashUtils.h +++ b/src/common/HashUtils.h @@ -52,4 +52,31 @@ void HashCombine(size_t* hash, const T& value, const Args&... args) { HashCombine(hash, args...); } +// Workaround a bug between clang++ and libstdlibc++ by defining our own hashing for bitsets. +// When _GLIBCXX_DEBUG is enabled libstdc++ wraps containers into debug containers. For bitset this +// means what is normally std::bitset is defined as std::__cxx1988::bitset and is replaced by the +// debug version of bitset. +// When hashing, std::hash proxies the call to std::hash and +// fails on clang because the latter tries to access the private _M_getdata member of the bitset. +// It looks like it should work because the non-debug bitset declares +// +// friend struct std::hash // bitset is the name of the class itself +// +// which should friend std::hash but somehow doesn't work on clang. +#if defined(_GLIBCXX_DEBUG) +template +size_t Hash(const std::bitset& value) { + constexpr size_t kWindowSize = sizeof(unsigned long long); + + std::bitset bits = value; + size_t hash = 0; + for (size_t processedBits = 0; processedBits < N; processedBits += kWindowSize) { + HashCombine(&hash, bits.to_ullong()); + bits >>= kWindowSize; + } + + return hash; +} +#endif + #endif // COMMON_HASHUTILS_H_