// hash_map extension header // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #pragma once #ifndef _HASH_MAP_ #define _HASH_MAP_ #include #if _STL_COMPILER_PREPROCESSOR #include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new #ifndef _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS #error is deprecated and will be REMOVED. Please use . You can define \ _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS to acknowledge that you have received this warning. #endif // _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS namespace stdext { using _STD allocator; using _STD enable_if_t; using _STD is_constructible_v; using _STD pair; using _STD swap; using _STD _Hash; using _STD _Is_nothrow_swappable; using _STD _Swap_adl; using _STD _Xout_of_range; // CLASS TEMPLATE _Hmap_traits template // true if multiple equivalent keys are permitted class _Hmap_traits : public _Tr { // traits required to make _Hash behave like a map public: using key_type = _Kty; using value_type = pair; using _Mutable_value_type = pair<_Kty, _Ty>; using key_compare = _Tr; using allocator_type = _Alloc; #if _HAS_CXX17 using node_type = _STD _Node_handle<_STD _List_node::void_pointer>, _Alloc, _STD _Node_handle_map_base, _Kty, _Ty>; #endif // _HAS_CXX17 static constexpr bool _Multi = _Mfl; static constexpr bool _Standard = false; template using _In_place_key_extractor = _STD _In_place_key_extract_map<_Kty, _Args...>; template using _Deduce_key = const _Kty&; using key_equal = _Tr; _Hmap_traits() = default; _Hmap_traits(const _Tr& _Traits) noexcept(_STD is_nothrow_copy_constructible_v<_Tr>) : _Tr(_Traits) {} class value_compare { public: using first_argument_type = value_type; using second_argument_type = value_type; using result_type = bool; _NODISCARD bool operator()(const value_type& _Left, const value_type& _Right) const noexcept(noexcept(_Keycompobj(_Left.first, _Right.first))) { // test if _Left precedes _Right by comparing just keys return _Keycompobj(_Left.first, _Right.first); } value_compare(const key_compare& _Keycomparg) noexcept(_STD is_nothrow_copy_constructible_v) : _Keycompobj(_Keycomparg) {} key_compare _Keycompobj; }; template static const _Kty& _Kfn(const pair<_Ty1, _Ty2>& _Val) noexcept { // extract key from element value return _Val.first; } template static const _Ty2& _Nonkfn(const pair<_Ty1, _Ty2>& _Val) noexcept { // extract non-key from element value return _Val.second; } float& _Get_max_bucket_size() noexcept { return _Max_buckets; } const float& _Get_max_bucket_size() const noexcept { return _Max_buckets; } void swap(_Hmap_traits& _Rhs) noexcept(_Is_nothrow_swappable<_Tr>::value) { _Swap_adl(static_cast<_Tr&>(*this), static_cast<_Tr&>(_Rhs)); _STD swap(_Max_buckets, _Rhs._Max_buckets); } float _Max_buckets = 0.0F; // current maximum bucket size }; // CLASS TEMPLATE hash_map template >, class _Alloc = allocator>> class hash_map : public _Hash<_Hmap_traits<_Kty, _Ty, _Tr, _Alloc, false>> { // hash table of {key, mapped} values, unique keys public: using _Mybase = _Hash<_Hmap_traits<_Kty, _Ty, _Tr, _Alloc, false>>; using key_type = _Kty; using mapped_type = _Ty; using referent_type = _Ty; using key_compare = _Tr; using value_compare = typename _Mybase::_Value_compare; using value_type = pair; using allocator_type = typename _Mybase::allocator_type; using size_type = typename _Mybase::size_type; using difference_type = typename _Mybase::difference_type; using pointer = typename _Mybase::pointer; using const_pointer = typename _Mybase::const_pointer; using reference = value_type&; using const_reference = const value_type&; using iterator = typename _Mybase::iterator; using const_iterator = typename _Mybase::const_iterator; using _Alnode = typename _Mybase::_Alnode; using _Alnode_traits = typename _Mybase::_Alnode_traits; #if _HAS_CXX17 using insert_return_type = _STD _Insert_return_type; #endif // _HAS_CXX17 hash_map() : _Mybase(key_compare(), allocator_type()) {} explicit hash_map(const allocator_type& _Al) : _Mybase(key_compare(), _Al) {} hash_map(const hash_map& _Right) : _Mybase(_Right, _Alnode_traits::select_on_container_copy_construction(_Right._Getal())) {} hash_map(const hash_map& _Right, const allocator_type& _Al) : _Mybase(_Right, _Al) {} explicit hash_map(const key_compare& _Traits) : _Mybase(_Traits, allocator_type()) {} hash_map(const key_compare& _Traits, const allocator_type& _Al) : _Mybase(_Traits, _Al) {} template hash_map(_Iter _First, _Iter _Last) : _Mybase(key_compare(), allocator_type()) { insert(_First, _Last); } template hash_map(_Iter _First, _Iter _Last, const key_compare& _Traits) : _Mybase(_Traits, allocator_type()) { insert(_First, _Last); } template hash_map(_Iter _First, _Iter _Last, const key_compare& _Traits, const allocator_type& _Al) : _Mybase(_Traits, _Al) { insert(_First, _Last); } hash_map& operator=(const hash_map& _Right) { _Mybase::operator=(_Right); return *this; } hash_map(hash_map&& _Right) : _Mybase(_STD move(_Right)) {} hash_map(hash_map&& _Right, const allocator_type& _Al) : _Mybase(_STD move(_Right), _Al) {} hash_map& operator=(hash_map&& _Right) noexcept(noexcept(_Mybase::operator=(_STD move(_Right)))) { _Mybase::operator=(_STD move(_Right)); return *this; } mapped_type& operator[](key_type&& _Keyval) { return this->_Try_emplace(_STD move(_Keyval)).first->_Myval.second; } void swap(hash_map& _Right) noexcept(noexcept(_Mybase::swap(_Right))) { _Mybase::swap(_Right); } using _Mybase::insert; template , int> = 0> pair insert(_Valty&& _Val) { return this->emplace(_STD forward<_Valty>(_Val)); } template , int> = 0> iterator insert(const_iterator _Where, _Valty&& _Val) { return this->emplace_hint(_Where, _STD forward<_Valty>(_Val)); } hash_map(_STD initializer_list _Ilist) : _Mybase(key_compare(), allocator_type()) { insert(_Ilist); } hash_map(_STD initializer_list _Ilist, const key_compare& _Pred) : _Mybase(_Pred, allocator_type()) { insert(_Ilist); } hash_map(_STD initializer_list _Ilist, const key_compare& _Pred, const allocator_type& _Al) : _Mybase(_Pred, _Al) { insert(_Ilist); } hash_map& operator=(_STD initializer_list _Ilist) { this->clear(); insert(_Ilist); return *this; } mapped_type& operator[](const key_type& _Keyval) { return this->_Try_emplace(_Keyval).first->_Myval.second; } mapped_type& at(const key_type& _Keyval) { const auto _Target = this->_Find_last(_Keyval, this->_Traitsobj(_Keyval)); if (_Target._Duplicate) { return _Target._Duplicate->_Myval.second; } _Xout_of_range("invalid hash_map key"); } const mapped_type& at(const key_type& _Keyval) const { const auto _Target = this->_Find_last(_Keyval, this->_Traitsobj(_Keyval)); if (_Target._Duplicate) { return _Target._Duplicate->_Myval.second; } _Xout_of_range("invalid hash_map key"); } using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; reverse_iterator rbegin() noexcept { return reverse_iterator(this->end()); } const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(this->end()); } reverse_iterator rend() noexcept { return reverse_iterator(this->begin()); } const_reverse_iterator rend() const noexcept { return const_reverse_iterator(this->begin()); } const_reverse_iterator crbegin() const noexcept { return rbegin(); } const_reverse_iterator crend() const noexcept { return rend(); } _NODISCARD key_compare key_comp() const { return this->_Traitsobj; } _NODISCARD value_compare value_comp() const { return value_compare(key_comp()); } using _Mybase::_Unchecked_begin; using _Mybase::_Unchecked_end; }; template void swap(hash_map<_Kty, _Ty, _Tr, _Alloc>& _Left, hash_map<_Kty, _Ty, _Tr, _Alloc>& _Right) noexcept( noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } template _NODISCARD bool operator==( const hash_map<_Kty, _Ty, _Tr, _Alloc>& _Left, const hash_map<_Kty, _Ty, _Tr, _Alloc>& _Right) { return _STD _Hash_equal(_Left, _Right); } template _NODISCARD bool operator!=( const hash_map<_Kty, _Ty, _Tr, _Alloc>& _Left, const hash_map<_Kty, _Ty, _Tr, _Alloc>& _Right) { return !(_Left == _Right); } // CLASS TEMPLATE hash_multimap template >, class _Alloc = allocator>> class hash_multimap : public _Hash<_Hmap_traits<_Kty, _Ty, _Tr, _Alloc, true>> { // hash table of {key, mapped} values, non-unique keys public: using _Mybase = _Hash<_Hmap_traits<_Kty, _Ty, _Tr, _Alloc, true>>; using key_type = _Kty; using mapped_type = _Ty; using referent_type = _Ty; // old name, magically gone using key_compare = _Tr; using value_compare = typename _Mybase::_Value_compare; using value_type = pair; using allocator_type = typename _Mybase::allocator_type; using size_type = typename _Mybase::size_type; using difference_type = typename _Mybase::difference_type; using pointer = typename _Mybase::pointer; using const_pointer = typename _Mybase::const_pointer; using reference = value_type&; using const_reference = const value_type&; using iterator = typename _Mybase::iterator; using const_iterator = typename _Mybase::const_iterator; using _Alnode = typename _Mybase::_Alnode; using _Alnode_traits = typename _Mybase::_Alnode_traits; hash_multimap() : _Mybase(key_compare(), allocator_type()) {} explicit hash_multimap(const allocator_type& _Al) : _Mybase(key_compare(), _Al) {} hash_multimap(const hash_multimap& _Right) : _Mybase(_Right, _Alnode_traits::select_on_container_copy_construction(_Right._Getal())) {} hash_multimap(const hash_multimap& _Right, const allocator_type& _Al) : _Mybase(_Right, _Al) {} explicit hash_multimap(const key_compare& _Traits) : _Mybase(_Traits, allocator_type()) {} hash_multimap(const key_compare& _Traits, const allocator_type& _Al) : _Mybase(_Traits, _Al) {} template hash_multimap(_Iter _First, _Iter _Last) : _Mybase(key_compare(), allocator_type()) { insert(_First, _Last); } template hash_multimap(_Iter _First, _Iter _Last, const key_compare& _Traits) : _Mybase(_Traits, allocator_type()) { insert(_First, _Last); } template hash_multimap(_Iter _First, _Iter _Last, const key_compare& _Traits, const allocator_type& _Al) : _Mybase(_Traits, _Al) { insert(_First, _Last); } hash_multimap& operator=(const hash_multimap& _Right) { _Mybase::operator=(_Right); return *this; } hash_multimap(hash_multimap&& _Right) : _Mybase(_STD move(_Right)) {} hash_multimap(hash_multimap&& _Right, const allocator_type& _Al) : _Mybase(_STD move(_Right), _Al) {} hash_multimap& operator=(hash_multimap&& _Right) noexcept(noexcept(_Mybase::operator=(_STD move(_Right)))) { _Mybase::operator=(_STD move(_Right)); return *this; } void swap(hash_multimap& _Right) noexcept(noexcept(_Mybase::swap(_Right))) { _Mybase::swap(_Right); } using _Mybase::insert; template , int> = 0> iterator insert(_Valty&& _Val) { return this->emplace(_STD forward<_Valty>(_Val)); } template , int> = 0> iterator insert(const_iterator _Where, _Valty&& _Val) { return this->emplace_hint(_Where, _STD forward<_Valty>(_Val)); } hash_multimap(_STD initializer_list _Ilist) : _Mybase(key_compare(), allocator_type()) { insert(_Ilist); } hash_multimap(_STD initializer_list _Ilist, const key_compare& _Pred) : _Mybase(_Pred, allocator_type()) { insert(_Ilist); } hash_multimap(_STD initializer_list _Ilist, const key_compare& _Pred, const allocator_type& _Al) : _Mybase(_Pred, _Al) { insert(_Ilist); } hash_multimap& operator=(_STD initializer_list _Ilist) { this->clear(); insert(_Ilist); return *this; } using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; reverse_iterator rbegin() noexcept { return reverse_iterator(this->end()); } const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(this->end()); } reverse_iterator rend() noexcept { return reverse_iterator(this->begin()); } const_reverse_iterator rend() const noexcept { return const_reverse_iterator(this->begin()); } const_reverse_iterator crbegin() const noexcept { return rbegin(); } const_reverse_iterator crend() const noexcept { return rend(); } _NODISCARD key_compare key_comp() const { return this->_Traitsobj; } _NODISCARD value_compare value_comp() const { return value_compare(key_comp()); } using _Mybase::_Unchecked_begin; using _Mybase::_Unchecked_end; }; template void swap(hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Left, hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Right) noexcept( noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } template _NODISCARD bool operator==( const hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Left, const hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Right) { return _STD _Hash_equal(_Left, _Right); } template _NODISCARD bool operator!=( const hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Left, const hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Right) { return !(_Left == _Right); } } // namespace stdext _STD_BEGIN using _STDEXT hash_map; using _STDEXT hash_multimap; _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #endif // _STL_COMPILER_PREPROCESSOR #endif // _HASH_MAP_