17 #ifndef MOMO_INCLUDE_GUARD_STDISH_UNORDERED_MAP
18 #define MOMO_INCLUDE_GUARD_STDISH_UNORDERED_MAP
20 #include "../HashMap.h"
55 template<
typename TKey,
typename TMapped,
56 typename THashFunc = HashCoder<TKey>,
57 typename TEqualFunc = std::equal_to<TKey>,
58 typename TAllocator = std::allocator<std::pair<const TKey, TMapped>>,
59 typename THashMap = HashMap<TKey, TMapped, HashTraitsStd<TKey, THashFunc, TEqualFunc>,
60 MemManagerStd<TAllocator>>>
64 typedef THashMap HashMap;
82 typedef std::pair<const key_type, mapped_type>
value_type;
104 template<
typename KeyArg>
105 struct IsValidKeyArg :
public HashTraits::template IsValidKeyArg<KeyArg>
117 struct IteratorProxy :
public iterator
149 : mHashMap(HashTraits(), MemManager(alloc))
154 : mHashMap(HashTraits(bucketCount), MemManager(alloc))
160 : mHashMap(HashTraits(bucketCount, hashFunc), MemManager(alloc))
166 : mHashMap(HashTraits(bucketCount, hashFunc, equalFunc), MemManager(alloc))
170 template<
typename Iterator>
176 template<
typename Iterator>
184 template<
typename Iterator>
192 template<
typename Iterator>
224 #ifdef MOMO_HAS_CONTAINERS_RANGES
225 template<std::ranges::input_range Range>
226 requires std::convertible_to<std::ranges::range_reference_t<Range>,
value_type>
229 insert_range(std::forward<Range>(values));
232 template<std::ranges::input_range Range>
233 requires std::convertible_to<std::ranges::range_reference_t<Range>,
value_type>
238 insert_range(std::forward<Range>(values));
241 template<std::ranges::input_range Range>
242 requires std::convertible_to<std::ranges::range_reference_t<Range>,
value_type>
247 insert_range(std::forward<Range>(values));
250 template<std::ranges::input_range Range>
251 requires std::convertible_to<std::ranges::range_reference_t<Range>,
value_type>
256 insert_range(std::forward<Range>(values));
258 #endif // MOMO_HAS_CONTAINERS_RANGES
261 : mHashMap(std::move(right.mHashMap))
266 noexcept(std::is_empty<allocator_type>::value)
267 : mHashMap(pvCreateMap(
std::move(right), alloc))
272 : mHashMap(right.mHashMap)
277 : mHashMap(right.mHashMap, MemManager(alloc))
284 noexcept(std::is_empty<allocator_type>::value ||
285 std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
289 bool propagate = std::is_empty<allocator_type>::value ||
290 std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value;
292 mHashMap = pvCreateMap(std::move(right), alloc);
301 bool propagate = std::is_empty<allocator_type>::value ||
302 std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value;
304 mHashMap = HashMap(right.mHashMap, MemManager(alloc));
311 HashMap hashMap(mHashMap.GetHashTraits(), MemManager(
get_allocator()));
312 hashMap.Insert(values.begin(), values.end());
313 mHashMap = std::move(hashMap);
319 MOMO_ASSERT(std::allocator_traits<allocator_type>::propagate_on_container_swap::value
321 mHashMap.Swap(right.mHashMap);
341 return ConstIteratorProxy(mHashMap.GetBegin());
346 return IteratorProxy(mHashMap.GetBegin());
351 return ConstIteratorProxy(mHashMap.GetEnd());
356 return IteratorProxy(mHashMap.GetEnd());
379 throw std::out_of_range(
"invalid load factor");
380 HashTraits hashTraits(mHashMap.GetHashTraits(), maxLoadFactor);
382 hashMap.Reserve(
size());
384 mHashMap = std::move(hashMap);
389 return mHashMap.GetHashTraits().GetHashFunc();
394 return mHashMap.GetHashTraits().GetEqualFunc();
399 return allocator_type(mHashMap.GetMemManager().GetByteAllocator());
404 return std::allocator_traits<allocator_type>::max_size(
get_allocator());
409 return mHashMap.GetCount();
414 return mHashMap.IsEmpty();
424 bucketCount = std::minmax(bucketCount,
size_t{2}).second;
426 bucketCount =
size_t{1} << logBucketCount;
432 mHashMap.Reserve(
count);
437 return ConstIteratorProxy(mHashMap.Find(key));
442 return IteratorProxy(mHashMap.Find(key));
445 template<
typename KeyArg>
449 return ConstIteratorProxy(mHashMap.Find(key));
452 template<
typename KeyArg>
456 return IteratorProxy(mHashMap.Find(key));
464 template<
typename KeyArg>
473 return mHashMap.ContainsKey(key);
476 template<
typename KeyArg>
480 return mHashMap.ContainsKey(key);
493 template<
typename KeyArg>
495 std::pair<const_iterator, const_iterator>>
equal_range(
const KeyArg& key)
const
500 template<
typename KeyArg>
507 template<
typename ValueArg = std::pair<key_type, mapped_type>>
509 std::pair<iterator, bool>>
insert(ValueArg&& valueArg)
511 return emplace(std::forward<ValueArg>(valueArg));
514 template<
typename ValueArg = std::pair<key_type, mapped_type>>
518 return emplace_hint(hint, std::forward<ValueArg>(valueArg));
526 std::move(NodeTypeProxy::GetExtractedPair(node)));
533 #ifdef MOMO_USE_UNORDERED_HINT_ITERATORS
536 return IteratorProxy(mHashMap.Add(ConstIteratorProxy::GetBaseIterator(hint),
537 std::move(NodeTypeProxy::GetExtractedPair(node))));
540 return insert(std::move(node)).position;
544 template<
typename Iterator>
545 void insert(Iterator first, Iterator last)
547 pvInsertRange(first, last);
550 void insert(std::initializer_list<value_type> values)
552 mHashMap.Insert(values.begin(), values.end());
555 #ifdef MOMO_HAS_CONTAINERS_RANGES
556 template<std::ranges::input_range Range>
557 requires std::convertible_to<std::ranges::range_reference_t<Range>,
value_type>
558 void insert_range(Range&& values)
560 pvInsertRange(std::ranges::begin(values), std::ranges::end(values));
562 #endif // MOMO_HAS_CONTAINERS_RANGES
566 return pvEmplace(
nullptr, std::tuple<>(), std::tuple<>());
571 return pvEmplace(hint, std::tuple<>(), std::tuple<>()).first;
574 template<
typename ValueArg>
575 std::pair<iterator, bool>
emplace(ValueArg&& valueArg)
577 return pvEmplace(
nullptr,
578 std::forward_as_tuple(std::get<0>(std::forward<ValueArg>(valueArg))),
579 std::forward_as_tuple(std::get<1>(std::forward<ValueArg>(valueArg))));
582 template<
typename ValueArg>
585 return pvEmplace(hint,
586 std::forward_as_tuple(std::get<0>(std::forward<ValueArg>(valueArg))),
587 std::forward_as_tuple(std::get<1>(std::forward<ValueArg>(valueArg)))).first;
590 template<
typename KeyArg,
typename MappedArg>
591 std::pair<iterator, bool>
emplace(KeyArg&& keyArg, MappedArg&& mappedArg)
593 return pvEmplace(
nullptr, std::forward_as_tuple(std::forward<KeyArg>(keyArg)),
594 std::forward_as_tuple(std::forward<MappedArg>(mappedArg)));
597 template<
typename KeyArg,
typename MappedArg>
600 return pvEmplace(hint, std::forward_as_tuple(std::forward<KeyArg>(keyArg)),
601 std::forward_as_tuple(std::forward<MappedArg>(mappedArg))).first;
604 template<
typename... KeyArgs,
typename... MappedArgs>
605 std::pair<iterator, bool>
emplace(std::piecewise_construct_t,
606 std::tuple<KeyArgs...> keyArgs, std::tuple<MappedArgs...> mappedArgs)
608 return pvEmplace(
nullptr, std::move(keyArgs), std::move(mappedArgs));
611 template<
typename... KeyArgs,
typename... MappedArgs>
613 std::tuple<KeyArgs...> keyArgs, std::tuple<MappedArgs...> mappedArgs)
615 return pvEmplace(hint, std::move(keyArgs), std::move(mappedArgs)).first;
620 return IteratorProxy(mHashMap.Remove(ConstIteratorProxy::GetBaseIterator(where)));
630 if (first ==
begin() && last ==
end())
637 return IteratorProxy(mHashMap.MakeMutableIterator(
638 ConstIteratorProxy::GetBaseIterator(first)));
640 if (first !=
end() && std::next(first) == last)
642 throw std::invalid_argument(
"invalid unordered_map erase arguments");
647 return mHashMap.Remove(key) ? 1 : 0;
650 template<
typename ValueFilter>
655 return cont.mHashMap.Remove(pairFilter);
660 return mHashMap[std::move(key)];
665 return mHashMap[key];
672 throw std::out_of_range(
"invalid unordered_map key");
680 throw std::out_of_range(
"invalid unordered_map key");
684 template<
typename... MappedArgs>
687 return pvEmplace(
nullptr, std::forward_as_tuple(std::move(key)),
688 std::forward_as_tuple(std::forward<MappedArgs>(mappedArgs)...));
691 template<
typename... MappedArgs>
694 return pvEmplace(hint, std::forward_as_tuple(std::move(key)),
695 std::forward_as_tuple(std::forward<MappedArgs>(mappedArgs)...)).first;
698 template<
typename... MappedArgs>
701 return pvEmplace(
nullptr, std::forward_as_tuple(key),
702 std::forward_as_tuple(std::forward<MappedArgs>(mappedArgs)...));
705 template<
typename... MappedArgs>
708 return pvEmplace(hint, std::forward_as_tuple(key),
709 std::forward_as_tuple(std::forward<MappedArgs>(mappedArgs)...)).first;
712 template<
typename MappedArg>
715 return pvInsertOrAssign(
nullptr, std::move(key), std::forward<MappedArg>(mappedArg));
718 template<
typename MappedArg>
721 return pvInsertOrAssign(hint, std::move(key), std::forward<MappedArg>(mappedArg)).first;
724 template<
typename MappedArg>
727 return pvInsertOrAssign(
nullptr, key, std::forward<MappedArg>(mappedArg));
730 template<
typename MappedArg>
733 return pvInsertOrAssign(hint, key, std::forward<MappedArg>(mappedArg)).first;
747 template<
typename Map>
750 mHashMap.MergeFrom(
map.get_nested_container());
761 return mHashMap.GetBucketCount();
766 return mHashMap.GetBucketBounds(bucketIndex).GetCount();
771 return LocalIteratorProxy(mHashMap.GetBucketBounds(bucketIndex).GetBegin());
776 return ConstLocalIteratorProxy(mHashMap.GetBucketBounds(bucketIndex).GetBegin());
781 return LocalIteratorProxy(mHashMap.GetBucketBounds(bucketIndex).GetEnd());
786 return ConstLocalIteratorProxy(mHashMap.GetBucketBounds(bucketIndex).GetEnd());
791 return begin(bucketIndex);
796 return end(bucketIndex);
801 return mHashMap.GetBucketIndex(key);
808 if (
count == 0 && bucketCount == 0)
810 return static_cast<float>(
count) /
static_cast<float>(bucketCount);
820 if (iter == right.
end())
822 if (!(iter->second == ref.second))
830 return !(left == right);
836 if (right.get_allocator() == alloc)
837 return std::move(right.mHashMap);
838 HashMap hashMap(right.mHashMap.GetHashTraits(), MemManager(alloc));
839 hashMap.MergeFrom(right.mHashMap);
843 template<
typename Hint,
typename... KeyArgs,
typename... MappedArgs>
844 std::pair<iterator, bool> pvEmplace(Hint hint, std::tuple<KeyArgs...>&& keyArgs,
845 std::tuple<MappedArgs...>&& mappedArgs)
847 typedef typename HashMap::KeyValueTraits
848 ::template ValueCreator<MappedArgs...> MappedCreator;
849 return pvInsert(hint, std::move(keyArgs),
850 MappedCreator(mHashMap.GetMemManager(), std::move(mappedArgs)));
853 template<
typename Hint,
typename... KeyArgs,
typename MappedCreator>
854 std::pair<iterator, bool> pvInsert(Hint , std::tuple<KeyArgs...>&& keyArgs,
855 MappedCreator&& mappedCreator)
857 MemManager& memManager = mHashMap.GetMemManager();
860 typedef typename KeyManager::template Creator<KeyArgs...> KeyCreator;
862 KeyCreator(memManager, std::move(keyArgs))(keyBuffer.GetPtr());
863 key_type* keyPtr = keyBuffer.template GetPtr<true>();
869 KeyManager::Destroy(memManager, *keyPtr);
871 return { IteratorProxy(pos),
false };
873 auto valueCreator = [&memManager, &keyPtr, &mappedCreator]
876 KeyManager::Relocate(memManager, *keyPtr, newKey);
880 std::forward<MappedCreator>(mappedCreator)(newMapped);
884 KeyManager::Destroy(memManager, *newKey);
889 return { IteratorProxy(resPos),
true };
893 if (keyPtr !=
nullptr)
894 KeyManager::Destroy(memManager, *keyPtr);
899 template<
typename Hint,
typename RKey,
typename MappedCreator,
900 typename Key =
typename std::decay<RKey>::type>
902 std::pair<iterator, bool>> pvInsert(Hint , std::tuple<RKey>&& key,
903 MappedCreator&& mappedCreator)
906 std::forward<RKey>(std::get<0>(key)), std::forward<MappedCreator>(mappedCreator));
907 return { IteratorProxy(res.position), res.inserted };
910 #ifdef MOMO_USE_UNORDERED_HINT_ITERATORS
911 template<
typename... KeyArgs,
typename MappedCreator>
912 std::pair<iterator, bool> pvInsert(
const_iterator hint, std::tuple<KeyArgs...>&& keyArgs,
913 MappedCreator&& mappedCreator)
915 MemManager& memManager = mHashMap.GetMemManager();
917 typedef typename KeyManager::template Creator<KeyArgs...> KeyCreator;
918 auto valueCreator = [&memManager, &keyArgs, &mappedCreator]
921 KeyCreator(memManager, std::move(keyArgs))(newKey);
924 std::forward<MappedCreator>(mappedCreator)(newMapped);
928 KeyManager::Destroy(memManager, *newKey);
933 ConstIteratorProxy::GetBaseIterator(hint), valueCreator);
934 return { IteratorProxy(resPos),
true };
937 template<
typename RKey,
typename MappedCreator,
938 typename Key =
typename std::decay<RKey>::type>
940 std::pair<iterator, bool>> pvInsert(
const_iterator hint, std::tuple<RKey>&& key,
941 MappedCreator&& mappedCreator)
943 typename HashMap::Position resPos = mHashMap.AddCrt(ConstIteratorProxy::GetBaseIterator(hint),
944 std::forward<RKey>(std::get<0>(key)), std::forward<MappedCreator>(mappedCreator));
945 return { IteratorProxy(resPos),
true };
947 #endif // MOMO_USE_UNORDERED_HINT_ITERATORS
949 template<
typename Iterator,
typename Sentinel>
951 void> pvInsertRange(Iterator
begin, Sentinel
end)
953 mHashMap.Insert(std::move(
begin), std::move(
end));
956 template<
typename Iterator,
typename Sentinel>
958 void> pvInsertRange(Iterator
begin, Sentinel
end)
960 for (Iterator iter = std::move(
begin); iter !=
end; ++iter)
964 template<
typename H
int,
typename RKey,
typename MappedArg>
965 std::pair<iterator, bool> pvInsertOrAssign(Hint hint, RKey&& key, MappedArg&& mappedArg)
967 std::pair<iterator, bool> res = pvEmplace(hint,
968 std::forward_as_tuple(std::forward<RKey>(key)),
969 std::forward_as_tuple(std::forward<MappedArg>(mappedArg)));
971 res.first->second = std::forward<MappedArg>(mappedArg);
988 template<
typename TKey,
typename TMapped,
989 typename THashFunc = HashCoder<TKey>,
990 typename TEqualFunc = std::equal_to<TKey>,
991 typename TAllocator = std::allocator<std::pair<const TKey, TMapped>>>
993 HashMap<TKey, TMapped, HashTraitsStd<TKey, THashFunc, TEqualFunc, HashBucketOpenDefault>,
994 MemManagerStd<TAllocator>>>
997 typedef unordered_map<TKey, TMapped, THashFunc, TEqualFunc, TAllocator,
1009 using UnorderedMap::UnorderedMap;
1024 template<
typename ValueFilter>
1029 return cont.get_nested_container().Remove(pairFilter);
1033 #ifdef MOMO_HAS_DEDUCTION_GUIDES
1035 #define MOMO_DECLARE_DEDUCTION_GUIDES(unordered_map) \
1036 template<typename Iterator, \
1037 typename Value = typename std::iterator_traits<Iterator>::value_type, \
1038 typename Key = std::decay_t<typename Value::first_type>, \
1039 typename Mapped = std::decay_t<typename Value::second_type>> \
1040 unordered_map(Iterator, Iterator) \
1041 -> unordered_map<Key, Mapped>; \
1042 template<typename Iterator, \
1043 typename Value = typename std::iterator_traits<Iterator>::value_type, \
1044 typename Key = std::decay_t<typename Value::first_type>, \
1045 typename Mapped = std::decay_t<typename Value::second_type>, \
1046 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1047 typename = internal::unordered_checker<Key, Allocator, HashCoder<Key>>> \
1048 unordered_map(Iterator, Iterator, size_t, Allocator = Allocator()) \
1049 -> unordered_map<Key, Mapped, HashCoder<Key>, std::equal_to<Key>, Allocator>; \
1050 template<typename Iterator, typename HashFunc, \
1051 typename Value = typename std::iterator_traits<Iterator>::value_type, \
1052 typename Key = std::decay_t<typename Value::first_type>, \
1053 typename Mapped = std::decay_t<typename Value::second_type>, \
1054 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1055 typename = internal::unordered_checker<Key, Allocator, HashFunc>> \
1056 unordered_map(Iterator, Iterator, size_t, HashFunc, Allocator = Allocator()) \
1057 -> unordered_map<Key, Mapped, HashFunc, std::equal_to<Key>, Allocator>; \
1058 template<typename Iterator, typename HashFunc, typename EqualFunc, \
1059 typename Value = typename std::iterator_traits<Iterator>::value_type, \
1060 typename Key = std::decay_t<typename Value::first_type>, \
1061 typename Mapped = std::decay_t<typename Value::second_type>, \
1062 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1063 typename = internal::unordered_checker<Key, Allocator, HashFunc, EqualFunc>> \
1064 unordered_map(Iterator, Iterator, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \
1065 -> unordered_map<Key, Mapped, HashFunc, EqualFunc, Allocator>; \
1066 template<typename CKey, typename Mapped, \
1067 typename Key = std::remove_const_t<CKey>> \
1068 unordered_map(std::initializer_list<std::pair<CKey, Mapped>>) \
1069 -> unordered_map<Key, Mapped>; \
1070 template<typename CKey, typename Mapped, \
1071 typename Key = std::remove_const_t<CKey>, \
1072 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1073 typename = internal::unordered_checker<Key, Allocator, HashCoder<Key>>> \
1074 unordered_map(std::initializer_list<std::pair<CKey, Mapped>>, size_t, Allocator = Allocator()) \
1075 -> unordered_map<Key, Mapped, HashCoder<Key>, std::equal_to<Key>, Allocator>; \
1076 template<typename CKey, typename Mapped, typename HashFunc, \
1077 typename Key = std::remove_const_t<CKey>, \
1078 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1079 typename = internal::unordered_checker<Key, Allocator, HashFunc>> \
1080 unordered_map(std::initializer_list<std::pair<CKey, Mapped>>, size_t, HashFunc, Allocator = Allocator()) \
1081 -> unordered_map<Key, Mapped, HashFunc, std::equal_to<Key>, Allocator>; \
1082 template<typename CKey, typename Mapped, typename HashFunc, typename EqualFunc, \
1083 typename Key = std::remove_const_t<CKey>, \
1084 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1085 typename = internal::unordered_checker<Key, Allocator, HashFunc, EqualFunc>> \
1086 unordered_map(std::initializer_list<std::pair<CKey, Mapped>>, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \
1087 -> unordered_map<Key, Mapped, HashFunc, EqualFunc, Allocator>;
1089 MOMO_DECLARE_DEDUCTION_GUIDES(unordered_map)
1090 MOMO_DECLARE_DEDUCTION_GUIDES(unordered_map_open)
1092 #undef MOMO_DECLARE_DEDUCTION_GUIDES
1094 #ifdef MOMO_HAS_CONTAINERS_RANGES
1096 #define MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_map) \
1097 template<std::ranges::input_range Range, \
1098 typename Value = std::ranges::range_value_t<Range>, \
1099 typename Key = std::decay_t<typename Value::first_type>, \
1100 typename Mapped = std::decay_t<typename Value::second_type>> \
1101 unordered_map(std::from_range_t, Range&&) \
1102 -> unordered_map<Key, Mapped>; \
1103 template<std::ranges::input_range Range, \
1104 typename Value = std::ranges::range_value_t<Range>, \
1105 typename Key = std::decay_t<typename Value::first_type>, \
1106 typename Mapped = std::decay_t<typename Value::second_type>, \
1107 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1108 typename = internal::unordered_checker<Key, Allocator, HashCoder<Key>>> \
1109 unordered_map(std::from_range_t, Range&&, size_t, Allocator = Allocator()) \
1110 -> unordered_map<Key, Mapped, HashCoder<Key>, std::equal_to<Key>, Allocator>; \
1111 template<std::ranges::input_range Range, typename HashFunc, \
1112 typename Value = std::ranges::range_value_t<Range>, \
1113 typename Key = std::decay_t<typename Value::first_type>, \
1114 typename Mapped = std::decay_t<typename Value::second_type>, \
1115 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1116 typename = internal::unordered_checker<Key, Allocator, HashFunc>> \
1117 unordered_map(std::from_range_t, Range&&, size_t, HashFunc, Allocator = Allocator()) \
1118 -> unordered_map<Key, Mapped, HashFunc, std::equal_to<Key>, Allocator>; \
1119 template<std::ranges::input_range Range, typename HashFunc, typename EqualFunc, \
1120 typename Value = std::ranges::range_value_t<Range>, \
1121 typename Key = std::decay_t<typename Value::first_type>, \
1122 typename Mapped = std::decay_t<typename Value::second_type>, \
1123 typename Allocator = std::allocator<std::pair<const Key, Mapped>>, \
1124 typename = internal::unordered_checker<Key, Allocator, HashFunc, EqualFunc>> \
1125 unordered_map(std::from_range_t, Range&&, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \
1126 -> unordered_map<Key, Mapped, HashFunc, EqualFunc, Allocator>;
1128 MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_map)
1129 MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_map_open)
1131 #undef MOMO_DECLARE_DEDUCTION_GUIDES_RANGES
1133 #endif // MOMO_HAS_CONTAINERS_RANGES
1135 #endif // MOMO_HAS_DEDUCTION_GUIDES
1141 #endif // MOMO_INCLUDE_GUARD_STDISH_UNORDERED_MAP