hash.h
Go to the documentation of this file.
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_


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14