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