// 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 #include #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` can be constructed with a `T`, and can // be compared and hashed. However, all hashing goes through the hashing // type-erasure framework. template class TypeErasedValue { public: TypeErasedValue() = default; TypeErasedValue(const TypeErasedValue&) = default; TypeErasedValue(TypeErasedValue&&) = default; explicit TypeErasedValue(const T& n) : n_(n) {} template 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 class TypeErasedContainer : public TypeErasedValue { public: using value_type = typename T::value_type; TypeErasedContainer() = default; TypeErasedContainer(const TypeErasedContainer&) = default; TypeErasedContainer(TypeErasedContainer&&) = default; explicit TypeErasedContainer(const T& n) : TypeErasedValue(n) {} TypeErasedContainer(std::initializer_list 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 using is_hashable = std::is_default_constructible>; } // namespace hash_test_internal ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HASH_INTERNAL_HASH_TEST_H_