hash_policy_testing.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 // Utilities to help tests verify that hash tables properly handle stateful
00016 // allocators and hash functions.
00017 
00018 #ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_
00019 #define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_
00020 
00021 #include <cstdlib>
00022 #include <limits>
00023 #include <memory>
00024 #include <ostream>
00025 #include <type_traits>
00026 #include <utility>
00027 #include <vector>
00028 
00029 #include "absl/hash/hash.h"
00030 #include "absl/strings/string_view.h"
00031 
00032 namespace absl {
00033 namespace container_internal {
00034 namespace hash_testing_internal {
00035 
00036 template <class Derived>
00037 struct WithId {
00038   WithId() : id_(next_id<Derived>()) {}
00039   WithId(const WithId& that) : id_(that.id_) {}
00040   WithId(WithId&& that) : id_(that.id_) { that.id_ = 0; }
00041   WithId& operator=(const WithId& that) {
00042     id_ = that.id_;
00043     return *this;
00044   }
00045   WithId& operator=(WithId&& that) {
00046     id_ = that.id_;
00047     that.id_ = 0;
00048     return *this;
00049   }
00050 
00051   size_t id() const { return id_; }
00052 
00053   friend bool operator==(const WithId& a, const WithId& b) {
00054     return a.id_ == b.id_;
00055   }
00056   friend bool operator!=(const WithId& a, const WithId& b) { return !(a == b); }
00057 
00058  protected:
00059   explicit WithId(size_t id) : id_(id) {}
00060 
00061  private:
00062   size_t id_;
00063 
00064   template <class T>
00065   static size_t next_id() {
00066     // 0 is reserved for moved from state.
00067     static size_t gId = 1;
00068     return gId++;
00069   }
00070 };
00071 
00072 }  // namespace hash_testing_internal
00073 
00074 struct NonStandardLayout {
00075   NonStandardLayout() {}
00076   explicit NonStandardLayout(std::string s) : value(std::move(s)) {}
00077   virtual ~NonStandardLayout() {}
00078 
00079   friend bool operator==(const NonStandardLayout& a,
00080                          const NonStandardLayout& b) {
00081     return a.value == b.value;
00082   }
00083   friend bool operator!=(const NonStandardLayout& a,
00084                          const NonStandardLayout& b) {
00085     return a.value != b.value;
00086   }
00087 
00088   template <typename H>
00089   friend H AbslHashValue(H h, const NonStandardLayout& v) {
00090     return H::combine(std::move(h), v.value);
00091   }
00092 
00093   std::string value;
00094 };
00095 
00096 struct StatefulTestingHash
00097     : absl::container_internal::hash_testing_internal::WithId<
00098           StatefulTestingHash> {
00099   template <class T>
00100   size_t operator()(const T& t) const {
00101     return absl::Hash<T>{}(t);
00102   }
00103 };
00104 
00105 struct StatefulTestingEqual
00106     : absl::container_internal::hash_testing_internal::WithId<
00107           StatefulTestingEqual> {
00108   template <class T, class U>
00109   bool operator()(const T& t, const U& u) const {
00110     return t == u;
00111   }
00112 };
00113 
00114 // It is expected that Alloc() == Alloc() for all allocators so we cannot use
00115 // WithId base. We need to explicitly assign ids.
00116 template <class T = int>
00117 struct Alloc : std::allocator<T> {
00118   using propagate_on_container_swap = std::true_type;
00119 
00120   // Using old paradigm for this to ensure compatibility.
00121   explicit Alloc(size_t id = 0) : id_(id) {}
00122 
00123   Alloc(const Alloc&) = default;
00124   Alloc& operator=(const Alloc&) = default;
00125 
00126   template <class U>
00127   Alloc(const Alloc<U>& that) : std::allocator<T>(that), id_(that.id()) {}
00128 
00129   template <class U>
00130   struct rebind {
00131     using other = Alloc<U>;
00132   };
00133 
00134   size_t id() const { return id_; }
00135 
00136   friend bool operator==(const Alloc& a, const Alloc& b) {
00137     return a.id_ == b.id_;
00138   }
00139   friend bool operator!=(const Alloc& a, const Alloc& b) { return !(a == b); }
00140 
00141  private:
00142   size_t id_ = (std::numeric_limits<size_t>::max)();
00143 };
00144 
00145 template <class Map>
00146 auto items(const Map& m) -> std::vector<
00147     std::pair<typename Map::key_type, typename Map::mapped_type>> {
00148   using std::get;
00149   std::vector<std::pair<typename Map::key_type, typename Map::mapped_type>> res;
00150   res.reserve(m.size());
00151   for (const auto& v : m) res.emplace_back(get<0>(v), get<1>(v));
00152   return res;
00153 }
00154 
00155 template <class Set>
00156 auto keys(const Set& s)
00157     -> std::vector<typename std::decay<typename Set::key_type>::type> {
00158   std::vector<typename std::decay<typename Set::key_type>::type> res;
00159   res.reserve(s.size());
00160   for (const auto& v : s) res.emplace_back(v);
00161   return res;
00162 }
00163 
00164 }  // namespace container_internal
00165 }  // namespace absl
00166 
00167 // ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS is false for glibcxx versions
00168 // where the unordered containers are missing certain constructors that
00169 // take allocator arguments. This test is defined ad-hoc for the platforms
00170 // we care about (notably Crosstool 17) because libstdcxx's useless
00171 // versioning scheme precludes a more principled solution.
00172 // From GCC-4.9 Changelog: (src: https://gcc.gnu.org/gcc-4.9/changes.html)
00173 // "the unordered associative containers in <unordered_map> and <unordered_set>
00174 // meet the allocator-aware container requirements;"
00175 #if (defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425 ) || \
00176 ( __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9 ))
00177 #define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 0
00178 #else
00179 #define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 1
00180 #endif
00181 
00182 #endif  // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_


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