HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_ArrayMap.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_ArrayMap.h (UT Library, C++)
7  *
8  * COMMENTS: Flat-array-based hash map implementation.
9  */
10 
11 #pragma once
12 
13 #ifndef __UT_ArrayMap__
14 #define __UT_ArrayMap__
15 
16 #include "UT_Array.h"
17 #include "UT_ArraySet.h"
18 #include "UT_IteratorRange.h"
19 
20 #include <hboost/functional/hash.hpp>
21 
22 #include <iterator>
23 #include <stdexcept>
24 #include <utility>
25 
26 namespace UT {
27 
28 template<class KeyEqual,typename Key,typename T>
30 {
31  bool operator()(const std::pair<Key,T> &a,const std::pair<Key,T> &b) const
32  {
33  return KeyEqual()(a.first, b.first);
34  }
35 };
36 
37 template<typename Hash,typename Key,typename T>
38 struct MapKeyHash
39 {
40  size_t operator()(const std::pair<Key,T> &a) const
41  {
42  return Hash()(a.first);
43  }
44 };
45 
46 template<typename S0,typename S1>
47 struct MapKeyClearer : public DefaultClearer<std::pair<S0,S1> >
48 {
50  using Base::clear;
51  /// Only need to actually check the key,
52  /// even though clear and clearConstruct will clear both.
53  static bool isClear(const std::pair<S0,S1> &v)
54  {
55  return DefaultClearer<S0>::isClear(v.first);
56  }
57  /// An overload for when there's only a key.
58  static bool isClear(const S0 &v)
59  {
61  }
64 };
65 
66 /// This is close to a drop-in replacement for std::unordered_map,
67 /// except that it uses a single array of items and empty spaces
68 /// marked with a dedicated "clear" value.
69 /// It also has a fixed maximum load factor, and doesn't store a
70 /// hasher, comparator, or allocator object as member data,
71 /// avoiding unnecessary overhead, but these differences introduce
72 /// some interface incompatibilities.
73 ///
74 /// See the comment on UT::ArraySet for specifics on these interface
75 /// incompatibilities. Most functions are inherited from UT::ArraySet.
76 template<
77  typename Key,
78  typename T,
79  bool MULTI=false,
80  std::size_t MAX_LOAD_FACTOR_256=128,
81  typename Clearer=MapKeyClearer<Key,T>,
82  class Hash=hboost::hash<Key>,
83  class KeyEqual=std::equal_to<Key>
84 >
85 class ArrayMap : public ArraySet<std::pair<Key,T>,MULTI,MAX_LOAD_FACTOR_256,Clearer,MapKeyHash<Hash,Key,T>,MapKeyEqual<KeyEqual,Key,T> >
86 {
87 public:
90  typedef Key key_type;
91  typedef T mapped_type;
92  typedef Hash hasher;
93  typedef KeyEqual key_equal;
94 
95  /// GCC and Clang can't find base class members in templated code, so we
96  /// need to declare explicitly that we're inheriting them.
97  using pointer = typename set_type::pointer;
99  using value_type = typename set_type::value_type;
100  using size_type = typename set_type::size_type;
101 
102  /// Inherit iterator and const_iterator
103  using iterator = typename set_type::iterator;
104  template<bool constant_type>
105  using iterator_t = typename set_type::template iterator_t<constant_type>;
107 
108  /// Inherit the constructors from ArraySet
109  using set_type::set_type;
110 
111  /// Inherit size from ArraySet.
112  using set_type::size;
113 
114  /// Inherit insert from ArraySet, in addition to signatures below.
115  using set_type::insert;
116 
117  std::pair<iterator, bool> insert(const Key &key, const T &val)
118  {
119  return insert(std::pair<Key,T>(key, val));
120  }
121  std::pair<iterator, bool> insert(Key &&key, T &&val)
122  {
123  return insert(std::make_pair(std::forward<Key>(key),
124  std::forward<T>(val)));
125  }
126 
127  bool operator==(const map_type &that) const
128  {
129  if (size() != that.size())
130  return false;
131 
132  // Check if one has no allocation (both empty)
133  if (!myBuckets || !that.myBuckets)
134  return true;
135 
136  const const_pointer pend = myBuckets + myNumBuckets;
137  for (const_pointer p = myBuckets; p != pend; ++p)
138  {
139  if (Clearer::isClear(*p))
140  continue;
141  // NOTE: Don't just use that.contains(*p), since it only checks the key!
142  const_iterator it = that.find(p->first);
143  if (it.atEnd())
144  return false;
145  if (*p != *it)
146  return false;
147  }
148  return true;
149  }
150  bool operator!=(const map_type &that) const
151  {
152  return !(*this == that);
153  }
154 
155  /// Returns an iterator to the first item matching key,
156  /// or an end iterator if no items match key.
157  /// @{
158  iterator find(const Key &key)
159  {
160  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
161 
162  const pointer pstart = myBuckets;
163  if (!pstart)
164  return iterator(nullptr,nullptr,false);
165 
166  const pointer pend = pstart + myNumBuckets;
167 
168  const pointer search_start = searchStart(key);
169  for (pointer p = search_start; p != pend; ++p)
170  {
171  if (key_equal()(key,p->first))
172  return iterator(p,pend,false);
173  if (Clearer::isClear(*p))
174  return iterator(pend,pend,false);
175  }
176  // Hit the end, so search back from before the start of the block.
177  for (pointer p = search_start-1; p >= pstart; --p)
178  {
179  if (key_equal()(key,p->first))
180  return iterator(p,pend,false);
181  if (Clearer::isClear(*p))
182  return iterator(pend,pend,false);
183  }
184  return iterator(pend,pend,false);
185  }
186  const_iterator find(const Key &key) const
187  {
188  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
189 
190  const const_pointer pstart = myBuckets;
191  if (!pstart)
192  return const_iterator(nullptr,nullptr,false);
193 
194  const const_pointer pend = pstart + myNumBuckets;
195 
196  const_pointer search_start = searchStart(key);
197  for (const_pointer p = search_start; p != pend; ++p)
198  {
199  if (key_equal()(key,p->first))
200  return const_iterator(p,pend,false);
201  if (Clearer::isClear(*p))
202  return const_iterator(pend,pend,false);
203  }
204  // Hit the end, so search back from before the start of the block.
205  for (const_pointer p = search_start-1; p >= pstart; --p)
206  {
207  if (key_equal()(key,p->first))
208  return const_iterator(p,pend,false);
209  if (Clearer::isClear(*p))
210  return const_iterator(pend,pend,false);
211  }
212  return const_iterator(pend,pend,false);
213  }
214  /// @}
215 
216  /// Returns the value at the key if it exists, or the provided default
217  /// value if it does not.
218  /// NOTE: Considering making this return const V&? Don't.
219  /// Lifetime extension rules likely can't be used to make that safe.
220  /// eg. const Foo &foo = get(key, Foo()) will return a stale reference.
221  mapped_type get(const key_type &key, const mapped_type &defval) const
222  {
223  auto it = this->find(key);
224  if (it == this->end())
225  return defval;
226  return it->second;
227  }
228 
229  /// Returns a reference to the value of the first item matching key.
230  /// WARNING: This throws an exception if nothing matches key!
231  /// @{
232  T &at(const Key &key)
233  {
234  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
235 
236  if (!myBuckets)
237  {
238  UT_ASSERT_MSG(0,"WARNING! An exception is about to be thrown in UT::ArrayMap::at!");
239  throw std::out_of_range("Key not found in UT::ArrayMap::at(const Key &)");
240  }
241 
242  const pointer pstart = myBuckets;
243  const const_pointer pend = pstart + myNumBuckets;
244  const pointer search_start = searchStart(key);
245  for (pointer p = search_start; p != pend; ++p)
246  {
247  if (key_equal()(key,p->first))
248  return p->second;
249  if (Clearer::isClear(*p))
250  {
251  UT_ASSERT_MSG(0,"WARNING! An exception is about to be thrown in UT::ArrayMap::at!");
252  throw std::out_of_range("Key not found in UT::ArrayMap::at(const Key &)");
253  }
254  }
255  // Hit the end, so search back from before the start of the block.
256  for (pointer p = search_start-1; p >= pstart; --p)
257  {
258  if (key_equal()(key,p->first))
259  return p->second;
260  if (Clearer::isClear(*p))
261  {
262  UT_ASSERT_MSG(0,"WARNING! An exception is about to be thrown in UT::ArrayMap::at!");
263  throw std::out_of_range("Key not found in UT::ArrayMap::at(const Key &)");
264  }
265  }
266  UT_ASSERT_MSG(0,"WARNING! An exception is about to be thrown in UT::ArrayMap::at!");
267  throw std::out_of_range("Key not found in UT::ArrayMap::at(const Key &)");
268  }
269  const T &at(const Key &key) const
270  {
271  if (!myBuckets)
272  {
273  UT_ASSERT_MSG(0,"WARNING! An exception is about to be thrown in UT::ArrayMap!");
274  throw std::out_of_range("Key not found in UT::ArrayMap::at(const Key &) const");
275  }
276 
277  const const_pointer pstart = myBuckets;
278  const const_pointer pend = pstart + myNumBuckets;
279  const_pointer search_start = searchStart(key);
280  for (const_pointer p = search_start; p != pend; ++p)
281  {
282  if (key_equal()(key,p->first))
283  return p->second;
284  if (Clearer::isClear(*p))
285  {
286  UT_ASSERT_MSG(0,"WARNING! An exception is about to be thrown in UT::ArrayMap!");
287  throw std::out_of_range("Key not found in UT::ArrayMap::at(const Key &) const");
288  }
289  }
290  // Hit the end, so search back from before the start of the block.
291  for (const_pointer p = search_start-1; p >= pstart; --p)
292  {
293  if (key_equal()(key,p->first))
294  return p->second;
295  if (Clearer::isClear(*p))
296  {
297  UT_ASSERT_MSG(0,"WARNING! An exception is about to be thrown in UT::ArrayMap!");
298  throw std::out_of_range("Key not found in UT::ArrayMap::at(const Key &) const");
299  }
300  }
301  UT_ASSERT_MSG(0,"WARNING! An exception is about to be thrown in UT::ArrayMap!");
302  throw std::out_of_range("Key not found in UT::ArrayMap::at(const Key &) const");
303  }
304  /// @}
305 
306  /// Returns the number of entries matching key.
307  /// If MULTI is false, this will only return either 0 or 1.
308  size_type count(const Key &key) const
309  {
310  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
311 
312  if (!myBuckets)
313  return 0;
314 
315  const const_pointer pstart = myBuckets;
316  const const_pointer pend = pstart + myNumBuckets;
317  const_pointer search_start = searchStart(key);
318  size_type count = 0;
319  for (const_pointer p = search_start; p != pend; ++p)
320  {
321  if (key_equal()(key,p->first))
322  {
323  if (!MULTI)
324  return 1;
325  ++count;
326  }
327  if (Clearer::isClear(*p))
328  return MULTI ? count : 0;
329  }
330  // Hit the end, so search back from before the start of the block.
331  for (const_pointer p = search_start-1; p >= pstart; --p)
332  {
333  if (key_equal()(key,p->first))
334  {
335  if (!MULTI)
336  return 1;
337  ++count;
338  }
339  if (Clearer::isClear(*p))
340  return MULTI ? count : 0;
341  }
342  return MULTI ? count : 0;
343  }
344 
345  /// Returns true iff the set contains the given key.
346  /// This should be faster than count() if MULTI is true.
347  bool contains(const Key &key) const
348  {
349  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
350 
351  if (!myBuckets)
352  return false;
353 
354  const const_pointer pstart = myBuckets;
355  const const_pointer pend = pstart + myNumBuckets;
356  const_pointer search_start = searchStart(key);
357  for (const_pointer p = search_start; p != pend; ++p)
358  {
359  if (key_equal()(key,p->first))
360  return true;
361  if (Clearer::isClear(*p))
362  return false;
363  }
364  // Hit the end, so search back from before the start of the block.
365  for (const_pointer p = search_start-1; p >= pstart; --p)
366  {
367  if (key_equal()(key,p->first))
368  return true;
369  if (Clearer::isClear(*p))
370  return false;
371  }
372  return false;
373  }
374 
375  /// Returns a reference to the first value that is mapped-to from a key
376  /// matching key, inserting if none exist.
377  /// NOTE: If you use this, key cannot match the key of a pair
378  /// cleared by Clearer, else insertHelper will assert.
379  T &operator[](const Key &key)
380  {
381  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
382 
383  iterator it = find(key);
384  if (!it.atEnd())
385  return it->second;
386 
387  // NOTE: Must use value initialization (not to be confused with default
388  // constructor!) for second, so that, e.g. ints will be
389  // initialized to zero and pointers will be nullptr.
390  value_type value(key, mapped_type());
391 
392  pointer dest;
393  set_type::template insertHelper<false,true>(myBuckets,myNumBuckets,value,dest);
394  *dest = std::move(value);
395  ++*((size_type*)(myBuckets+myNumBuckets));
396  return dest->second;
397  }
398 
399  /// Returns a reference to the first value that is mapped-to from a key
400  /// matching key, inserting if none exist.
401  /// NOTE: If you use this, key cannot match the key of a pair
402  /// cleared by Clearer, else insertHelper will assert.
403  T &operator[](Key &&key)
404  {
405  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
406 
407  iterator it = find(key);
408  if (!it.atEnd())
409  return it->second;
410 
411  // NOTE: Must use value initialization (not to be confused with default
412  // constructor!) for second, so that, e.g. ints will be
413  // initialized to zero and pointers will be nullptr.
414  value_type value(std::move(key), mapped_type());
415 
416  pointer dest;
417  set_type::template insertHelper<false,true>(myBuckets,myNumBuckets,value,dest);
418  *dest = std::move(value);
419  ++*((size_type*)(myBuckets+myNumBuckets));
420  return dest->second;
421  }
422 
423  /// Returns a pair of iterators representing the range of values matching
424  /// key, as [first,second).
425  /// @{
426  std::pair<const_iterator,const_iterator> equal_range(const Key &key) const
427  {
428  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
429 
430  const const_pointer pstart = myBuckets;
431  const const_pointer pend = pstart + myNumBuckets;
432  if (!pstart)
433  return std::make_pair(const_iterator(nullptr,nullptr,false), const_iterator(nullptr,nullptr,false));
434 
435  const const_pointer search_start = searchStart(key);
436  if (!MULTI)
437  {
438  for (const_pointer p = search_start; p != pend; ++p)
439  {
440  if (key_equal()(key,p->first))
441  return std::make_pair(const_iterator(p,pend,false), const_iterator(p+1,pend,true));
442  if (Clearer::isClear(*p))
443  return std::make_pair(const_iterator(pend,pend,false), const_iterator(pend,pend,false));
444  }
445  // Hit the end, so search back from before the start of the block.
446  for (const_pointer p = search_start-1; p >= pstart; --p)
447  {
448  if (key_equal()(key,p->first))
449  return std::make_pair(const_iterator(p,pend,false), const_iterator(p+1,pend,true));
450  if (Clearer::isClear(*p))
451  return std::make_pair(const_iterator(pend,pend,false), const_iterator(pend,pend,false));
452  }
453  return std::make_pair(const_iterator(pend,pend,false), const_iterator(pend,pend,false));
454  }
455 
456  // MULTI is true, so we might have multiple matches
457  const_pointer first_found = nullptr;
458  const_pointer end_found = pend;
459  for (const_pointer p = search_start; p != pend; ++p)
460  {
461  if (key_equal()(key,p->first))
462  {
463  if (!first_found)
464  first_found = p;
465  }
466  else if (first_found)
467  {
468  if (first_found != search_start)
469  return std::make_pair(const_iterator(first_found,pend,false), const_iterator(p,pend,true));
470 
471  end_found = p;
472  break;
473  }
474  else if (Clearer::isClear(*p))
475  {
476  // NOTE: first_found must be false
477  return std::make_pair(const_iterator(pend,pend,false), const_iterator(pend,pend,false));
478  }
479  }
480 
481  // Hit the end, so search back from before the start of the block.
482  for (const_pointer p = search_start-1; p >= pstart; --p)
483  {
484  if (!key_equal()(key,p->first))
485  {
486  return std::make_pair(const_iterator(p+1,pend,false), const_iterator(end_found,pend,true));
487  }
488  }
489  return std::make_pair(const_iterator(pstart,pend,false), const_iterator(end_found,pend,true));
490  }
491  std::pair<iterator,iterator> equal_range(const Key &key)
492  {
493  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
494 
495  const pointer pstart = myBuckets;
496  const pointer pend = pstart + myNumBuckets;
497  if (!pstart)
498  return std::make_pair(iterator(nullptr,nullptr,false), iterator(nullptr,nullptr,false));
499 
500  const pointer search_start = searchStart(key);
501  if (!MULTI)
502  {
503  for (pointer p = search_start; p != pend; ++p)
504  {
505  if (key_equal()(key,p->first))
506  return std::make_pair(iterator(p,pend,false), iterator(p+1,pend,true));
507  if (Clearer::isClear(*p))
508  return std::make_pair(iterator(pend,pend,false), iterator(pend,pend,false));
509  }
510  // Hit the end, so search back from before the start of the block.
511  for (pointer p = search_start-1; p >= pstart; --p)
512  {
513  if (key_equal()(key,p->first))
514  return std::make_pair(iterator(p,pend,false), iterator(p+1,pend,true));
515  if (Clearer::isClear(*p))
516  return std::make_pair(iterator(pend,pend,false), iterator(pend,pend,false));
517  }
518  return std::make_pair(iterator(pend,pend,false), iterator(pend,pend,false));
519  }
520 
521  // MULTI is true, so we might have multiple matches
522  pointer first_found = nullptr;
523  pointer end_found = pend;
524  for (pointer p = search_start; p != pend; ++p)
525  {
526  if (key_equal()(key,p->first))
527  {
528  if (!first_found)
529  first_found = p;
530  }
531  else if (first_found)
532  {
533  if (first_found != search_start)
534  return std::make_pair(iterator(first_found,pend,false), iterator(p,pend,true));
535 
536  end_found = p;
537  break;
538  }
539  else if (Clearer::isClear(*p))
540  {
541  // NOTE: first_found must be false
542  return std::make_pair(iterator(pend,pend,false), iterator(pend,pend,false));
543  }
544  }
545 
546  // Hit the end, so search back from before the start of the block.
547  for (pointer p = search_start-1; p >= pstart; --p)
548  {
549  if (!key_equal()(key,p->first))
550  {
551  return std::make_pair(iterator(p+1,pend,false), iterator(end_found,pend,true));
552  }
553  }
554  return std::make_pair(iterator(pstart,pend,false), iterator(end_found,pend,true));
555  }
556  /// @}
557 
558  /// Inherit erase from ArraySet, in addition to signatures below.
559  using set_type::erase;
560 
561  /// Removes all items matching key and returns
562  /// the number of items removed.
563  size_type erase(const Key &key)
564  {
565  UT_ASSERT_MSG_P(!Clearer::isClear(key),"Don't query a clear key!");
566 
567  if (!MULTI)
568  {
569  iterator it = find(key);
570  if (it.atEnd())
571  return 0;
572  erase(it);
573  return 1;
574  }
575 
576  // NOTE: This commented out code won't work, because the 2-argument erase isn't implemented.
577  //std::pair<iterator,iterator> its = equal_range(key);
578  //size_type count = std::distance(its.first, its.second);
579  //erase(its.first, its.second);
580 
581  size_type count = 0;
582  for (iterator it = find(key); !it.atEnd(); it = find(key))
583  {
584  erase(it);
585  }
586  return count;
587  }
588 
589  template<typename FUNCTOR>
591  void forEachKey(FUNCTOR &&functor) const
592  {
594  const const_pointer pend = p + myNumBuckets;
595  for (; p != pend; ++p)
596  {
597  if (!Clearer::isClear(*p))
598  functor(p->first);
599  }
600  }
601 
602  template<typename FUNCTOR>
604  void forEachValue(FUNCTOR &&functor) const
605  {
607  const const_pointer pend = p + myNumBuckets;
608  for (; p != pend; ++p)
609  {
610  if (!Clearer::isClear(*p))
611  functor(p->second);
612  }
613  }
614 
615  template<bool constant_type>
617  {
618  public:
619  typedef std::forward_iterator_tag iterator_category;
620  typedef std::ptrdiff_t difference_type;
625 
626  template<typename COMPARATOR>
627  ordered_iterator_t(map_type &map, const COMPARATOR &comparator)
628  : myMap(map)
629  , myI(0)
630  {
631  myKeys.setCapacity(map.size());
632  map.forEachKey([this](const Key &key) {
633  myKeys.append(key);
634  });
635  myKeys.sort(comparator);
636  }
638  : myMap(that.myMap)
639  , myKeys(std::move(that.myKeys))
640  , myI(that.myI)
641  {}
643  {
644  return *myMap.find(myKeys[myI]);
645  }
647  {
648  return &*myMap.find(myKeys[myI]);
649  }
650  operator pointer() const
651  {
652  return &*myMap.find(myKeys[myI]);
653  }
654  void operator++()
655  {
656  ++myI;
657  }
658  bool atEnd() const
659  {
660  return myI >= myKeys.size();
661  }
662  private:
663  /// Use atEnd(), not ==
664  bool operator==(const ordered_iterator_t<constant_type> &) const = delete;
665  bool operator!=(const ordered_iterator_t<constant_type> &) const = delete;
666 
667  map_type &myMap;
668  UT_Array<Key> myKeys;
669  exint myI;
670  };
671 
672  template<typename COMPARATOR>
673  ordered_iterator_t<true> ordered_begin(const COMPARATOR &comparator) const
674  {
675  return ordered_iterator_t<true>(*this, comparator);
676  }
677 
678  template<typename COMPARATOR>
679  ordered_iterator_t<true> ordered_cbegin(const COMPARATOR &comparator) const
680  {
681  return ordered_iterator_t<true>(*this, comparator);
682  }
683 
684  template<typename COMPARATOR>
685  ordered_iterator_t<false> ordered_begin(const COMPARATOR &comparator)
686  {
687  return ordered_iterator_t<false>(*this, comparator);
688  }
689 
690 protected:
691  template<typename VIT, typename VT>
693  {
694  VT &operator()(const VIT &v) const { return v->first; }
695  };
696  template<typename VIT, typename VT>
698  {
699  VT &operator()(const VIT &v) const { return v->second; }
700  };
701 
702  template<typename IT, typename VT, typename DR>
704  {
705  public:
706  using iterator_category = std::forward_iterator_tag;
707  using value_type = VT;
708  using difference_type = std::ptrdiff_t;
709  using pointer = value_type*;
711 
713 
714  template<typename EIT, typename EDR>
716  it(src.it) {}
717 
718  reference operator*() const { DR dr; return dr(it); }
719  pointer operator->() const { DR dr; return &dr(it); }
720 
722  { return it == o.it; }
723 
725  { return it != o.it; }
726 
728  {
729  ++it;
730  return *this;
731  }
732 
733  protected:
734  friend class ArrayMap;
735 
736  partial_iterator_base(IT it) : it(it) {}
737  private:
738  IT it;
739  };
740 
741 public:
742  using const_key_iterator = partial_iterator_base<const_iterator, const key_type,
743  deref_pair_first<const_iterator, const key_type>>;
744  using mapped_iterator = partial_iterator_base<iterator, mapped_type,
745  deref_pair_second<iterator, mapped_type>>;
746  using const_mapped_iterator = partial_iterator_base<const_iterator, const mapped_type,
747  deref_pair_second<const_iterator, const mapped_type>>;
748 
749  /// Returns a const range object that iterates over the map but returns
750  /// only the key values.
751  /// Example:
752  /// @code
753  /// UT::ArrayMap<int, const char *> foo = {{1, "one"}, {2, "two"}};
754  /// for (int key : foo.key_range())
755  /// std::cout << key << "\n";
756  /// @endcode
758  { return UTmakeRange(const_key_iterator(this->begin()),
759  const_key_iterator(this->end())); }
760 
761  /// Returns a range object that iterates over the map but returns only
762  /// the mapped values.
764  { return UTmakeRange(mapped_iterator(this->begin()),
765  mapped_iterator(this->end())); }
766 
767  /// Returns a const range object that iterates over the map but returns
768  /// only the mapped values.
770  { return UTmakeRange(const_mapped_iterator(this->begin()),
771  const_mapped_iterator(this->end())); }
772 
773 private:
774  /// GCC and Clang can't find base class members in templated code, so we
775  /// need to declare explicitly that we're inheriting them.
776  using set_type::myBuckets;
778 
779  pointer searchStart(const Key &key)
780  {
781  const size_type hash = hasher()(key);
782  return myBuckets + (hash%myNumBuckets);
783  }
784  const_pointer searchStart(const Key &key) const
785  {
786  const size_type hash = hasher()(key);
787  return myBuckets + (hash%myNumBuckets);
788  }
789 };
790 
791 template<
792  typename Key,
793  typename T,
794  bool MULTI,
795  std::size_t MAX_LOAD_FACTOR_256,
796  typename Clearer,
797  class Hash,
798  class KeyEqual
799 >
800 struct DefaultClearer<ArrayMap<Key,T,MULTI,MAX_LOAD_FACTOR_256,Clearer,Hash,KeyEqual> >
801  : public DefaultClearer<typename ArrayMap<Key,T,MULTI,MAX_LOAD_FACTOR_256,Clearer,Hash,KeyEqual>::set_type>
802 {};
803 
804 } // namespace UT
805 
806 template<typename Key,
807  typename T,
808  bool MULTI = false,
809  int MAX_LOAD_FACTOR_256 = 128,
810  typename Clearer = UT::MapKeyClearer<Key,T>,
811  class Hash = hboost::hash<Key>,
812  class KeyEqual = std::equal_to<Key> >
814 
815 #endif
type
Definition: core.h:556
UT_IteratorRange< const_mapped_iterator > mapped_range() const
Definition: UT_ArrayMap.h:769
ArrayMap< Key, T, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > map_type
Definition: UT_ArrayMap.h:89
T & at(const Key &key)
Definition: UT_ArrayMap.h:232
bool contains(const Key &key) const
Definition: UT_ArrayMap.h:347
STATIC_INLINE size_t Hash(const char *s, size_t len)
Definition: farmhash.h:2099
SYS_FORCE_INLINE void forEachValue(FUNCTOR &&functor) const
Definition: UT_ArrayMap.h:604
ordered_iterator_t< true > ordered_cbegin(const COMPARATOR &comparator) const
Definition: UT_ArrayMap.h:679
ordered_iterator_t(map_type &map, const COMPARATOR &comparator)
Definition: UT_ArrayMap.h:627
bool operator==(const map_type &that) const
Definition: UT_ArrayMap.h:127
const GLdouble * v
Definition: glcorearb.h:837
GLsizei const GLfloat * value
Definition: glcorearb.h:824
T & operator[](Key &&key)
Definition: UT_ArrayMap.h:403
std::conditional< constant_type, typename set_type::const_pointer, typename set_type::pointer >::type pointer
Definition: UT_ArrayMap.h:623
UT_IteratorRange< IterT > UTmakeRange(IterT &&b, IterT &&e)
int64 exint
Definition: SYS_Types.h:125
std::pair< const_iterator, const_iterator > equal_range(const Key &key) const
Definition: UT_ArrayMap.h:426
SYS_FORCE_INLINE void forEachKey(FUNCTOR &&functor) const
Definition: UT_ArrayMap.h:591
bool operator==(const partial_iterator_base< IT, VT, DR > &o) const
Definition: UT_ArrayMap.h:721
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
partial_iterator_base & operator++()
Definition: UT_ArrayMap.h:727
partial_iterator_base< const_iterator, const mapped_type, deref_pair_second< const_iterator, const mapped_type >> const_mapped_iterator
Definition: UT_ArrayMap.h:747
const T & at(const Key &key) const
Definition: UT_ArrayMap.h:269
void setCapacity(exint new_capacity)
#define UT_ASSERT_MSG_P(ZZ,...)
Definition: UT_Assert.h:158
std::forward_iterator_tag iterator_category
Definition: UT_ArrayMap.h:619
ordered_iterator_t< true > ordered_begin(const COMPARATOR &comparator) const
Definition: UT_ArrayMap.h:673
exint size() const
Definition: UT_Array.h:653
reference operator*() const
Definition: UT_ArrayMap.h:642
iterator find(const Key &key)
Definition: UT_ArrayMap.h:158
T & operator[](const Key &key)
Definition: UT_ArrayMap.h:379
ArraySet< std::pair< Key, T >, MULTI, MAX_LOAD_FACTOR_256, Clearer, MapKeyHash< Hash, Key, T >, MapKeyEqual< KeyEqual, Key, T > > set_type
Definition: UT_ArraySet.h:230
std::conditional< constant_type, const typename ArrayMap::map_type, typename ArrayMap::map_type >::type map_type
Definition: UT_ArrayMap.h:624
#define UT_ASSERT_MSG(ZZ,...)
Definition: UT_Assert.h:159
std::conditional< constant_type, const value_type, value_type >::type & reference
Definition: UT_ArrayMap.h:622
bool operator()(const std::pair< Key, T > &a, const std::pair< Key, T > &b) const
Definition: UT_ArrayMap.h:31
typename set_type::const_pointer const_pointer
Definition: UT_ArrayMap.h:98
typename set_type::size_type size_type
Definition: UT_ArrayMap.h:100
std::size_t size_type
Definition: UT_ArraySet.h:233
partial_iterator_base< const_iterator, const key_type, deref_pair_first< const_iterator, const key_type >> const_key_iterator
Definition: UT_ArrayMap.h:743
static void clearConstruct(std::pair< S0, S1 > *p)
Definition: UT_ArraySet.h:123
std::pair< iterator, iterator > equal_range(const Key &key)
Definition: UT_ArrayMap.h:491
void sort(ComparatorBool is_less={})
Sort using std::sort with bool comparator. Defaults to operator<().
Definition: UT_Array.h:463
size_t operator()(const std::pair< Key, T > &a) const
Definition: UT_ArrayMap.h:40
std::pair< iterator, bool > insert(const Key &key, const T &val)
Definition: UT_ArrayMap.h:117
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
partial_iterator_base(const partial_iterator_base< EIT, VT, EDR > &src)
Definition: UT_ArrayMap.h:715
Set iterator class.
Definition: UT_ArraySet.h:614
ordered_iterator_t(ordered_iterator_t< constant_type > &&that)
Definition: UT_ArrayMap.h:637
size_type erase(const Key &key)
Definition: UT_ArrayMap.h:563
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
exint append()
Definition: UT_Array.h:142
static bool isClear(const std::pair< S0, S1 > &v)
Definition: UT_ArrayMap.h:53
partial_iterator_base< iterator, mapped_type, deref_pair_second< iterator, mapped_type >> mapped_iterator
Definition: UT_ArrayMap.h:745
ordered_iterator_t< false > ordered_begin(const COMPARATOR &comparator)
Definition: UT_ArrayMap.h:685
std::conditional< constant_type, const typename ArrayMap::value_type, typename ArrayMap::value_type >::type value_type
Definition: UT_ArrayMap.h:621
GLenum void ** pointer
Definition: glcorearb.h:810
const_iterator find(const Key &key) const
Definition: UT_ArrayMap.h:186
size_type count(const Key &key) const
Definition: UT_ArrayMap.h:308
static bool isClear(const S0 &v)
An overload for when there's only a key.
Definition: UT_ArrayMap.h:58
bool operator!=(const map_type &that) const
Definition: UT_ArrayMap.h:150
bool operator!=(const partial_iterator_base< IT, VT, DR > &o) const
Definition: UT_ArrayMap.h:724
typename set_type::iterator iterator
Inherit iterator and const_iterator.
Definition: UT_ArrayMap.h:103
VT & operator()(const VIT &v) const
Definition: UT_ArrayMap.h:699
const value_type * const_pointer
Definition: UT_ArraySet.h:240
GLuint GLfloat * val
Definition: glcorearb.h:1608
static void clear(std::pair< S0, S1 > &v)
Definition: UT_ArraySet.h:114
KeyEqual key_equal
Definition: UT_ArrayMap.h:93
typename set_type::template iterator_t< constant_type > iterator_t
Definition: UT_ArrayMap.h:105
std::pair< iterator, bool > insert(Key &&key, T &&val)
Definition: UT_ArrayMap.h:121
VT & operator()(const VIT &v) const
Definition: UT_ArrayMap.h:694
std::forward_iterator_tag iterator_category
Definition: UT_ArrayMap.h:706
UT_IteratorRange< const_key_iterator > key_range() const
Definition: UT_ArrayMap.h:757
typename set_type::const_iterator const_iterator
Definition: UT_ArrayMap.h:106
GLint GLsizei count
Definition: glcorearb.h:405
UT_IteratorRange< mapped_iterator > mapped_range()
Definition: UT_ArrayMap.h:763
ArraySet< std::pair< Key, T >, MULTI, MAX_LOAD_FACTOR_256, Clearer, MapKeyHash< Hash, Key, T >, MapKeyEqual< KeyEqual, Key, T > > set_type
Definition: UT_ArrayMap.h:88
GLenum src
Definition: glcorearb.h:1793
value_type * pointer
Definition: UT_ArraySet.h:239