OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
hopscotch_map.h
1 
24 #ifndef TSL_HOPSCOTCH_MAP_H
25 #define TSL_HOPSCOTCH_MAP_H
26 
27 
28 #include <algorithm>
29 #include <cstddef>
30 #include <functional>
31 #include <initializer_list>
32 #include <list>
33 #include <memory>
34 #include <type_traits>
35 #include <utility>
36 #include "hopscotch_hash.h"
37 
38 
39 namespace tsl {
40 
71 template<class Key,
72  class T,
73  class Hash = std::hash<Key>,
74  class KeyEqual = std::equal_to<Key>,
75  class Allocator = std::allocator<std::pair<Key, T>>,
76  unsigned int NeighborhoodSize = 62,
77  bool StoreHash = false,
78  class GrowthPolicy = tsl::power_of_two_growth_policy>
80 private:
81  template<typename U>
83 
84  class KeySelect {
85  public:
86  using key_type = Key;
87 
88  const key_type& operator()(const std::pair<Key, T>& key_value) const {
89  return key_value.first;
90  }
91 
92  key_type& operator()(std::pair<Key, T>& key_value) {
93  return key_value.first;
94  }
95  };
96 
97  class ValueSelect {
98  public:
99  using value_type = T;
100 
101  const value_type& operator()(const std::pair<Key, T>& key_value) const {
102  return key_value.second;
103  }
104 
105  value_type& operator()(std::pair<Key, T>& key_value) {
106  return key_value.second;
107  }
108  };
109 
110 
111  using overflow_container_type = std::list<std::pair<Key, T>, Allocator>;
113  Hash, KeyEqual,
114  Allocator, NeighborhoodSize,
115  StoreHash, GrowthPolicy,
116  overflow_container_type>;
117 
118 public:
119  using key_type = typename ht::key_type;
120  using mapped_type = T;
121  using value_type = typename ht::value_type;
122  using size_type = typename ht::size_type;
123  using difference_type = typename ht::difference_type;
124  using hasher = typename ht::hasher;
125  using key_equal = typename ht::key_equal;
126  using allocator_type = typename ht::allocator_type;
127  using reference = typename ht::reference;
128  using const_reference = typename ht::const_reference;
129  using pointer = typename ht::pointer;
130  using const_pointer = typename ht::const_pointer;
131  using iterator = typename ht::iterator;
132  using const_iterator = typename ht::const_iterator;
133 
134 
135 
136  /*
137  * Constructors
138  */
139  hopscotch_map() : hopscotch_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {
140  }
141 
142  explicit hopscotch_map(size_type bucket_count,
143  const Hash& hash = Hash(),
144  const KeyEqual& equal = KeyEqual(),
145  const Allocator& alloc = Allocator()) :
146  m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)
147  {
148  }
149 
150  hopscotch_map(size_type bucket_count,
151  const Allocator& alloc) : hopscotch_map(bucket_count, Hash(), KeyEqual(), alloc)
152  {
153  }
154 
155  hopscotch_map(size_type bucket_count,
156  const Hash& hash,
157  const Allocator& alloc) : hopscotch_map(bucket_count, hash, KeyEqual(), alloc)
158  {
159  }
160 
161  explicit hopscotch_map(const Allocator& alloc) : hopscotch_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
162  }
163 
164  template<class InputIt>
165  hopscotch_map(InputIt first, InputIt last,
166  size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
167  const Hash& hash = Hash(),
168  const KeyEqual& equal = KeyEqual(),
169  const Allocator& alloc = Allocator()) : hopscotch_map(bucket_count, hash, equal, alloc)
170  {
171  insert(first, last);
172  }
173 
174  template<class InputIt>
175  hopscotch_map(InputIt first, InputIt last,
176  size_type bucket_count,
177  const Allocator& alloc) : hopscotch_map(first, last, bucket_count, Hash(), KeyEqual(), alloc)
178  {
179  }
180 
181  template<class InputIt>
182  hopscotch_map(InputIt first, InputIt last,
183  size_type bucket_count,
184  const Hash& hash,
185  const Allocator& alloc) : hopscotch_map(first, last, bucket_count, hash, KeyEqual(), alloc)
186  {
187  }
188 
189  hopscotch_map(std::initializer_list<value_type> init,
190  size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
191  const Hash& hash = Hash(),
192  const KeyEqual& equal = KeyEqual(),
193  const Allocator& alloc = Allocator()) :
194  hopscotch_map(init.begin(), init.end(), bucket_count, hash, equal, alloc)
195  {
196  }
197 
198  hopscotch_map(std::initializer_list<value_type> init,
199  size_type bucket_count,
200  const Allocator& alloc) :
201  hopscotch_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
202  {
203  }
204 
205  hopscotch_map(std::initializer_list<value_type> init,
206  size_type bucket_count,
207  const Hash& hash,
208  const Allocator& alloc) :
209  hopscotch_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
210  {
211  }
212 
213 
214  hopscotch_map& operator=(std::initializer_list<value_type> ilist) {
215  m_ht.clear();
216 
217  m_ht.reserve(ilist.size());
218  m_ht.insert(ilist.begin(), ilist.end());
219 
220  return *this;
221  }
222 
223  allocator_type get_allocator() const { return m_ht.get_allocator(); }
224 
225 
226  /*
227  * Iterators
228  */
229  iterator begin() noexcept { return m_ht.begin(); }
230  const_iterator begin() const noexcept { return m_ht.begin(); }
231  const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
232 
233  iterator end() noexcept { return m_ht.end(); }
234  const_iterator end() const noexcept { return m_ht.end(); }
235  const_iterator cend() const noexcept { return m_ht.cend(); }
236 
237 
238  /*
239  * Capacity
240  */
241  bool empty() const noexcept { return m_ht.empty(); }
242  size_type size() const noexcept { return m_ht.size(); }
243  size_type max_size() const noexcept { return m_ht.max_size(); }
244 
245  /*
246  * Modifiers
247  */
248  void clear() noexcept { m_ht.clear(); }
249 
250 
251 
252 
253  std::pair<iterator, bool> insert(const value_type& value) {
254  return m_ht.insert(value);
255  }
256 
257  template<class P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
258  std::pair<iterator, bool> insert(P&& value) {
259  return m_ht.insert(std::forward<P>(value));
260  }
261 
262  std::pair<iterator, bool> insert(value_type&& value) {
263  return m_ht.insert(std::move(value));
264  }
265 
266 
267  iterator insert(const_iterator hint, const value_type& value) {
268  return m_ht.insert(hint, value);
269  }
270 
271  template<class P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
272  iterator insert(const_iterator hint, P&& value) {
273  return m_ht.insert(hint, std::forward<P>(value));
274  }
275 
276  iterator insert(const_iterator hint, value_type&& value) {
277  return m_ht.insert(hint, std::move(value));
278  }
279 
280 
281  template<class InputIt>
282  void insert(InputIt first, InputIt last) {
283  m_ht.insert(first, last);
284  }
285 
286  void insert(std::initializer_list<value_type> ilist) {
287  m_ht.insert(ilist.begin(), ilist.end());
288  }
289 
290 
291 
292 
293  template<class M>
294  std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) {
295  return m_ht.insert_or_assign(k, std::forward<M>(obj));
296  }
297 
298  template<class M>
299  std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) {
300  return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj));
301  }
302 
303  template<class M>
304  iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj) {
305  return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
306  }
307 
308  template<class M>
309  iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj) {
310  return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
311  }
312 
313 
314 
315 
322  template<class... Args>
323  std::pair<iterator, bool> emplace(Args&&... args) {
324  return m_ht.emplace(std::forward<Args>(args)...);
325  }
326 
327 
328 
329 
336  template<class... Args>
337  iterator emplace_hint(const_iterator hint, Args&&... args) {
338  return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
339  }
340 
341 
342 
343 
344  template<class... Args>
345  std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args) {
346  return m_ht.try_emplace(k, std::forward<Args>(args)...);
347  }
348 
349  template<class... Args>
350  std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args) {
351  return m_ht.try_emplace(std::move(k), std::forward<Args>(args)...);
352  }
353 
354  template<class... Args>
355  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args) {
356  return m_ht.try_emplace(hint, k, std::forward<Args>(args)...);
357  }
358 
359  template<class... Args>
360  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args) {
361  return m_ht.try_emplace(hint, std::move(k), std::forward<Args>(args)...);
362  }
363 
364 
365 
366 
367  iterator erase(iterator pos) { return m_ht.erase(pos); }
368  iterator erase(const_iterator pos) { return m_ht.erase(pos); }
369  iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
370  size_type erase(const key_type& key) { return m_ht.erase(key); }
371 
376  size_type erase(const key_type& key, std::size_t precalculated_hash) {
377  return m_ht.erase(key, precalculated_hash);
378  }
379 
384  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
385  size_type erase(const K& key) { return m_ht.erase(key); }
386 
393  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
394  size_type erase(const K& key, std::size_t precalculated_hash) {
395  return m_ht.erase(key, precalculated_hash);
396  }
397 
398 
399 
400 
401  void swap(hopscotch_map& other) { other.m_ht.swap(m_ht); }
402 
403  /*
404  * Lookup
405  */
406  T& at(const Key& key) { return m_ht.at(key); }
407 
412  T& at(const Key& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
413 
414 
415  const T& at(const Key& key) const { return m_ht.at(key); }
416 
420  const T& at(const Key& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
421 
422 
427  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
428  T& at(const K& key) { return m_ht.at(key); }
429 
436  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
437  T& at(const K& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
438 
439 
443  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
444  const T& at(const K& key) const { return m_ht.at(key); }
445 
449  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
450  const T& at(const K& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
451 
452 
453 
454 
455  T& operator[](const Key& key) { return m_ht[key]; }
456  T& operator[](Key&& key) { return m_ht[std::move(key)]; }
457 
458 
459 
460 
461  size_type count(const Key& key) const { return m_ht.count(key); }
462 
467  size_type count(const Key& key, std::size_t precalculated_hash) const {
468  return m_ht.count(key, precalculated_hash);
469  }
470 
475  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
476  size_type count(const K& key) const { return m_ht.count(key); }
477 
484  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
485  size_type count(const K& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
486 
487 
488 
489 
490  iterator find(const Key& key) { return m_ht.find(key); }
491 
496  iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
497 
498  const_iterator find(const Key& key) const { return m_ht.find(key); }
499 
503  const_iterator find(const Key& key, std::size_t precalculated_hash) const {
504  return m_ht.find(key, precalculated_hash);
505  }
506 
511  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
512  iterator find(const K& key) { return m_ht.find(key); }
513 
520  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
521  iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
522 
526  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
527  const_iterator find(const K& key) const { return m_ht.find(key); }
528 
535  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
536  const_iterator find(const K& key, std::size_t precalculated_hash) const {
537  return m_ht.find(key, precalculated_hash);
538  }
539 
540 
541 
542 
543  std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
544 
549  std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
550  return m_ht.equal_range(key, precalculated_hash);
551  }
552 
553  std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
554 
558  std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
559  return m_ht.equal_range(key, precalculated_hash);
560  }
561 
566  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
567  std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
568 
569 
576  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
577  std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
578  return m_ht.equal_range(key, precalculated_hash);
579  }
580 
584  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
585  std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
586 
590  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
591  std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
592  return m_ht.equal_range(key, precalculated_hash);
593  }
594 
595 
596 
597 
598  /*
599  * Bucket interface
600  */
601  size_type bucket_count() const { return m_ht.bucket_count(); }
602  size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
603 
604 
605  /*
606  * Hash policy
607  */
608  float load_factor() const { return m_ht.load_factor(); }
609  float max_load_factor() const { return m_ht.max_load_factor(); }
610  void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
611 
612  void rehash(size_type count) { m_ht.rehash(count); }
613  void reserve(size_type count) { m_ht.reserve(count); }
614 
615 
616  /*
617  * Observers
618  */
619  hasher hash_function() const { return m_ht.hash_function(); }
620  key_equal key_eq() const { return m_ht.key_eq(); }
621 
622  /*
623  * Other
624  */
625 
629  iterator mutable_iterator(const_iterator pos) {
630  return m_ht.mutable_iterator(pos);
631  }
632 
633  size_type overflow_size() const noexcept { return m_ht.overflow_size(); }
634 
635  friend bool operator==(const hopscotch_map& lhs, const hopscotch_map& rhs) {
636  if(lhs.size() != rhs.size()) {
637  return false;
638  }
639 
640  for(const auto& element_lhs : lhs) {
641  const auto it_element_rhs = rhs.find(element_lhs.first);
642  if(it_element_rhs == rhs.cend() || element_lhs.second != it_element_rhs->second) {
643  return false;
644  }
645  }
646 
647  return true;
648  }
649 
650  friend bool operator!=(const hopscotch_map& lhs, const hopscotch_map& rhs) {
651  return !operator==(lhs, rhs);
652  }
653 
654  friend void swap(hopscotch_map& lhs, hopscotch_map& rhs) {
655  lhs.swap(rhs);
656  }
657 
658 
659 
660 private:
661  ht m_ht;
662 };
663 
664 } // end namespace tsl
665 
666 #endif
iterator mutable_iterator(const_iterator pos)
const_iterator find(const K &key) const
std::pair< iterator, iterator > equal_range(const Key &key, std::size_t precalculated_hash)
size_type count(const K &key, std::size_t precalculated_hash) const
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t precalculated_hash) const
std::pair< iterator, iterator > equal_range(const K &key)
const_iterator find(const K &key, std::size_t precalculated_hash) const
size_type erase(const K &key)
T & at(const K &key, std::size_t precalculated_hash)
iterator find(const Key &key, std::size_t precalculated_hash)
size_type erase(const K &key, std::size_t precalculated_hash)
iterator emplace_hint(const_iterator hint, Args &&... args)
iterator find(const K &key)
std::pair< iterator, bool > emplace(Args &&... args)
size_type count(const K &key) const
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
const_iterator find(const Key &key, std::size_t precalculated_hash) const
size_type erase(const key_type &key, std::size_t precalculated_hash)
const T & at(const K &key, std::size_t precalculated_hash) const
const T & at(const Key &key, std::size_t precalculated_hash) const
std::pair< iterator, iterator > equal_range(const K &key, std::size_t precalculated_hash)
iterator find(const K &key, std::size_t precalculated_hash)
const T & at(const K &key) const
size_type count(const Key &key, std::size_t precalculated_hash) const
Structure required for the Sph Harmonic amplitude dictionary arguments.
OutputIteratorT OffsetT ReductionOpT OuputT init
< [in] The initial value of the reduction
Test structure used for several test.
Definition: Point_test.hpp:105
std::pair< const_iterator, const_iterator > equal_range(const Key &key, std::size_t precalculated_hash) const
T & at(const K &key)
T & at(const Key &key, std::size_t precalculated_hash)