1 // Copyright 2023 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Common code shared between absl/hash/hash_test.cc and 16 // absl/hash/hash_instantiated_test.cc. 17 18 #ifndef ABSL_HASH_INTERNAL_HASH_TEST_H_ 19 #define ABSL_HASH_INTERNAL_HASH_TEST_H_ 20 21 #include <type_traits> 22 #include <utility> 23 24 #include "absl/base/config.h" 25 #include "absl/hash/hash.h" 26 27 namespace absl { 28 ABSL_NAMESPACE_BEGIN 29 namespace hash_test_internal { 30 31 // Utility wrapper of T for the purposes of testing the `AbslHash` type erasure 32 // mechanism. `TypeErasedValue<T>` can be constructed with a `T`, and can 33 // be compared and hashed. However, all hashing goes through the hashing 34 // type-erasure framework. 35 template <typename T> 36 class TypeErasedValue { 37 public: 38 TypeErasedValue() = default; 39 TypeErasedValue(const TypeErasedValue&) = default; 40 TypeErasedValue(TypeErasedValue&&) = default; TypeErasedValue(const T & n)41 explicit TypeErasedValue(const T& n) : n_(n) {} 42 43 template <typename H> AbslHashValue(H hash_state,const TypeErasedValue & v)44 friend H AbslHashValue(H hash_state, const TypeErasedValue& v) { 45 v.HashValue(absl::HashState::Create(&hash_state)); 46 return hash_state; 47 } 48 HashValue(absl::HashState state)49 void HashValue(absl::HashState state) const { 50 absl::HashState::combine(std::move(state), n_); 51 } 52 53 bool operator==(const TypeErasedValue& rhs) const { return n_ == rhs.n_; } 54 bool operator!=(const TypeErasedValue& rhs) const { return !(*this == rhs); } 55 56 private: 57 T n_; 58 }; 59 60 // A TypeErasedValue refinement, for containers. It exposes the wrapped 61 // `value_type` and is constructible from an initializer list. 62 template <typename T> 63 class TypeErasedContainer : public TypeErasedValue<T> { 64 public: 65 using value_type = typename T::value_type; 66 TypeErasedContainer() = default; 67 TypeErasedContainer(const TypeErasedContainer&) = default; 68 TypeErasedContainer(TypeErasedContainer&&) = default; TypeErasedContainer(const T & n)69 explicit TypeErasedContainer(const T& n) : TypeErasedValue<T>(n) {} TypeErasedContainer(std::initializer_list<value_type> init_list)70 TypeErasedContainer(std::initializer_list<value_type> init_list) 71 : TypeErasedContainer(T(init_list.begin(), init_list.end())) {} 72 // one-argument constructor of value type T, to appease older toolchains that 73 // get confused by one-element initializer lists in some contexts TypeErasedContainer(const value_type & v)74 explicit TypeErasedContainer(const value_type& v) 75 : TypeErasedContainer(T(&v, &v + 1)) {} 76 }; 77 78 // Helper trait to verify if T is hashable. We use absl::Hash's poison status to 79 // detect it. 80 template <typename T> 81 using is_hashable = std::is_default_constructible<absl::Hash<T>>; 82 83 } // namespace hash_test_internal 84 ABSL_NAMESPACE_END 85 } // namespace absl 86 87 #endif // ABSL_HASH_INTERNAL_HASH_TEST_H_ 88