diff options
author | Abseil Team <absl-team@google.com> | 2022-01-19 11:04:50 -0800 |
---|---|---|
committer | dinord <dino.radakovich@gmail.com> | 2022-01-19 14:36:25 -0500 |
commit | fbbb5865a562c9a9167d71c1cf56b82025a8f065 (patch) | |
tree | 212c8694bb6cf1d76af2b4aabac02c4910f6beab /absl/hash/internal/spy_hash_state.h | |
parent | 9bb42857112ad13b23de4333fbb75eb47db9de95 (diff) | |
download | abseil-fbbb5865a562c9a9167d71c1cf56b82025a8f065.tar.gz abseil-fbbb5865a562c9a9167d71c1cf56b82025a8f065.tar.bz2 abseil-fbbb5865a562c9a9167d71c1cf56b82025a8f065.zip |
Export of internal Abseil changes
--
487c7a754a3b93bc0f9de14bdced48007a96ae55 by Greg Falcon <gfalcon@google.com>:
Add support for absl::Hash to hash unordered containers. These can now be hashed directly, as well as combined in AbslHashValue implementations.
This also adds a new method, `H::combine_unordered()`, to the public AbslHashValue hash state API. This allows users to implement hash specializations for their own unordered collection types.
A traits class, `H::is_hashable<T>`, is also added to the hash state API. H::is_hashable<T>::value reflects whether type T is considered hashable by the AbslHashValue framework. This allows users to properly SFINAE templated versions of AbslHashValue. (The AbslHashValue implementation added to raw_hash_set shows an example of its use.)
PiperOrigin-RevId: 422856706
GitOrigin-RevId: 487c7a754a3b93bc0f9de14bdced48007a96ae55
Change-Id: Id31fd4ccba282f8c9ae6fcee6ae0ad0f7879f456
Diffstat (limited to 'absl/hash/internal/spy_hash_state.h')
-rw-r--r-- | absl/hash/internal/spy_hash_state.h | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/absl/hash/internal/spy_hash_state.h b/absl/hash/internal/spy_hash_state.h index c0831208..09728266 100644 --- a/absl/hash/internal/spy_hash_state.h +++ b/absl/hash/internal/spy_hash_state.h @@ -15,6 +15,7 @@ #ifndef ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_ #define ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_ +#include <algorithm> #include <ostream> #include <string> #include <vector> @@ -167,6 +168,24 @@ class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> { using SpyHashStateImpl::HashStateBase::combine_contiguous; + template <typename CombinerT> + static SpyHashStateImpl RunCombineUnordered(SpyHashStateImpl state, + CombinerT combiner) { + UnorderedCombinerCallback cb; + + combiner(SpyHashStateImpl<void>{}, std::ref(cb)); + + std::sort(cb.element_hash_representations.begin(), + cb.element_hash_representations.end()); + state.hash_representation_.insert(state.hash_representation_.end(), + cb.element_hash_representations.begin(), + cb.element_hash_representations.end()); + if (cb.error && cb.error->has_value()) { + state.error_ = std::move(cb.error); + } + return state; + } + absl::optional<std::string> error() const { if (moved_from_) { return "Returned a moved-from instance of the hash state object."; @@ -178,6 +197,22 @@ class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> { template <typename U> friend class SpyHashStateImpl; + struct UnorderedCombinerCallback { + std::vector<std::string> element_hash_representations; + std::shared_ptr<absl::optional<std::string>> error; + + // The inner spy can have a different type. + template <typename U> + void operator()(SpyHashStateImpl<U>& inner) { + element_hash_representations.push_back( + absl::StrJoin(inner.hash_representation_, "")); + if (inner.error_->has_value()) { + error = std::move(inner.error_); + } + inner = SpyHashStateImpl<void>{}; + } + }; + // This is true if SpyHashStateImpl<T> has been passed to a call of // AbslHashValue with the wrong type. This detects that the user called // AbslHashValue directly (because the hash state type does not match). |