00001 // Copyright 2018 The Abseil Authors. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // https://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 // 00015 // ----------------------------------------------------------------------------- 00016 // File: hash.h 00017 // ----------------------------------------------------------------------------- 00018 // 00019 // This header file defines the Abseil `hash` library and the Abseil hashing 00020 // framework. This framework consists of the following: 00021 // 00022 // * The `absl::Hash` functor, which is used to invoke the hasher within the 00023 // Abseil hashing framework. `absl::Hash<T>` supports most basic types and 00024 // a number of Abseil types out of the box. 00025 // * `AbslHashValue`, an extension point that allows you to extend types to 00026 // support Abseil hashing without requiring you to define a hashing 00027 // algorithm. 00028 // * `HashState`, a type-erased class which implements the manipulation of the 00029 // hash state (H) itself, contains member functions `combine()` and 00030 // `combine_contiguous()`, which you can use to contribute to an existing 00031 // hash state when hashing your types. 00032 // 00033 // Unlike `std::hash` or other hashing frameworks, the Abseil hashing framework 00034 // provides most of its utility by abstracting away the hash algorithm (and its 00035 // implementation) entirely. Instead, a type invokes the Abseil hashing 00036 // framework by simply combining its state with the state of known, hashable 00037 // types. Hashing of that combined state is separately done by `absl::Hash`. 00038 // 00039 // One should assume that a hash algorithm is chosen randomly at the start of 00040 // each process. E.g., absl::Hash<int>()(9) in one process and 00041 // absl::Hash<int>()(9) in another process are likely to differ. 00042 // 00043 // Example: 00044 // 00045 // // Suppose we have a class `Circle` for which we want to add hashing: 00046 // class Circle { 00047 // public: 00048 // ... 00049 // private: 00050 // std::pair<int, int> center_; 00051 // int radius_; 00052 // }; 00053 // 00054 // // To add hashing support to `Circle`, we simply need to add a free 00055 // // (non-member) function `AbslHashValue()`, and return the combined hash 00056 // // state of the existing hash state and the class state. You can add such a 00057 // // free function using a friend declaration within the body of the class: 00058 // class Circle { 00059 // public: 00060 // ... 00061 // template <typename H> 00062 // friend H AbslHashValue(H h, const Circle& c) { 00063 // return H::combine(std::move(h), c.center_, c.radius_); 00064 // } 00065 // ... 00066 // }; 00067 // 00068 // For more information, see Adding Type Support to `absl::Hash` below. 00069 // 00070 #ifndef ABSL_HASH_HASH_H_ 00071 #define ABSL_HASH_HASH_H_ 00072 00073 #include "absl/hash/internal/hash.h" 00074 00075 namespace absl { 00076 00077 // ----------------------------------------------------------------------------- 00078 // `absl::Hash` 00079 // ----------------------------------------------------------------------------- 00080 // 00081 // `absl::Hash<T>` is a convenient general-purpose hash functor for any type `T` 00082 // satisfying any of the following conditions (in order): 00083 // 00084 // * T is an arithmetic or pointer type 00085 // * T defines an overload for `AbslHashValue(H, const T&)` for an arbitrary 00086 // hash state `H`. 00087 // - T defines a specialization of `HASH_NAMESPACE::hash<T>` 00088 // - T defines a specialization of `std::hash<T>` 00089 // 00090 // `absl::Hash` intrinsically supports the following types: 00091 // 00092 // * All integral types (including bool) 00093 // * All enum types 00094 // * All floating-point types (although hashing them is discouraged) 00095 // * All pointer types, including nullptr_t 00096 // * std::pair<T1, T2>, if T1 and T2 are hashable 00097 // * std::tuple<Ts...>, if all the Ts... are hashable 00098 // * std::unique_ptr and std::shared_ptr 00099 // * All string-like types including: 00100 // * std::string 00101 // * std::string_view (as well as any instance of std::basic_string that 00102 // uses char and std::char_traits) 00103 // * All the standard sequence containers (provided the elements are hashable) 00104 // * All the standard ordered associative containers (provided the elements are 00105 // hashable) 00106 // * absl types such as the following: 00107 // * absl::string_view 00108 // * absl::InlinedVector 00109 // * absl::FixedArray 00110 // * absl::uint128 00111 // * absl::Time, absl::Duration, and absl::TimeZone 00112 // 00113 // Note: the list above is not meant to be exhaustive. Additional type support 00114 // may be added, in which case the above list will be updated. 00115 // 00116 // ----------------------------------------------------------------------------- 00117 // absl::Hash Invocation Evaluation 00118 // ----------------------------------------------------------------------------- 00119 // 00120 // When invoked, `absl::Hash<T>` searches for supplied hash functions in the 00121 // following order: 00122 // 00123 // * Natively supported types out of the box (see above) 00124 // * Types for which an `AbslHashValue()` overload is provided (such as 00125 // user-defined types). See "Adding Type Support to `absl::Hash`" below. 00126 // * Types which define a `HASH_NAMESPACE::hash<T>` specialization (aka 00127 // `__gnu_cxx::hash<T>` for gcc/Clang or `stdext::hash<T>` for MSVC) 00128 // * Types which define a `std::hash<T>` specialization 00129 // 00130 // The fallback to legacy hash functions exists mainly for backwards 00131 // compatibility. If you have a choice, prefer defining an `AbslHashValue` 00132 // overload instead of specializing any legacy hash functors. 00133 // 00134 // ----------------------------------------------------------------------------- 00135 // The Hash State Concept, and using `HashState` for Type Erasure 00136 // ----------------------------------------------------------------------------- 00137 // 00138 // The `absl::Hash` framework relies on the Concept of a "hash state." Such a 00139 // hash state is used in several places: 00140 // 00141 // * Within existing implementations of `absl::Hash<T>` to store the hashed 00142 // state of an object. Note that it is up to the implementation how it stores 00143 // such state. A hash table, for example, may mix the state to produce an 00144 // integer value; a testing framework may simply hold a vector of that state. 00145 // * Within implementations of `AbslHashValue()` used to extend user-defined 00146 // types. (See "Adding Type Support to absl::Hash" below.) 00147 // * Inside a `HashState`, providing type erasure for the concept of a hash 00148 // state, which you can use to extend the `absl::Hash` framework for types 00149 // that are otherwise difficult to extend using `AbslHashValue()`. (See the 00150 // `HashState` class below.) 00151 // 00152 // The "hash state" concept contains two member functions for mixing hash state: 00153 // 00154 // * `H::combine(state, values...)` 00155 // 00156 // Combines an arbitrary number of values into a hash state, returning the 00157 // updated state. Note that the existing hash state is move-only and must be 00158 // passed by value. 00159 // 00160 // Each of the value types T must be hashable by H. 00161 // 00162 // NOTE: 00163 // 00164 // state = H::combine(std::move(state), value1, value2, value3); 00165 // 00166 // must be guaranteed to produce the same hash expansion as 00167 // 00168 // state = H::combine(std::move(state), value1); 00169 // state = H::combine(std::move(state), value2); 00170 // state = H::combine(std::move(state), value3); 00171 // 00172 // * `H::combine_contiguous(state, data, size)` 00173 // 00174 // Combines a contiguous array of `size` elements into a hash state, 00175 // returning the updated state. Note that the existing hash state is 00176 // move-only and must be passed by value. 00177 // 00178 // NOTE: 00179 // 00180 // state = H::combine_contiguous(std::move(state), data, size); 00181 // 00182 // need NOT be guaranteed to produce the same hash expansion as a loop 00183 // (it may perform internal optimizations). If you need this guarantee, use a 00184 // loop instead. 00185 // 00186 // ----------------------------------------------------------------------------- 00187 // Adding Type Support to `absl::Hash` 00188 // ----------------------------------------------------------------------------- 00189 // 00190 // To add support for your user-defined type, add a proper `AbslHashValue()` 00191 // overload as a free (non-member) function. The overload will take an 00192 // existing hash state and should combine that state with state from the type. 00193 // 00194 // Example: 00195 // 00196 // template <typename H> 00197 // H AbslHashValue(H state, const MyType& v) { 00198 // return H::combine(std::move(state), v.field1, ..., v.fieldN); 00199 // } 00200 // 00201 // where `(field1, ..., fieldN)` are the members you would use on your 00202 // `operator==` to define equality. 00203 // 00204 // Notice that `AbslHashValue` is not a class member, but an ordinary function. 00205 // An `AbslHashValue` overload for a type should only be declared in the same 00206 // file and namespace as said type. The proper `AbslHashValue` implementation 00207 // for a given type will be discovered via ADL. 00208 // 00209 // Note: unlike `std::hash', `absl::Hash` should never be specialized. It must 00210 // only be extended by adding `AbslHashValue()` overloads. 00211 // 00212 template <typename T> 00213 using Hash = absl::hash_internal::Hash<T>; 00214 00215 // HashState 00216 // 00217 // A type erased version of the hash state concept, for use in user-defined 00218 // `AbslHashValue` implementations that can't use templates (such as PImpl 00219 // classes, virtual functions, etc.). The type erasure adds overhead so it 00220 // should be avoided unless necessary. 00221 // 00222 // Note: This wrapper will only erase calls to: 00223 // combine_contiguous(H, const unsigned char*, size_t) 00224 // 00225 // All other calls will be handled internally and will not invoke overloads 00226 // provided by the wrapped class. 00227 // 00228 // Users of this class should still define a template `AbslHashValue` function, 00229 // but can use `absl::HashState::Create(&state)` to erase the type of the hash 00230 // state and dispatch to their private hashing logic. 00231 // 00232 // This state can be used like any other hash state. In particular, you can call 00233 // `HashState::combine()` and `HashState::combine_contiguous()` on it. 00234 // 00235 // Example: 00236 // 00237 // class Interface { 00238 // public: 00239 // template <typename H> 00240 // friend H AbslHashValue(H state, const Interface& value) { 00241 // state = H::combine(std::move(state), std::type_index(typeid(*this))); 00242 // value.HashValue(absl::HashState::Create(&state)); 00243 // return state; 00244 // } 00245 // private: 00246 // virtual void HashValue(absl::HashState state) const = 0; 00247 // }; 00248 // 00249 // class Impl : Interface { 00250 // private: 00251 // void HashValue(absl::HashState state) const override { 00252 // absl::HashState::combine(std::move(state), v1_, v2_); 00253 // } 00254 // int v1_; 00255 // std::string v2_; 00256 // }; 00257 class HashState : public hash_internal::HashStateBase<HashState> { 00258 public: 00259 // HashState::Create() 00260 // 00261 // Create a new `HashState` instance that wraps `state`. All calls to 00262 // `combine()` and `combine_contiguous()` on the new instance will be 00263 // redirected to the original `state` object. The `state` object must outlive 00264 // the `HashState` instance. 00265 template <typename T> 00266 static HashState Create(T* state) { 00267 HashState s; 00268 s.Init(state); 00269 return s; 00270 } 00271 00272 HashState(const HashState&) = delete; 00273 HashState& operator=(const HashState&) = delete; 00274 HashState(HashState&&) = default; 00275 HashState& operator=(HashState&&) = default; 00276 00277 // HashState::combine() 00278 // 00279 // Combines an arbitrary number of values into a hash state, returning the 00280 // updated state. 00281 using HashState::HashStateBase::combine; 00282 00283 // HashState::combine_contiguous() 00284 // 00285 // Combines a contiguous array of `size` elements into a hash state, returning 00286 // the updated state. 00287 static HashState combine_contiguous(HashState hash_state, 00288 const unsigned char* first, size_t size) { 00289 hash_state.combine_contiguous_(hash_state.state_, first, size); 00290 return hash_state; 00291 } 00292 using HashState::HashStateBase::combine_contiguous; 00293 00294 private: 00295 HashState() = default; 00296 00297 template <typename T> 00298 static void CombineContiguousImpl(void* p, const unsigned char* first, 00299 size_t size) { 00300 T& state = *static_cast<T*>(p); 00301 state = T::combine_contiguous(std::move(state), first, size); 00302 } 00303 00304 template <typename T> 00305 void Init(T* state) { 00306 state_ = state; 00307 combine_contiguous_ = &CombineContiguousImpl<T>; 00308 } 00309 00310 // Do not erase an already erased state. 00311 void Init(HashState* state) { 00312 state_ = state->state_; 00313 combine_contiguous_ = state->combine_contiguous_; 00314 } 00315 00316 void* state_; 00317 void (*combine_contiguous_)(void*, const unsigned char*, size_t); 00318 }; 00319 00320 } // namespace absl 00321 00322 #endif // ABSL_HASH_HASH_H_