| // Copyright 2023 The Abseil Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| // Common code shared between absl/hash/hash_test.cc and | |
| // absl/hash/hash_instantiated_test.cc. | |
| #ifndef ABSL_HASH_INTERNAL_HASH_TEST_H_ | |
| #define ABSL_HASH_INTERNAL_HASH_TEST_H_ | |
| #include <initializer_list> | |
| #include <type_traits> | |
| #include <utility> | |
| #include "absl/base/config.h" | |
| #include "absl/hash/hash.h" | |
| namespace absl { | |
| ABSL_NAMESPACE_BEGIN | |
| namespace hash_test_internal { | |
| // Utility wrapper of T for the purposes of testing the `AbslHash` type erasure | |
| // mechanism. `TypeErasedValue<T>` can be constructed with a `T`, and can | |
| // be compared and hashed. However, all hashing goes through the hashing | |
| // type-erasure framework. | |
| template <typename T> | |
| class TypeErasedValue { | |
| public: | |
| TypeErasedValue() = default; | |
| TypeErasedValue(const TypeErasedValue&) = default; | |
| TypeErasedValue(TypeErasedValue&&) = default; | |
| explicit TypeErasedValue(const T& n) : n_(n) {} | |
| template <typename H> | |
| friend H AbslHashValue(H hash_state, const TypeErasedValue& v) { | |
| v.HashValue(absl::HashState::Create(&hash_state)); | |
| return hash_state; | |
| } | |
| void HashValue(absl::HashState state) const { | |
| absl::HashState::combine(std::move(state), n_); | |
| } | |
| bool operator==(const TypeErasedValue& rhs) const { return n_ == rhs.n_; } | |
| bool operator!=(const TypeErasedValue& rhs) const { return !(*this == rhs); } | |
| private: | |
| T n_; | |
| }; | |
| // A TypeErasedValue refinement, for containers. It exposes the wrapped | |
| // `value_type` and is constructible from an initializer list. | |
| template <typename T> | |
| class TypeErasedContainer : public TypeErasedValue<T> { | |
| public: | |
| using value_type = typename T::value_type; | |
| TypeErasedContainer() = default; | |
| TypeErasedContainer(const TypeErasedContainer&) = default; | |
| TypeErasedContainer(TypeErasedContainer&&) = default; | |
| explicit TypeErasedContainer(const T& n) : TypeErasedValue<T>(n) {} | |
| TypeErasedContainer(std::initializer_list<value_type> init_list) | |
| : TypeErasedContainer(T(init_list.begin(), init_list.end())) {} | |
| // one-argument constructor of value type T, to appease older toolchains that | |
| // get confused by one-element initializer lists in some contexts | |
| explicit TypeErasedContainer(const value_type& v) | |
| : TypeErasedContainer(T(&v, &v + 1)) {} | |
| }; | |
| // Helper trait to verify if T is hashable. We use absl::Hash's poison status to | |
| // detect it. | |
| template <typename T> | |
| using is_hashable = std::is_default_constructible<absl::Hash<T>>; | |
| } // namespace hash_test_internal | |
| ABSL_NAMESPACE_END | |
| } // namespace absl | |
| #endif // ABSL_HASH_INTERNAL_HASH_TEST_H_ |