momo  3.9
unordered_multimap.h
Go to the documentation of this file.
1 /**********************************************************\
2 
3  This file is part of the
4  https://github.com/morzhovets/momo
5  project, distributed under the MIT License. See
6  https://github.com/morzhovets/momo/blob/branch_cpp11/LICENSE
7  for details.
8 
9  momo/stdish/unordered_multimap.h
10 
11  namespace momo::stdish:
12  class unordered_multimap
13  class unordered_multimap_open
14 
15 \**********************************************************/
16 
17 #ifndef MOMO_INCLUDE_GUARD_STDISH_UNORDERED_MULTIMAP
18 #define MOMO_INCLUDE_GUARD_STDISH_UNORDERED_MULTIMAP
19 
20 #include "../HashMultiMap.h"
21 
22 namespace momo
23 {
24 
25 namespace stdish
26 {
27 
57 template<typename TKey, typename TMapped,
58  typename THashFunc = HashCoder<TKey>,
59  typename TEqualFunc = std::equal_to<TKey>,
60  typename TAllocator = std::allocator<std::pair<const TKey, TMapped>>,
61  typename THashMultiMap = HashMultiMap<TKey, TMapped, HashTraitsStd<TKey, THashFunc, TEqualFunc>,
62  MemManagerStd<TAllocator>>>
64 {
65 private:
66  typedef THashMultiMap HashMultiMap;
67  typedef typename HashMultiMap::HashTraits HashTraits;
68  typedef typename HashMultiMap::MemManager MemManager;
69 
70 public:
71  typedef TKey key_type;
72  typedef TMapped mapped_type;
73  typedef THashFunc hasher;
74  typedef TEqualFunc key_equal;
75  typedef TAllocator allocator_type;
76 
77  typedef HashMultiMap nested_container_type;
78 
79  typedef size_t size_type;
80  typedef ptrdiff_t difference_type;
81 
82  typedef std::pair<const key_type, mapped_type> value_type;
83 
87 
88  typedef typename iterator::Reference reference;
90 
91  typedef typename iterator::Pointer pointer;
93  //typedef typename std::allocator_traits<allocator_type>::pointer pointer;
94  //typedef typename std::allocator_traits<allocator_type>::const_pointer const_pointer;
95 
96  //node_type;
97 
98  //local_iterator;
99  //const_local_iterator;
100 
101 private:
102  template<typename KeyArg>
103  struct IsValidKeyArg : public HashTraits::template IsValidKeyArg<KeyArg>
104  {
105  };
106 
107  struct ConstIteratorProxy : public const_iterator
108  {
109  typedef const_iterator ConstIterator;
110  MOMO_DECLARE_PROXY_CONSTRUCTOR(ConstIterator)
111  MOMO_DECLARE_PROXY_FUNCTION(ConstIterator, GetBaseIterator,
113  };
114 
115  struct IteratorProxy : public iterator
116  {
117  typedef iterator Iterator;
119  };
120 
121 public:
123  {
124  }
125 
126  explicit unordered_multimap(const allocator_type& alloc)
127  : mHashMultiMap(HashTraits(), MemManager(alloc))
128  {
129  }
130 
131  explicit unordered_multimap(size_type bucketCount,
132  const allocator_type& alloc = allocator_type())
133  : mHashMultiMap(HashTraits(bucketCount), MemManager(alloc))
134  {
135  }
136 
137  unordered_multimap(size_type bucketCount, const hasher& hashFunc,
138  const allocator_type& alloc = allocator_type())
139  : mHashMultiMap(HashTraits(bucketCount, hashFunc), MemManager(alloc))
140  {
141  }
142 
143  unordered_multimap(size_type bucketCount, const hasher& hashFunc, const key_equal& equalFunc,
144  const allocator_type& alloc = allocator_type())
145  : mHashMultiMap(HashTraits(bucketCount, hashFunc, equalFunc), MemManager(alloc))
146  {
147  }
148 
149  template<typename Iterator>
150  unordered_multimap(Iterator first, Iterator last)
151  {
152  insert(first, last);
153  }
154 
155  template<typename Iterator>
156  unordered_multimap(Iterator first, Iterator last, size_type bucketCount,
157  const allocator_type& alloc = allocator_type())
158  : unordered_multimap(bucketCount, alloc)
159  {
160  insert(first, last);
161  }
162 
163  template<typename Iterator>
164  unordered_multimap(Iterator first, Iterator last, size_type bucketCount,
165  const hasher& hashFunc, const allocator_type& alloc = allocator_type())
166  : unordered_multimap(bucketCount, hashFunc, alloc)
167  {
168  insert(first, last);
169  }
170 
171  template<typename Iterator>
172  unordered_multimap(Iterator first, Iterator last, size_type bucketCount,
173  const hasher& hashFunc, const key_equal& equalFunc,
174  const allocator_type& alloc = allocator_type())
175  : unordered_multimap(bucketCount, hashFunc, equalFunc, alloc)
176  {
177  insert(first, last);
178  }
179 
180  unordered_multimap(std::initializer_list<value_type> values)
181  : unordered_multimap(values.begin(), values.end())
182  {
183  }
184 
185  unordered_multimap(std::initializer_list<value_type> values, size_type bucketCount,
186  const allocator_type& alloc = allocator_type())
187  : unordered_multimap(values.begin(), values.end(), bucketCount, alloc)
188  {
189  }
190 
191  unordered_multimap(std::initializer_list<value_type> values, size_type bucketCount,
192  const hasher& hashFunc, const allocator_type& alloc = allocator_type())
193  : unordered_multimap(values.begin(), values.end(), bucketCount, hashFunc, alloc)
194  {
195  }
196 
197  unordered_multimap(std::initializer_list<value_type> values, size_type bucketCount,
198  const hasher& hashFunc, const key_equal& equalFunc,
199  const allocator_type& alloc = allocator_type())
200  : unordered_multimap(values.begin(), values.end(), bucketCount, hashFunc, equalFunc, alloc)
201  {
202  }
203 
205  : mHashMultiMap(std::move(right.mHashMultiMap))
206  {
207  }
208 
211  noexcept(std::is_empty<allocator_type>::value)
212  : mHashMultiMap(pvCreateMultiMap(std::move(right), alloc))
213  {
214  }
215 
217  : mHashMultiMap(right.mHashMultiMap)
218  {
219  }
220 
223  : mHashMultiMap(right.mHashMultiMap, MemManager(alloc))
224  {
225  }
226 
227  ~unordered_multimap() = default;
228 
230  noexcept(std::is_empty<allocator_type>::value ||
231  std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
232  {
233  if (this != &right)
234  {
235  bool propagate = std::is_empty<allocator_type>::value ||
236  std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value;
237  allocator_type alloc = (propagate ? &right : this)->get_allocator();
238  mHashMultiMap = pvCreateMultiMap(std::move(right), alloc);
239  }
240  return *this;
241  }
242 
244  {
245  if (this != &right)
246  {
247  bool propagate = std::is_empty<allocator_type>::value ||
248  std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value;
249  allocator_type alloc = (propagate ? &right : this)->get_allocator();
250  mHashMultiMap = HashMultiMap(right.mHashMultiMap, MemManager(alloc));
251  }
252  return *this;
253  }
254 
255  unordered_multimap& operator=(std::initializer_list<value_type> values)
256  {
257  HashMultiMap hashMultiMap(mHashMultiMap.GetHashTraits(), MemManager(get_allocator()));
258  hashMultiMap.Add(values.begin(), values.end());
259  mHashMultiMap = std::move(hashMultiMap);
260  return *this;
261  }
262 
263  void swap(unordered_multimap& right) noexcept
264  {
265  MOMO_ASSERT(std::allocator_traits<allocator_type>::propagate_on_container_swap::value
266  || get_allocator() == right.get_allocator());
267  mHashMultiMap.Swap(right.mHashMultiMap);
268  }
269 
270  friend void swap(unordered_multimap& left, unordered_multimap& right) noexcept
271  {
272  left.swap(right);
273  }
274 
276  {
277  return mHashMultiMap;
278  }
279 
281  {
282  return mHashMultiMap;
283  }
284 
285  const_iterator begin() const noexcept
286  {
287  return ConstIteratorProxy(mHashMultiMap.GetBegin());
288  }
289 
290  iterator begin() noexcept
291  {
292  return IteratorProxy(mHashMultiMap.GetBegin());
293  }
294 
295  const_iterator end() const noexcept
296  {
297  return ConstIteratorProxy(mHashMultiMap.GetEnd());
298  }
299 
300  iterator end() noexcept
301  {
302  return IteratorProxy(mHashMultiMap.GetEnd());
303  }
304 
305  const_iterator cbegin() const noexcept
306  {
307  return begin();
308  }
309 
310  const_iterator cend() const noexcept
311  {
312  return end();
313  }
314 
315  //float max_load_factor() const noexcept
316  //void max_load_factor(float maxLoadFactor)
317 
319  {
320  return mHashMultiMap.GetHashTraits().GetHashFunc();
321  }
322 
324  {
325  return mHashMultiMap.GetHashTraits().GetEqualFunc();
326  }
327 
328  allocator_type get_allocator() const noexcept
329  {
330  return allocator_type(mHashMultiMap.GetMemManager().GetByteAllocator());
331  }
332 
333  size_type max_size() const noexcept
334  {
335  return std::allocator_traits<allocator_type>::max_size(get_allocator());
336  }
337 
338  size_type size() const noexcept
339  {
340  return mHashMultiMap.GetValueCount();
341  }
342 
343  MOMO_NODISCARD bool empty() const noexcept
344  {
345  return size() == 0;
346  }
347 
348  void clear() noexcept
349  {
350  mHashMultiMap.Clear();
351  }
352 
353  //void rehash(size_type bucketCount)
354  //void reserve(size_type count)
355 
357  {
358  return equal_range(key).first;
359  }
360 
362  {
363  return equal_range(key).first;
364  }
365 
366  template<typename KeyArg>
368  const_iterator> find(const KeyArg& key) const
369  {
370  return equal_range(key).first;
371  }
372 
373  template<typename KeyArg>
375  iterator> find(const KeyArg& key)
376  {
377  return equal_range(key).first;
378  }
379 
381  {
382  typename HashMultiMap::ConstKeyIterator keyIter = mHashMultiMap.Find(key);
383  return !!keyIter ? keyIter->GetCount() : 0;
384  }
385 
386  template<typename KeyArg>
388  size_type> count(const KeyArg& key) const
389  {
390  typename HashMultiMap::ConstKeyIterator keyIter = mHashMultiMap.Find(key);
391  return !!keyIter ? keyIter->GetCount() : 0;
392  }
393 
394  MOMO_FORCEINLINE bool contains(const key_type& key) const
395  {
396  return count(key) > 0;
397  }
398 
399  template<typename KeyArg>
401  bool> contains(const KeyArg& key) const
402  {
403  return count(key) > 0;
404  }
405 
406  MOMO_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
407  {
408  return pvEqualRange<const_iterator, ConstIteratorProxy>(mHashMultiMap,
409  mHashMultiMap.Find(key));
410  }
411 
412  MOMO_FORCEINLINE std::pair<iterator, iterator> equal_range(const key_type& key)
413  {
414  return pvEqualRange<iterator, IteratorProxy>(mHashMultiMap, mHashMultiMap.Find(key));
415  }
416 
417  template<typename KeyArg>
419  std::pair<const_iterator, const_iterator>> equal_range(const KeyArg& key) const
420  {
421  return pvEqualRange<const_iterator, ConstIteratorProxy>(mHashMultiMap,
422  mHashMultiMap.Find(key));
423  }
424 
425  template<typename KeyArg>
427  std::pair<iterator, iterator>> equal_range(const KeyArg& key)
428  {
429  return pvEqualRange<iterator, IteratorProxy>(mHashMultiMap, mHashMultiMap.Find(key));
430  }
431 
432  //template<typename Value>
433  //momo::internal::EnableIf<std::is_constructible<value_type, Value>::value,
434  //iterator> insert(Value&& value)
435 
436  //template<typename Value>
437  //momo::internal::EnableIf<std::is_constructible<value_type, Value>::value,
438  //iterator> insert(const_iterator hint, Value&& value)
439 
440  //iterator insert(value_type&& value)
441 
442  //iterator insert(const_iterator hint, value_type&& value)
443 
444  //iterator insert(const value_type& value)
445 
446  //iterator insert(const_iterator hint, const value_type& value)
447 
448  iterator insert(std::pair<key_type, mapped_type>&& value)
449  {
450  return pvEmplace(std::forward_as_tuple(std::move(value.first)),
451  std::forward_as_tuple(std::move(value.second)));
452  }
453 
454  iterator insert(const_iterator, std::pair<key_type, mapped_type>&& value)
455  {
456  return insert(std::move(value));
457  }
458 
459  template<typename First, typename Second>
461  && std::is_constructible<mapped_type, const Second&>::value,
462  iterator> insert(const std::pair<First, Second>& value)
463  {
464  return pvEmplace(std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
465  }
466 
467  template<typename First, typename Second>
469  && std::is_constructible<mapped_type, const Second&>::value,
470  iterator> insert(const_iterator, const std::pair<First, Second>& value)
471  {
472  return insert(value);
473  }
474 
475  template<typename First, typename Second>
477  && std::is_constructible<mapped_type, Second&&>::value,
478  iterator> insert(std::pair<First, Second>&& value)
479  {
480  return pvEmplace(std::forward_as_tuple(std::forward<First>(value.first)),
481  std::forward_as_tuple(std::forward<Second>(value.second)));
482  }
483 
484  template<typename First, typename Second>
486  && std::is_constructible<mapped_type, Second&&>::value,
487  iterator> insert(const_iterator, std::pair<First, Second>&& value)
488  {
489  return insert(std::move(value));
490  }
491 
492  template<typename Iterator>
493  void insert(Iterator first, Iterator last)
494  {
496  }
497 
498  void insert(std::initializer_list<value_type> values)
499  {
500  mHashMultiMap.Add(values.begin(), values.end());
501  }
502 
504  {
505  return pvEmplace(std::tuple<>(), std::tuple<>());
506  }
507 
509  {
510  return emplace();
511  }
512 
513  template<typename ValueArg>
514  iterator emplace(ValueArg&& valueArg)
515  {
516  return insert(std::forward<ValueArg>(valueArg));
517  }
518 
519  template<typename ValueArg>
520  iterator emplace_hint(const_iterator, ValueArg&& valueArg)
521  {
522  return emplace(std::forward<ValueArg>(valueArg));
523  }
524 
525  template<typename KeyArg, typename MappedArg>
526  iterator emplace(KeyArg&& keyArg, MappedArg&& mappedArg)
527  {
528  return pvEmplace(std::forward_as_tuple(std::forward<KeyArg>(keyArg)),
529  std::forward_as_tuple(std::forward<MappedArg>(mappedArg)));
530  }
531 
532  template<typename KeyArg, typename MappedArg>
533  iterator emplace_hint(const_iterator, KeyArg&& keyArg, MappedArg&& mappedArg)
534  {
535  return emplace(std::forward<KeyArg>(keyArg), std::forward<MappedArg>(mappedArg));
536  }
537 
538  template<typename... KeyArgs, typename... MappedArgs>
539  iterator emplace(std::piecewise_construct_t,
540  std::tuple<KeyArgs...> keyArgs, std::tuple<MappedArgs...> mappedArgs)
541  {
542  return pvEmplace(std::move(keyArgs), std::move(mappedArgs));
543  }
544 
545  template<typename... KeyArgs, typename... MappedArgs>
546  iterator emplace_hint(const_iterator, std::piecewise_construct_t,
547  std::tuple<KeyArgs...> keyArgs, std::tuple<MappedArgs...> mappedArgs)
548  {
549  return pvEmplace(std::move(keyArgs), std::move(mappedArgs));
550  }
551 
553  {
554  typename HashMultiMap::ConstIterator iter = ConstIteratorProxy::GetBaseIterator(where);
555  typename HashMultiMap::ConstKeyIterator keyIter = iter.GetKeyIterator();
556  if (keyIter->GetCount() == 1)
557  return IteratorProxy(mHashMultiMap.MakeIterator(mHashMultiMap.RemoveKey(keyIter)));
558  else
559  return IteratorProxy(mHashMultiMap.Remove(iter));
560  }
561 
563  {
564  return erase(static_cast<const_iterator>(where));
565  }
566 
568  {
569  if (first == begin() && last == end())
570  {
571  clear();
572  return end();
573  }
574  if (first == last)
575  {
576  return IteratorProxy(mHashMultiMap.MakeMutableIterator(
577  ConstIteratorProxy::GetBaseIterator(first)));
578  }
579  if (first != end())
580  {
581  if (std::next(first) == last)
582  return erase(first);
583  typename HashMultiMap::ConstKeyIterator keyIter =
584  ConstIteratorProxy::GetBaseIterator(first).GetKeyIterator();
585  if (last == ConstIteratorProxy(mHashMultiMap.MakeIterator(keyIter, keyIter->GetCount())))
586  return IteratorProxy(mHashMultiMap.MakeIterator(mHashMultiMap.RemoveKey(keyIter)));
587  }
588  throw std::invalid_argument("invalid unordered_multimap erase arguments");
589  }
590 
592  {
593  return mHashMultiMap.RemoveKey(key);
594  }
595 
596  template<typename ValueFilter>
597  friend size_type erase_if(unordered_multimap& cont, const ValueFilter& valueFilter)
598  {
599  auto pairFilter = [&valueFilter] (const key_type& key, const mapped_type& mapped)
600  { return valueFilter(const_reference(key, mapped)); };
601  return cont.mHashMultiMap.Remove(pairFilter);
602  }
603 
604  //iterator insert(node_type&& node)
605  //iterator insert(const_iterator, node_type&& node)
606  //node_type extract(const_iterator where)
607  //node_type extract(const key_type& key)
608  //void merge(...)
609 
610  //size_type max_bucket_count() const noexcept
611  //size_type bucket_count() const noexcept
612  //size_type bucket_size(size_type bucketIndex) const
613  //local_iterator begin(size_type bucketIndex)
614  //const_local_iterator begin(size_type bucketIndex) const
615  //local_iterator end(size_type bucketIndex)
616  //const_local_iterator end(size_type bucketIndex) const
617  //const_local_iterator cbegin(size_type bucketIndex) const
618  //const_local_iterator cend(size_type bucketIndex) const
619  //size_type bucket(const key_type& key) const
620  //float load_factor() const noexcept
621 
622  bool operator==(const unordered_multimap& right) const
623  {
624  if (mHashMultiMap.GetKeyCount() != right.mHashMultiMap.GetKeyCount())
625  return false;
626  if (mHashMultiMap.GetValueCount() != right.mHashMultiMap.GetValueCount())
627  return false;
628  for (typename HashMultiMap::ConstKeyIterator::Reference ref : mHashMultiMap.GetKeyBounds())
629  {
630  if (ref.GetCount() == 0)
631  continue;
632  typename HashMultiMap::ConstKeyIterator rightKeyIter = right.mHashMultiMap.Find(ref.key);
633  if (!rightKeyIter)
634  return false;
635  if (ref.GetCount() != rightKeyIter->GetCount())
636  return false;
637  if (!std::is_permutation(ref.GetBegin(), ref.GetEnd(), rightKeyIter->GetBegin()))
638  return false;
639  }
640  return true;
641  }
642 
643  bool operator!=(const unordered_multimap& right) const
644  {
645  return !(*this == right);
646  }
647 
648 private:
649  static HashMultiMap pvCreateMultiMap(unordered_multimap&& right, const allocator_type& alloc)
650  {
651  if (right.get_allocator() == alloc)
652  return std::move(right.mHashMultiMap);
653  HashMultiMap hashMultiMap(right.mHashMultiMap.GetHashTraits(), MemManager(alloc));
654  for (reference ref : right)
655  hashMultiMap.Add(ref.first, std::move(ref.second));
656  right.clear();
657  return hashMultiMap;
658  }
659 
660  template<typename Iterator, typename IteratorProxy, typename HashMultiMap, typename KeyIterator>
661  static std::pair<Iterator, Iterator> pvEqualRange(HashMultiMap& hashMultiMap,
662  KeyIterator keyIter)
663  {
664  Iterator end = IteratorProxy(hashMultiMap.GetEnd());
665  if (!keyIter)
666  return { end, end };
667  size_t count = keyIter->GetCount();
668  if (count == 0)
669  return { end, end };
670  Iterator first = IteratorProxy(hashMultiMap.MakeIterator(keyIter, 0));
671  Iterator last = IteratorProxy(hashMultiMap.MakeIterator(keyIter, count));
672  return { first, last };
673  }
674 
675  template<typename... KeyArgs, typename... MappedArgs>
676  iterator pvEmplace(std::tuple<KeyArgs...>&& keyArgs, std::tuple<MappedArgs...>&& mappedArgs)
677  {
678  typedef typename HashMultiMap::KeyValueTraits
679  ::template ValueCreator<MappedArgs...> MappedCreator;
680  return pvInsert(std::move(keyArgs),
681  MappedCreator(mHashMultiMap.GetMemManager(), std::move(mappedArgs)));
682  }
683 
684  template<typename... KeyArgs, typename MappedCreator>
685  iterator pvInsert(std::tuple<KeyArgs...>&& keyArgs, MappedCreator&& mappedCreator)
686  {
687  MemManager& memManager = mHashMultiMap.GetMemManager();
690  typedef typename KeyManager::template Creator<KeyArgs...> KeyCreator;
691  KeyBuffer keyBuffer;
692  KeyCreator(memManager, std::move(keyArgs))(&keyBuffer);
693  iterator resIter;
694  try
695  {
696  resIter = pvInsert(std::forward_as_tuple(std::move(*&keyBuffer)),
697  std::forward<MappedCreator>(mappedCreator));
698  }
699  catch (...)
700  {
701  KeyManager::Destroy(memManager, *&keyBuffer);
702  throw;
703  }
704  KeyManager::Destroy(memManager, *&keyBuffer);
705  return resIter;
706  }
707 
708  template<typename RKey, typename MappedCreator,
709  typename Key = typename std::decay<RKey>::type>
711  iterator> pvInsert(std::tuple<RKey>&& key, MappedCreator&& mappedCreator)
712  {
713  return IteratorProxy(mHashMultiMap.AddCrt(
714  std::forward<RKey>(std::get<0>(key)), std::forward<MappedCreator>(mappedCreator)));
715  }
716 
717  template<typename Iterator>
718  void pvInsert(Iterator first, Iterator last, std::true_type /*isMapArgIterator*/)
719  {
720  mHashMultiMap.Add(first, last);
721  }
722 
723  template<typename Iterator>
724  void pvInsert(Iterator first, Iterator last, std::false_type /*isMapArgIterator*/)
725  {
726  for (Iterator iter = first; iter != last; ++iter)
727  insert(*iter);
728  }
729 
730 private:
731  HashMultiMap mHashMultiMap;
732 };
733 
743 template<typename TKey, typename TMapped,
744  typename THashFunc = HashCoder<TKey>,
745  typename TEqualFunc = std::equal_to<TKey>,
746  typename TAllocator = std::allocator<std::pair<const TKey, TMapped>>>
747 class unordered_multimap_open : public unordered_multimap<TKey, TMapped, THashFunc, TEqualFunc, TAllocator,
748  HashMultiMap<TKey, TMapped, HashTraitsStd<TKey, THashFunc, TEqualFunc, HashBucketOpenDefault>,
749  MemManagerStd<TAllocator>>>
750 {
751 private:
752  typedef unordered_multimap<TKey, TMapped, THashFunc, TEqualFunc, TAllocator,
755 
756 public:
757  using typename UnorderedMultiMap::key_type;
758  using typename UnorderedMultiMap::mapped_type;
759  using typename UnorderedMultiMap::size_type;
760  using typename UnorderedMultiMap::value_type;
761  using typename UnorderedMultiMap::const_reference;
762 
763 public:
764  using UnorderedMultiMap::UnorderedMultiMap;
765 
766  unordered_multimap_open() {} // clang 3.6
767 
768  unordered_multimap_open& operator=(std::initializer_list<value_type> values)
769  {
771  return *this;
772  }
773 
774  friend void swap(unordered_multimap_open& left, unordered_multimap_open& right) noexcept
775  {
776  left.swap(right);
777  }
778 
779  template<typename ValueFilter>
780  friend size_type erase_if(unordered_multimap_open& cont, const ValueFilter& valueFilter)
781  {
782  auto pairFilter = [&valueFilter] (const key_type& key, const mapped_type& mapped)
783  { return valueFilter(const_reference(key, mapped)); };
784  return cont.get_nested_container().Remove(pairFilter);
785  }
786 };
787 
788 #ifdef MOMO_HAS_DEDUCTION_GUIDES
789 
790 #define MOMO_DECLARE_DEDUCTION_GUIDES(unordered_multimap) \
791 template<typename Iterator, \
792  typename Key = std::remove_const_t<typename std::iterator_traits<Iterator>::value_type::first_type>, \
793  typename Mapped = typename std::iterator_traits<Iterator>::value_type::second_type> \
794 unordered_multimap(Iterator, Iterator) \
795  -> unordered_multimap<Key, Mapped>; \
796 template<typename Iterator, \
797  typename Key = std::remove_const_t<typename std::iterator_traits<Iterator>::value_type::first_type>, \
798  typename Mapped = typename std::iterator_traits<Iterator>::value_type::second_type, \
799  typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
800  typename = decltype(std::declval<Allocator&>().allocate(size_t{}))> \
801 unordered_multimap(Iterator, Iterator, size_t, Allocator = Allocator()) \
802  -> unordered_multimap<Key, Mapped, HashCoder<Key>, std::equal_to<Key>, Allocator>; \
803 template<typename Iterator, typename HashFunc, \
804  typename Key = std::remove_const_t<typename std::iterator_traits<Iterator>::value_type::first_type>, \
805  typename Mapped = typename std::iterator_traits<Iterator>::value_type::second_type, \
806  typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
807  typename = decltype(std::declval<HashFunc&>()(std::declval<const Key&>())), \
808  typename = decltype(std::declval<Allocator&>().allocate(size_t{}))> \
809 unordered_multimap(Iterator, Iterator, size_t, HashFunc, Allocator = Allocator()) \
810  -> unordered_multimap<Key, Mapped, HashFunc, std::equal_to<Key>, Allocator>; \
811 template<typename Iterator, typename HashFunc, typename EqualFunc, \
812  typename Key = std::remove_const_t<typename std::iterator_traits<Iterator>::value_type::first_type>, \
813  typename Mapped = typename std::iterator_traits<Iterator>::value_type::second_type, \
814  typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
815  typename = decltype(std::declval<HashFunc&>()(std::declval<const Key&>())), \
816  typename = decltype(std::declval<EqualFunc&>()(std::declval<const Key&>(), std::declval<const Key&>()))> \
817 unordered_multimap(Iterator, Iterator, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \
818  -> unordered_multimap<Key, Mapped, HashFunc, EqualFunc, Allocator>; \
819 template<typename Key, typename Mapped> \
820 unordered_multimap(std::initializer_list<std::pair<Key, Mapped>>) \
821  -> unordered_multimap<Key, Mapped>; \
822 template<typename Key, typename Mapped, \
823  typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
824  typename = decltype(std::declval<Allocator&>().allocate(size_t{}))> \
825 unordered_multimap(std::initializer_list<std::pair<Key, Mapped>>, size_t, Allocator = Allocator()) \
826  -> unordered_multimap<Key, Mapped, HashCoder<Key>, std::equal_to<Key>, Allocator>; \
827 template<typename Key, typename Mapped, typename HashFunc, \
828  typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
829  typename = decltype(std::declval<HashFunc&>()(std::declval<const Key&>())), \
830  typename = decltype(std::declval<Allocator&>().allocate(size_t{}))> \
831 unordered_multimap(std::initializer_list<std::pair<Key, Mapped>>, size_t, HashFunc, Allocator = Allocator()) \
832  -> unordered_multimap<Key, Mapped, HashFunc, std::equal_to<Key>, Allocator>; \
833 template<typename Key, typename Mapped, typename HashFunc, typename EqualFunc, \
834  typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
835  typename = decltype(std::declval<HashFunc&>()(std::declval<const Key&>())), \
836  typename = decltype(std::declval<EqualFunc&>()(std::declval<const Key&>(), std::declval<const Key&>()))> \
837 unordered_multimap(std::initializer_list<std::pair<Key, Mapped>>, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \
838  -> unordered_multimap<Key, Mapped, HashFunc, EqualFunc, Allocator>;
839 
840 MOMO_DECLARE_DEDUCTION_GUIDES(unordered_multimap)
841 MOMO_DECLARE_DEDUCTION_GUIDES(unordered_multimap_open)
842 
843 #undef MOMO_DECLARE_DEDUCTION_GUIDES
844 
845 #endif // MOMO_HAS_DEDUCTION_GUIDES
846 
847 } // namespace stdish
848 
849 } // namespace momo
850 
851 #endif // MOMO_INCLUDE_GUARD_STDISH_UNORDERED_MULTIMAP
momo::stdish::unordered_multimap::swap
friend void swap(unordered_multimap &left, unordered_multimap &right) noexcept
Definition: unordered_multimap.h:270
momo::stdish::unordered_multimap::equal_range
MOMO_FORCEINLINE momo::internal::EnableIf< IsValidKeyArg< KeyArg >::value, std::pair< iterator, iterator > > equal_range(const KeyArg &key)
Definition: unordered_multimap.h:427
momo::internal::ObjectManager
Definition: ObjectManager.h:196
momo::HashMultiMap::Iterator
internal::HashMultiMapIterator< KeyIterator, Settings > Iterator
Definition: HashMultiMap.h:674
momo::stdish::unordered_multimap::max_size
size_type max_size() const noexcept
Definition: unordered_multimap.h:333
momo::stdish::unordered_multimap::insert
void insert(std::initializer_list< value_type > values)
Definition: unordered_multimap.h:498
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(const unordered_multimap &right)
Definition: unordered_multimap.h:216
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(unordered_multimap &&right, const momo::internal::Identity< allocator_type > &alloc) noexcept(std::is_empty< allocator_type >::value)
Definition: unordered_multimap.h:209
momo::internal::HashMultiMapIterator
Definition: HashMultiMap.h:182
momo::HashMultiMap::MakeIterator
ConstIterator MakeIterator(ConstKeyIterator keyIter, size_t valueIndex=0) const
Definition: HashMultiMap.h:1126
momo::internal::HashDerivedIterator::Reference
TReference< typename BaseIterator::Reference > Reference
Definition: IteratorUtility.h:396
momo::stdish::unordered_multimap::allocator_type
TAllocator allocator_type
Definition: unordered_multimap.h:75
momo::stdish::unordered_multimap::mapped_type
TMapped mapped_type
Definition: unordered_multimap.h:72
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(std::initializer_list< value_type > values, size_type bucketCount, const hasher &hashFunc, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:191
momo::stdish::unordered_multimap::erase
iterator erase(iterator where)
Definition: unordered_multimap.h:562
momo::stdish::unordered_multimap::swap
void swap(unordered_multimap &right) noexcept
Definition: unordered_multimap.h:263
momo::stdish::unordered_multimap_open::unordered_multimap_open
unordered_multimap_open()
Definition: unordered_multimap.h:766
momo::HashMultiMap::HashTraits
THashTraits HashTraits
Definition: HashMultiMap.h:564
momo::stdish::unordered_multimap::cbegin
const_iterator cbegin() const noexcept
Definition: unordered_multimap.h:305
momo::internal::IsMapArgIteratorStd
Definition: MapUtility.h:1004
momo::stdish::unordered_multimap::get_nested_container
const nested_container_type & get_nested_container() const noexcept
Definition: unordered_multimap.h:275
momo::stdish::unordered_multimap::end
const_iterator end() const noexcept
Definition: unordered_multimap.h:295
momo::stdish::unordered_multimap::count
MOMO_FORCEINLINE momo::internal::EnableIf< IsValidKeyArg< KeyArg >::value, size_type > count(const KeyArg &key) const
Definition: unordered_multimap.h:388
momo::stdish::unordered_multimap::erase
iterator erase(const_iterator where)
Definition: unordered_multimap.h:552
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(std::initializer_list< value_type > values, size_type bucketCount, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:185
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap()
Definition: unordered_multimap.h:122
momo::stdish::unordered_multimap::begin
const_iterator begin() const noexcept
Definition: unordered_multimap.h:285
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(Iterator first, Iterator last, size_type bucketCount, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:156
momo::stdish::unordered_multimap::size_type
size_t size_type
Definition: unordered_multimap.h:79
momo::stdish::unordered_multimap::find
MOMO_FORCEINLINE momo::internal::EnableIf< IsValidKeyArg< KeyArg >::value, iterator > find(const KeyArg &key)
Definition: unordered_multimap.h:375
momo::stdish::unordered_multimap::operator=
unordered_multimap & operator=(std::initializer_list< value_type > values)
Definition: unordered_multimap.h:255
momo::stdish::unordered_multimap
momo::stdish::unordered_multimap is similar to std::unordered_multimap, but much more efficient in me...
Definition: unordered_multimap.h:64
momo::stdish::unordered_multimap::nested_container_type
HashMultiMap nested_container_type
Definition: unordered_multimap.h:77
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(std::initializer_list< value_type > values, size_type bucketCount, const hasher &hashFunc, const key_equal &equalFunc, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:197
momo::stdish::unordered_multimap::insert
momo::internal::EnableIf< std::is_constructible< key_type, First && >::value &&std::is_constructible< mapped_type, Second && >::value, iterator > insert(std::pair< First, Second > &&value)
Definition: unordered_multimap.h:478
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(Iterator first, Iterator last, size_type bucketCount, const hasher &hashFunc, const key_equal &equalFunc, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:172
momo::stdish::unordered_multimap::emplace
iterator emplace(KeyArg &&keyArg, MappedArg &&mappedArg)
Definition: unordered_multimap.h:526
momo::stdish::unordered_multimap::emplace
iterator emplace(std::piecewise_construct_t, std::tuple< KeyArgs... > keyArgs, std::tuple< MappedArgs... > mappedArgs)
Definition: unordered_multimap.h:539
momo::internal::HashMultiMapIterator::GetKeyIterator
KeyIterator GetKeyIterator() const noexcept
Definition: HashMultiMap.h:249
momo::stdish::unordered_multimap::get_nested_container
nested_container_type & get_nested_container() noexcept
Definition: unordered_multimap.h:280
momo::stdish::unordered_multimap::begin
iterator begin() noexcept
Definition: unordered_multimap.h:290
momo::MemManagerStd
MemManagerStd uses allocator<unsigned char>::allocate and deallocate
Definition: MemManager.h:176
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(unordered_multimap &&right) noexcept
Definition: unordered_multimap.h:204
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(std::initializer_list< value_type > values)
Definition: unordered_multimap.h:180
momo::stdish::unordered_multimap::key_equal
TEqualFunc key_equal
Definition: unordered_multimap.h:74
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(Iterator first, Iterator last, size_type bucketCount, const hasher &hashFunc, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:164
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(size_type bucketCount, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:131
momo::stdish::unordered_multimap::emplace
iterator emplace()
Definition: unordered_multimap.h:503
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(Iterator first, Iterator last)
Definition: unordered_multimap.h:150
momo::stdish::unordered_multimap::emplace_hint
iterator emplace_hint(const_iterator, ValueArg &&valueArg)
Definition: unordered_multimap.h:520
momo::stdish::unordered_multimap::cend
const_iterator cend() const noexcept
Definition: unordered_multimap.h:310
momo::stdish::unordered_multimap::end
iterator end() noexcept
Definition: unordered_multimap.h:300
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(size_type bucketCount, const hasher &hashFunc, const key_equal &equalFunc, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:143
momo::stdish::unordered_multimap::erase_if
friend size_type erase_if(unordered_multimap &cont, const ValueFilter &valueFilter)
Definition: unordered_multimap.h:597
momo::stdish::unordered_multimap_open::mapped_type
TMapped mapped_type
Definition: unordered_multimap.h:72
momo::stdish::unordered_multimap_open::key_type
TKey key_type
Definition: unordered_multimap.h:71
momo::stdish::unordered_multimap::operator=
unordered_multimap & operator=(unordered_multimap &&right) noexcept(std::is_empty< allocator_type >::value||std::allocator_traits< allocator_type >::propagate_on_container_move_assignment::value)
Definition: unordered_multimap.h:229
momo::stdish::unordered_multimap::operator=
unordered_multimap & operator=(const unordered_multimap &right)
Definition: unordered_multimap.h:243
momo::stdish::unordered_multimap::equal_range
MOMO_FORCEINLINE std::pair< iterator, iterator > equal_range(const key_type &key)
Definition: unordered_multimap.h:412
momo::stdish::unordered_multimap::erase
size_type erase(const key_type &key)
Definition: unordered_multimap.h:591
momo::internal::EnableIf
typename std::enable_if< value, Type >::type EnableIf
Definition: Utility.h:174
momo::stdish::unordered_multimap::insert
momo::internal::EnableIf< std::is_constructible< key_type, First && >::value &&std::is_constructible< mapped_type, Second && >::value, iterator > insert(const_iterator, std::pair< First, Second > &&value)
Definition: unordered_multimap.h:487
momo::stdish::unordered_multimap::emplace
iterator emplace(ValueArg &&valueArg)
Definition: unordered_multimap.h:514
momo::stdish::unordered_multimap::iterator
momo::internal::HashDerivedIterator< typename HashMultiMap::Iterator, momo::internal::MapReferenceStd > iterator
Definition: unordered_multimap.h:85
momo::stdish::unordered_multimap_open
momo::stdish::unordered_multimap_open is similar to std::unordered_multimap, but much more efficient ...
Definition: unordered_multimap.h:750
momo::stdish::unordered_multimap::get_allocator
allocator_type get_allocator() const noexcept
Definition: unordered_multimap.h:328
momo
Definition: Array.h:26
momo::stdish::unordered_multimap_open::swap
friend void swap(unordered_multimap_open &left, unordered_multimap_open &right) noexcept
Definition: unordered_multimap.h:774
momo::stdish::unordered_multimap::find
MOMO_FORCEINLINE const_iterator find(const key_type &key) const
Definition: unordered_multimap.h:356
momo::internal::IteratorPointer
Definition: IteratorUtility.h:279
momo::stdish::unordered_multimap::hasher
THashFunc hasher
Definition: unordered_multimap.h:73
momo::stdish::unordered_multimap::erase
iterator erase(const_iterator first, const_iterator last)
Definition: unordered_multimap.h:567
momo::internal::Identity
EnableIf< true, Type > Identity
Definition: Utility.h:177
momo::stdish::unordered_multimap::const_pointer
const_iterator::Pointer const_pointer
Definition: unordered_multimap.h:92
momo::internal::HashDerivedIterator::BaseIterator
TBaseIterator BaseIterator
Definition: IteratorUtility.h:393
momo::stdish::unordered_multimap_open::erase_if
friend size_type erase_if(unordered_multimap_open &cont, const ValueFilter &valueFilter)
Definition: unordered_multimap.h:780
momo::stdish::unordered_multimap_open::size_type
size_t size_type
Definition: unordered_multimap.h:79
momo::stdish::unordered_multimap::find
MOMO_FORCEINLINE momo::internal::EnableIf< IsValidKeyArg< KeyArg >::value, const_iterator > find(const KeyArg &key) const
Definition: unordered_multimap.h:368
momo::stdish::unordered_multimap::operator!=
bool operator!=(const unordered_multimap &right) const
Definition: unordered_multimap.h:643
momo::stdish::unordered_multimap::insert
iterator insert(const_iterator, std::pair< key_type, mapped_type > &&value)
Definition: unordered_multimap.h:454
MOMO_DECLARE_PROXY_CONSTRUCTOR
#define MOMO_DECLARE_PROXY_CONSTRUCTOR(Object)
Definition: Utility.h:85
momo::stdish::unordered_multimap::emplace_hint
iterator emplace_hint(const_iterator, KeyArg &&keyArg, MappedArg &&mappedArg)
Definition: unordered_multimap.h:533
momo::stdish::unordered_multimap::empty
MOMO_NODISCARD bool empty() const noexcept
Definition: unordered_multimap.h:343
momo::stdish::unordered_multimap::insert
momo::internal::EnableIf< std::is_constructible< key_type, const First & >::value &&std::is_constructible< mapped_type, const Second & >::value, iterator > insert(const std::pair< First, Second > &value)
Definition: unordered_multimap.h:462
momo::stdish::unordered_multimap::key_eq
key_equal key_eq() const
Definition: unordered_multimap.h:323
momo::internal::HashDerivedIterator
Definition: IteratorUtility.h:391
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(const unordered_multimap &right, const momo::internal::Identity< allocator_type > &alloc)
Definition: unordered_multimap.h:221
momo::stdish::unordered_multimap::difference_type
ptrdiff_t difference_type
Definition: unordered_multimap.h:80
momo::internal::ObjectBuffer
Definition: ObjectManager.h:161
std
Definition: ArrayUtility.h:299
MOMO_FORCEINLINE
#define MOMO_FORCEINLINE
Definition: UserSettings.h:114
momo::stdish::unordered_multimap::reference
iterator::Reference reference
Definition: unordered_multimap.h:88
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(size_type bucketCount, const hasher &hashFunc, const allocator_type &alloc=allocator_type())
Definition: unordered_multimap.h:137
momo::stdish::unordered_multimap::clear
void clear() noexcept
Definition: unordered_multimap.h:348
momo::stdish::unordered_multimap::find
MOMO_FORCEINLINE iterator find(const key_type &key)
Definition: unordered_multimap.h:361
momo::HashMultiMap::GetEnd
ConstIterator GetEnd() const noexcept
Definition: HashMultiMap.h:828
momo::stdish::unordered_multimap::hash_function
hasher hash_function() const
Definition: unordered_multimap.h:318
momo::HashMultiMap
Definition: HashMultiMap.h:560
momo::HashMultiMap::MemManager
TMemManager MemManager
Definition: HashMultiMap.h:565
momo::stdish::unordered_multimap::equal_range
MOMO_FORCEINLINE std::pair< const_iterator, const_iterator > equal_range(const key_type &key) const
Definition: unordered_multimap.h:406
momo::stdish::unordered_multimap::unordered_multimap
unordered_multimap(const allocator_type &alloc)
Definition: unordered_multimap.h:126
momo::stdish::unordered_multimap::equal_range
MOMO_FORCEINLINE momo::internal::EnableIf< IsValidKeyArg< KeyArg >::value, std::pair< const_iterator, const_iterator > > equal_range(const KeyArg &key) const
Definition: unordered_multimap.h:419
momo::stdish::unordered_multimap::const_iterator
iterator::ConstIterator const_iterator
Definition: unordered_multimap.h:86
momo::stdish::unordered_multimap::key_type
TKey key_type
Definition: unordered_multimap.h:71
momo::stdish::unordered_multimap::size
size_type size() const noexcept
Definition: unordered_multimap.h:338
momo::stdish::unordered_multimap::insert
momo::internal::EnableIf< std::is_constructible< key_type, const First & >::value &&std::is_constructible< mapped_type, const Second & >::value, iterator > insert(const_iterator, const std::pair< First, Second > &value)
Definition: unordered_multimap.h:470
momo::stdish::unordered_multimap::count
MOMO_FORCEINLINE size_type count(const key_type &key) const
Definition: unordered_multimap.h:380
momo::stdish::unordered_multimap_open::const_reference
const_iterator::Reference const_reference
Definition: unordered_multimap.h:89
momo::stdish::unordered_multimap::const_reference
const_iterator::Reference const_reference
Definition: unordered_multimap.h:89
momo::stdish::unordered_multimap::value_type
std::pair< const key_type, mapped_type > value_type
Definition: unordered_multimap.h:82
momo::stdish::unordered_multimap::contains
MOMO_FORCEINLINE momo::internal::EnableIf< IsValidKeyArg< KeyArg >::value, bool > contains(const KeyArg &key) const
Definition: unordered_multimap.h:401
momo::stdish::unordered_multimap::pointer
iterator::Pointer pointer
Definition: unordered_multimap.h:91
momo::stdish::unordered_multimap::insert
void insert(Iterator first, Iterator last)
Definition: unordered_multimap.h:493
momo::stdish::unordered_multimap_open::operator=
unordered_multimap_open & operator=(std::initializer_list< value_type > values)
Definition: unordered_multimap.h:768
momo::stdish::unordered_multimap::contains
MOMO_FORCEINLINE bool contains(const key_type &key) const
Definition: unordered_multimap.h:394
MOMO_ASSERT
#define MOMO_ASSERT(expr)
Definition: UserSettings.h:162
momo::stdish::unordered_multimap::~unordered_multimap
~unordered_multimap()=default
momo::stdish::unordered_multimap::emplace_hint
iterator emplace_hint(const_iterator)
Definition: unordered_multimap.h:508
MOMO_DECLARE_PROXY_FUNCTION
#define MOMO_DECLARE_PROXY_FUNCTION(Object, Func, Result)
Definition: Utility.h:94
momo::stdish::unordered_multimap::insert
iterator insert(std::pair< key_type, mapped_type > &&value)
Definition: unordered_multimap.h:448
momo::stdish::unordered_multimap::operator==
bool operator==(const unordered_multimap &right) const
Definition: unordered_multimap.h:622
MOMO_NODISCARD
#define MOMO_NODISCARD
Definition: UserSettings.h:192
momo::stdish::unordered_multimap::emplace_hint
iterator emplace_hint(const_iterator, std::piecewise_construct_t, std::tuple< KeyArgs... > keyArgs, std::tuple< MappedArgs... > mappedArgs)
Definition: unordered_multimap.h:546
momo::internal::MapReferenceStd
Definition: MapUtility.h:68