// xhash internal header
#pragma once
#ifndef _XHASH_
#define _XHASH_
#ifndef RC_INVOKED
#include <cstring>
#include <cwchar>
#include <list>
#include <vector>

#if _HAS_CXX17
 #include <xnode_handle.h>
#endif /* _HAS_CXX17 */

 #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

namespace stdext {
using _STD basic_string;
using _STD less;
using _STD size_t;

		// FUNCTION TEMPLATE hash_value
template<class _Kty> inline
	size_t hash_value(const _Kty& _Keyval)
	{	// hash _Keyval to size_t value one-to-one
	return ((size_t)_Keyval ^ (size_t)0xdeadbeef);
	}

template<class _Elem,
	class _Traits,
	class _Alloc> inline
	size_t hash_value(const basic_string<_Elem, _Traits, _Alloc>& _Str)
	{	// hash string to size_t value
	return (_STD _Hash_array_representation(_Str.c_str(), _Str.size()));
	}

inline size_t hash_value(_In_z_ const char *_Str)
	{	// hash NTBS to size_t value
	return (_STD _Hash_array_representation(_Str, _CSTD strlen(_Str)));
	}

inline size_t hash_value(_In_z_ const wchar_t *_Str)
	{	// hash NTWCS to size_t value
	return (_STD _Hash_array_representation(_Str, _CSTD wcslen(_Str)));
	}

		// CLASS TEMPLATE hash_compare
template<class _Kty,
	class _Pr = less<_Kty>>
	class hash_compare
	{	// traits class for hash containers
public:
	enum
		{	// parameters for hash table
		bucket_size = 1		// 0 < bucket_size
		};

	hash_compare(_Pr _Pred = _Pr())
		: comp(_Pred)
		{	// construct with _Pred comparator
		}

	size_t operator()(const _Kty& _Keyval) const
		{	// hash _Keyval to size_t value by pseudorandomizing transform
		long _Quot = (long)(hash_value(_Keyval) & LONG_MAX);
		ldiv_t _Qrem = _CSTD ldiv(_Quot, 127773);

		_Qrem.rem = 16807 * _Qrem.rem - 2836 * _Qrem.quot;
		if (_Qrem.rem < 0)
			_Qrem.rem += LONG_MAX;
		return ((size_t)_Qrem.rem);
		}

	bool operator()(const _Kty& _Keyval1, const _Kty& _Keyval2) const
		{	// test if _Keyval1 ordered before _Keyval2
		return (comp(_Keyval1, _Keyval2));
		}

	_Pr comp;	// the comparator object
	};
}	// namespace stdext
_STD_BEGIN
using stdext::hash_compare;
using stdext::hash_value;
_STD_END

_STD_BEGIN
		// CLASS TEMPLATE _Uhash_compare
template<class _Kty,
	class _Hasher,
	class _Keyeq>
	class _Uhash_compare
	{	// traits class for unordered containers
public:
	enum
		{	// parameters for hash table
		bucket_size = 1	// 0 < bucket_size
		};

	_Uhash_compare(_Hasher _Hasharg = _Hasher(), _Keyeq _Keyeqarg = _Keyeq())
		: _Mypair(_One_then_variadic_args_t(), _Hasharg,
			_One_then_variadic_args_t(), _Keyeqarg, 0.0f)
		{	// construct with hasher and equality comparator
		}

	size_t operator()(const _Kty& _Keyval) const
		{	// hash _Keyval to size_t value
		return ((size_t)_Gethash()(_Keyval));
		}

	bool operator()(const _Kty& _Keyval1, const _Kty& _Keyval2) const
		{	// test if _Keyval1 NOT equal to _Keyval2
		return (!_Getkeyeq()(_Keyval1, _Keyval2));
		}

	const _Hasher& _Gethash() const noexcept
		{	// return const reference to hash function
		return (_Mypair._Get_first());
		}

	const _Keyeq& _Getkeyeq() const noexcept
		{	// return const reference to key equality predicate
		return (_Mypair._Get_second()._Get_first());
		}

	float& _Get_max_bucket_size() noexcept
		{	// return reference to current maximum bucket size
		return (_Mypair._Get_second()._Get_second());
		}

	const float& _Get_max_bucket_size() const noexcept
		{	// return const reference to current maximum bucket size
		return (_Mypair._Get_second()._Get_second());
		}

	void swap(_Uhash_compare& _Rhs) _NOEXCEPT_COND(_Is_nothrow_swappable<_Hasher>::value
		&& _Is_nothrow_swappable<_Keyeq>::value)
		{
		_Swap_adl(_Mypair._Get_first(), _Rhs._Mypair._Get_first());
		auto& _Lsecond = _Mypair._Get_second();
		auto& _Rsecond = _Rhs._Mypair._Get_second();
		_Swap_adl(_Lsecond._Get_first(), _Rsecond._Get_first());
		_STD swap(_Lsecond._Get_second(), _Rsecond._Get_second());
		}

	_Compressed_pair<_Hasher, _Compressed_pair<_Keyeq, float>> _Mypair;
	};

		// CLASS TEMPLATE _Hash
template<class _Traits>
	class _Hash
	{	// hash table -- list with vector of iterators for quick access
public:
	using key_type = typename _Traits::key_type;
	using key_compare = typename _Traits::key_compare;
	using value_compare = typename _Traits::value_compare;
	enum
		{	// various constants
		_Bucket_size = key_compare::bucket_size,
		_Min_buckets = 8,	// min_buckets = 2 ^^ N, 0 < N
		_Multi = _Traits::_Multi};
	using _Mylist = list<typename _Traits::value_type, typename _Traits::allocator_type>;
	using _Alnode = typename _Mylist::_Alnode;
	using _Alnode_traits = typename _Mylist::_Alnode_traits;

	using value_type = typename _Mylist::value_type;
	using allocator_type = typename _Mylist::allocator_type;
	using size_type = typename _Mylist::size_type;
	using difference_type = typename _Mylist::difference_type;
	using pointer = typename _Mylist::pointer;
	using const_pointer = typename _Mylist::const_pointer;
	using reference = value_type&;
	using const_reference = const value_type&;

	using iterator = conditional_t<is_same_v<key_type, value_type>,
		typename _Mylist::const_iterator,
		typename _Mylist::iterator>;
	using const_iterator = typename _Mylist::const_iterator;

	using _Unchecked_iterator = conditional_t<is_same_v<key_type, value_type>,
		typename _Mylist::_Unchecked_const_iterator,
		typename _Mylist::_Unchecked_iterator>;
	using _Unchecked_const_iterator = typename _Mylist::_Unchecked_const_iterator;

	using _Aliter = _Rebind_alloc_t<_Alnode, _Unchecked_iterator>;
	using _Myvec = vector<_Unchecked_iterator, _Aliter>;

	using _Pairib = pair<iterator, bool>;
	using _Pairii = pair<iterator, iterator>;
	using _Paircc = pair<const_iterator, const_iterator>;

	_Hash(const key_compare& _Parg,
		const allocator_type& _Al)
		: _Traitsobj(_Parg),
			_List(_Al),
			_Vec(static_cast<_Aliter>(_Al))
		{	// construct empty hash table
		_Max_bucket_size() = _Bucket_size;
		_Init();
		}

	template<class _Any_alloc>
		_Hash(const _Hash& _Right, const _Any_alloc& _Al)
		: _Traitsobj(_Right._Traitsobj),
			_List(allocator_type(_Al)),
			_Vec(static_cast<_Aliter>(_Al))
		{	// construct hash table by copying right
		_Copy(_Right);
		}

	_Hash(_Hash&& _Right)
		: _Traitsobj(_Right._Traitsobj),
			_List(_STD move(_Right._List)),
			_Vec(_STD move(_Right._Vec)),
			_Mask(_Right._Mask),
			_Maxidx(_Right._Maxidx)
		{	// construct hash table by moving _Right
		_Right.clear();
		}

	template<class _Iter>
		void _Move_nodes(_Iter _First, _Iter _Last, true_type)
		{	// move set elements
		for ( ; _First != _Last; ++_First)
			{
			_List.push_back(_STD move(*_First));
			}
		}

	template<class _Iter>
		void _Move_nodes(_Iter _First, _Iter _Last, false_type)
		{	// move map elements
		for ( ; _First != _Last; ++_First)
			{
			_List.emplace_back(_STD move(const_cast<key_type&>(_First->first)), _STD move(_First->second));
			}
		}

	template<class _Other>
		void _Move_assign_list(_Other& _Right, true_type)
		{	// move elements, POCMA
		_List = _STD move(_Right._List);
		}

	template<class _Other>
		void _Move_assign_list(_Other& _Right, false_type)
		{	// move elements, non-POCMA
		_List.clear();

		if (_List._Getal() == _Right._List._Getal())
			{
			_List._Assign_rv(_STD move(_Right._List), true_type());
			}
		else
			{
			_Move_nodes(_Right._List.begin(), _Right._List.end(), is_same<key_type, value_type>());

			_Init(bucket_count());
			_Reinsert();
			}
		}

	_Hash(_Hash&& _Right, const allocator_type& _Al)
		: _Traitsobj(_Right._Traitsobj),
			_List(_Al),
			_Vec(_STD move(_Right._Vec), static_cast<_Aliter>(_Al)),
			_Mask(_Right._Mask),
			_Maxidx(_Right._Maxidx)
		{	// construct hash table by moving _Right, allocator
		_Move_assign_list(_Right, false_type());

		_Right.clear();
		}

	_Hash& operator=(_Hash&& _Right)
		{	// assign by moving _Right
		if (this != _STD addressof(_Right))
			{
			_Traitsobj = _Right._Traitsobj;
			_Vec = _STD move(_Right._Vec);
			_Mask = _Right._Mask;
			_Maxidx = _Right._Maxidx;

			_Move_assign_list(_Right, typename _Alnode_traits::propagate_on_container_move_assignment());

			_Right.clear();
			}

		return (*this);
		}

	template<class... _Valty>
		_Pairib emplace(_Valty&&... _Val)
		{	// try to insert value_type(_Val...)
		_List.emplace_front(_STD forward<_Valty>(_Val)...);
		return (_Insert(_List.front(), _Unchecked_begin()));
		}

	template<class... _Valty>
		iterator emplace_hint(const_iterator, _Valty&&... _Val)
		{	// try to insert value_type(_Val...), ignore hint
		_List.emplace_front(_STD forward<_Valty>(_Val)...);
		return (_Insert(_List.front(), _Unchecked_begin()).first);
		}

	_Hash& operator=(const _Hash& _Right)
		{	// replace contents from _Right
		if (this != _STD addressof(_Right))
			{
			_Mylist _List2(_Right._List.get_allocator());
			_List = _List2;	// respect POCCA
			_Myvec _Vec2(_Right._Vec.get_allocator());
			_Vec = _Vec2;	// respect POCCA
			_Copy(_Right);
			}

		return (*this);
		}

	_NODISCARD iterator begin() noexcept
		{	// return iterator for beginning of mutable sequence
		return (_List.begin());
		}

	_NODISCARD const_iterator begin() const noexcept
		{	// return iterator for beginning of nonmutable sequence
		return (_List.begin());
		}

	_NODISCARD iterator end() noexcept
		{	// return iterator for end of mutable sequence
		return (_List.end());
		}

	_NODISCARD const_iterator end() const noexcept
		{	// return iterator for end of nonmutable sequence
		return (_List.end());
		}

	_Unchecked_iterator _Unchecked_begin()
		{	// return iterator for beginning of mutable sequence
		return (_List._Unchecked_begin());
		}

	_Unchecked_const_iterator _Unchecked_begin() const
		{	// return iterator for beginning of nonmutable sequence
		return (_List._Unchecked_begin());
		}

	_Unchecked_iterator _Unchecked_end()
		{	// return iterator for end of mutable sequence
		return (_List._Unchecked_end());
		}

	_Unchecked_const_iterator _Unchecked_end() const
		{	// return iterator for end of nonmutable sequence
		return (_List._Unchecked_end());
		}

	iterator _Make_iter(_Unchecked_const_iterator _Where) const
		{	// make iterator from _Unchecked_const_iterator
		return (_List._Make_iter(_Where));
		}

	iterator _Make_iter(const_iterator _Where) const
		{	// make iterator from const_iterator
		return (_List._Make_iter(_Where));
		}

	_NODISCARD const_iterator cbegin() const noexcept
		{	// return iterator for beginning of nonmutable sequence
		return (begin());
		}

	_NODISCARD const_iterator cend() const noexcept
		{	// return iterator for end of nonmutable sequence
		return (end());
		}

	_NODISCARD size_type size() const noexcept
		{	// return length of sequence
		return (_List.size());
		}

	_NODISCARD size_type max_size() const noexcept
		{	// return maximum possible length of sequence
		return (_List.max_size());
		}

	_NODISCARD bool empty() const noexcept
		{	// return true only if sequence is empty
		return (_List.empty());
		}

	_NODISCARD allocator_type get_allocator() const noexcept
		{	// return allocator object for values
		return (static_cast<allocator_type>(_List.get_allocator()));
		}

	_NODISCARD key_compare key_comp() const
		{	// return object for comparing keys
		return (_Traitsobj);
		}

	_NODISCARD value_compare value_comp() const
		{	// return object for comparing values
		return (value_compare(key_comp()));
		}

	using local_iterator = iterator;
	using const_local_iterator = const_iterator;

	_NODISCARD size_type bucket_count() const noexcept
		{	// return number of buckets
		return (_Maxidx);
		}

	_NODISCARD size_type max_bucket_count() const noexcept
		{	// return maximum number of buckets
		return (_Vec.max_size() / 2);
		}

	_NODISCARD size_type bucket(const key_type& _Keyval) const
		{	// return bucket corresponding to _Key
		return (_Hashval(_Keyval));
		}

	_NODISCARD size_type bucket_size(size_type _Bucket) const
		{	// return size of bucket _Bucket
		size_type _Ans = 0;
		if (_Bucket < _Maxidx)
			for (_Unchecked_const_iterator _Plist = _Begin(_Bucket);
				_Plist != _End(_Bucket); ++_Plist)
				++_Ans;
		return (_Ans);
		}

	_NODISCARD local_iterator begin(size_type _Bucket)
		{	// return iterator for bucket _Bucket
		if (_Bucket < bucket_count())
			return (_Make_iter(_Begin(_Bucket)));
		else
			return (end());
		}

	_NODISCARD const_local_iterator begin(size_type _Bucket) const
		{	// return iterator for bucket _Bucket
		if (_Bucket < bucket_count())
			return (_Make_iter(_Begin(_Bucket)));
		else
			return (end());
		}

	_NODISCARD local_iterator end(size_type _Bucket)
		{	// return iterator for bucket following _Bucket
		if (_Bucket < bucket_count())
			return (_Make_iter(_End(_Bucket)));
		else
			return (end());
		}

	_NODISCARD const_local_iterator end(size_type _Bucket) const
		{	// return iterator for bucket following _Bucket
		if (_Bucket < bucket_count())
			return (_Make_iter(_End(_Bucket)));
		else
			return (end());
		}

	_NODISCARD const_local_iterator cbegin(size_type _Bucket) const
		{	// return iterator for bucket _Bucket
		if (_Bucket < bucket_count())
			return (_Make_iter(_Begin(_Bucket)));
		else
			return (end());
		}

	_NODISCARD const_local_iterator cend(size_type _Bucket) const
		{	// return iterator for bucket following _Bucket
		if (_Bucket < bucket_count())
			return (_Make_iter(_End(_Bucket)));
		else
			return (end());
		}

	_NODISCARD float load_factor() const noexcept
		{	// return elements per bucket
		return ((float)size() / (float)bucket_count());
		}

	_NODISCARD float max_load_factor() const noexcept
		{	// return maximum elements per bucket
		return (_Max_bucket_size());
		}

	void max_load_factor(float _Newmax)
		{	// set new load factor
		if (_Newmax != _Newmax	// may detect a NaN
			|| _Newmax < 0)
			_Xout_of_range("invalid hash load factor");

		_Max_bucket_size() = _Newmax;
		}

	void rehash(size_type _Buckets)
		{	// rebuild table with at least _Buckets buckets
		size_type _Maxsize = _Vec.max_size() / 4;
		size_type _Newsize = _Min_buckets;

		while (_Newsize < _Buckets && _Newsize < _Maxsize)
			{
			_Newsize *= 2;	// double until big enough
			}

		if (_Newsize < _Buckets)
			{
			_Xout_of_range("invalid hash bucket count");
			}

		while (!(size() / max_load_factor() < _Newsize) && _Newsize < _Maxsize)
			{	// double until load factor okay
			_Newsize *= 2;
			}

		_Init(_Newsize);
		_Reinsert();
		}

	void reserve(size_type _Maxcount)
		{	// rebuild table with room for _Maxcount elements
		rehash((size_type)((float)(_Maxcount / max_load_factor() + 0.5F)));
		}

	template<bool _Multi2 = _Multi,
		enable_if_t<!_Multi2, int> = 0>
		_Pairib insert(const value_type& _Val)
		{	// try to insert node with value _Val
		return (_Insert(_Val, _Not_a_node_tag()));
		}

	template<bool _Multi2 = _Multi,
		enable_if_t<_Multi2, int> = 0>
		iterator insert(const value_type& _Val)
		{	// try to insert node with value _Val
		return (_Insert(_Val, _Not_a_node_tag()).first);
		}

	template<bool _Multi2 = _Multi,
		enable_if_t<!_Multi2, int> = 0>
		_Pairib insert(value_type&& _Val)
		{	// try to insert node with value _Val, favoring right side
		return (_Insert(_STD move(_Val), _Not_a_node_tag()));
		}

	template<bool _Multi2 = _Multi,
		enable_if_t<_Multi2, int> = 0>
		iterator insert(value_type&& _Val)
		{	// try to insert node with value _Val, favoring right side
		return (_Insert(_STD move(_Val), _Not_a_node_tag()).first);
		}

	iterator insert(const_iterator,
		const value_type& _Val)
		{	// try to insert node with value _Val, ignore hint
		return (_Insert(_Val, _Not_a_node_tag()).first);
		}

	iterator insert(const_iterator, value_type&& _Val)
		{	// try to insert node with value _Val, ignore hint
		return (_Insert(_STD move(_Val), _Not_a_node_tag()).first);
		}

	template<class _Iter>
		void insert(_Iter _First, _Iter _Last)
		{	// insert [_First, _Last) at front, then put in place
		_Adl_verify_range(_First, _Last);
		auto _UFirst = _Get_unwrapped(_First);
		const auto _ULast = _Get_unwrapped(_Last);
		for (; _UFirst != _ULast; ++_UFirst)
			{
			emplace(*_UFirst);
			}
		}

	void insert(initializer_list<value_type> _Ilist)
		{	// insert initializer_list
		insert(_Ilist.begin(), _Ilist.end());
		}

	template<class _Iter = iterator,
		class = enable_if_t<!is_same_v<_Iter, const_iterator>>>
		iterator erase(iterator _Plist)
		{	// erase element at _Plist
		return (erase(const_iterator{_Plist}));
		}

	iterator erase(const_iterator _Plist)
		{	// erase element at _Plist
		size_type _Bucket = _Hashval(_Traits::_Kfn(*_Plist));

		_Erase_bucket(_Make_iter(_Plist), _Bucket);
		return (_List.erase(_Plist));
		}

	iterator erase(const_iterator _First, const_iterator _Last)
		{	// erase [_First, _Last)
		if (_First == begin() && _Last == end())
			{	// erase all
			clear();
			return (begin());
			}

		// partial erase, one at a time
		while (_First != _Last)
			{
			erase(_First++);
			}

		return (_Make_iter(_First));
		}

	size_type erase(const key_type& _Keyval)
		{	// erase and count all that match _Keyval
		_Pairii _Where = equal_range(_Keyval);
		const auto _Num = static_cast<size_type>(_STD distance(_Where.first, _Where.second));
		erase(_Where.first, _Where.second);
		return (_Num);
		}

	void clear() noexcept
		{	// erase all
		_List.clear();
		_Init();
		}

	_NODISCARD iterator find(const key_type& _Keyval)
		{	// find an element in mutable hash table that matches _Keyval
		return (lower_bound(_Keyval));
		}

	_NODISCARD const_iterator find(const key_type& _Keyval) const
		{	// find an element in nonmutable hash table that matches _Keyval
		return (lower_bound(_Keyval));
		}

	_NODISCARD size_type count(const key_type& _Keyval) const
		{	// count all elements that match _Keyval
		_Paircc _Ans = equal_range(_Keyval);
		return (static_cast<size_type>(_STD distance(_Ans.first, _Ans.second)));
		}

	_NODISCARD iterator lower_bound(const key_type& _Keyval)
		{	// find leftmost not less than _Keyval in mutable hash table
		size_type _Bucket = _Hashval(_Keyval);
		for (_Unchecked_iterator _Where = _Begin(_Bucket);
			_Where != _End(_Bucket); ++_Where)
			if (!_Traitsobj(_Traits::_Kfn(*_Where), _Keyval))
				return (_Traitsobj(_Keyval,
					_Traits::_Kfn(*_Where)) ? end() : _Make_iter(_Where));
		return (end());
		}

	_NODISCARD const_iterator lower_bound(const key_type& _Keyval) const
		{	// find leftmost not less than _Keyval in nonmutable hash table
		size_type _Bucket = _Hashval(_Keyval);
		for (_Unchecked_const_iterator _Where = _Begin(_Bucket);
			_Where != _End(_Bucket); ++_Where)
			if (!_Traitsobj(_Traits::_Kfn(*_Where), _Keyval))
				return (_Traitsobj(_Keyval,
					_Traits::_Kfn(*_Where)) ? end() : _Make_iter(_Where));
		return (end());
		}

	_NODISCARD iterator upper_bound(const key_type& _Keyval)
		{	// find leftmost not greater than _Keyval in mutable hash table
		size_type _Bucket = _Hashval(_Keyval);
		for (_Unchecked_iterator _Where = _End(_Bucket);
			_Where != _Begin(_Bucket); )
			if (!_Traitsobj(_Keyval, _Traits::_Kfn(*--_Where)))
				return (_Traitsobj(_Traits::_Kfn(*_Where),
					_Keyval) ? end() : _Make_iter(++_Where));
		return (end());
		}

	_NODISCARD const_iterator upper_bound(const key_type& _Keyval) const
		{	// find leftmost not greater than _Keyval in nonmutable hash table
		size_type _Bucket = _Hashval(_Keyval);
		for (_Unchecked_const_iterator _Where = _End(_Bucket);
			_Where != _Begin(_Bucket); )
			if (!_Traitsobj(_Keyval, _Traits::_Kfn(*--_Where)))
				return (_Traitsobj(_Traits::_Kfn(*_Where),
					_Keyval) ? end() : _Make_iter(++_Where));
		return (end());
		}

	_NODISCARD _Pairii equal_range(const key_type& _Keyval)
		{	// find range equivalent to _Keyval in mutable hash table
		size_type _Bucket = _Hashval(_Keyval);
		for (_Unchecked_iterator _Where = _Begin(_Bucket);
			_Where != _End(_Bucket); ++_Where)
			if (!_Traitsobj(_Traits::_Kfn(*_Where), _Keyval))
				{	// found _First, look for end of range
				_Unchecked_iterator _First = _Where;
				for (; _Where != _End(_Bucket); ++_Where)
					if (_Traitsobj(_Keyval, _Traits::_Kfn(*_Where)))
						break;
				if (_First == _Where)
					break;
				return (_Pairii(_Make_iter(_First),
					_Make_iter(_Where)));
				}
		return (_Pairii(end(), end()));
		}

	_NODISCARD _Paircc equal_range(const key_type& _Keyval) const
		{	// find range equivalent to _Keyval in nonmutable hash table
		size_type _Bucket = _Hashval(_Keyval);
		for (_Unchecked_const_iterator _Where = _Begin(_Bucket);
			_Where != _End(_Bucket); ++_Where)
			if (!_Traitsobj(_Traits::_Kfn(*_Where), _Keyval))
				{	// found _First, look for end of range
				_Unchecked_const_iterator _First = _Where;
				for (; _Where != _End(_Bucket); ++_Where)
					if (_Traitsobj(_Keyval, _Traits::_Kfn(*_Where)))
						break;
				if (_First == _Where)
					break;
				return (_Paircc(_Make_iter(_First),
					_Make_iter(_Where)));
				}
		return (_Paircc(end(), end()));
		}

	void swap(_Hash& _Right)
		_NOEXCEPT_COND(_NOEXCEPT_OPER(_Traitsobj.swap(_Right._Traitsobj))) // strengthened
		{	// exchange contents with _Right
		if (this != _STD addressof(_Right))
			{	// different, worth swapping
			_Traitsobj.swap(_Right._Traitsobj);
			_List.swap(_Right._List);
			_Vec.swap(_Right._Vec);
			_Swap_adl(_Mask, _Right._Mask);
			_Swap_adl(_Maxidx, _Right._Maxidx);
			}
		}

protected:
	template<class _Valty>
		_Unchecked_iterator _Buy_if_not_node(_Valty&&, _Unchecked_iterator _Plist)
		{	// node exists, just return it
		return (_Plist);
		}

	template<class _Valty>
		_Unchecked_iterator _Buy_if_not_node(_Valty&& _Val, _Not_a_node_tag)
		{	// node doesn't exist, make it
		_List.push_front(_STD forward<_Valty>(_Val));
		return (_Unchecked_begin());
		}

	void _Destroy_if_node(_Unchecked_iterator _Plist)
		{	// node exists, destroy it
		_List.erase(_Make_iter(_Plist));
		}

	void _Destroy_if_node(_Not_a_node_tag)
		{	// node doesn't exist, do nothing
		}

 #if _HAS_CXX17
public:
	using node_type = typename _Traits::node_type;

	node_type extract(const const_iterator _Where)
		{	// extract the node denoted by _Where
		return (node_type::_Make(_Extract(_Where), _List._Getal()));
		}

	node_type extract(const key_type& _Keyval)
		{	// extract the first node whose key matches _Keyval
		const auto _Ptr = _Extract(_Keyval);
		if (!_Ptr)
			{
			return (node_type{});
			}

		return (node_type::_Make(_Ptr, _List._Getal()));
		}

	auto insert(node_type&& _Handle)
		{	// insert the node (if any) held in _Handle
  #if 1  /* TRANSITION, if constexpr */
		return _Insert_helper(bool_constant<_Multi>{}, _STD move(_Handle));
  #else  /* TRANSITION, if constexpr */
		const auto _Result = _Insert_node(_STD move(_Handle));
		if constexpr (_Multi)
			{
			return (_Result.first);
			}
		else
			{
			return (_Insert_return_type<iterator, node_type>{
				_Result.first, _Result.second, _STD move(_Handle)});
			}
  #endif /* TRANSITION, if constexpr */
		}

	iterator insert(const_iterator, node_type&& _Handle)
		{	// insert the node (if any) held in _Handle, ignore hint
		return (_Insert_node(_STD move(_Handle)).first);
		}

	template<class>
		friend class _Hash;

	template<class _Other_traits>
		void merge(_Hash<_Other_traits>& _That)
		{	// transfer all nodes from _That into *this
		static_assert(is_same_v<typename _Mylist::_Nodeptr,
			typename _Hash<_Other_traits>::_Mylist::_Nodeptr>,
			"merge() requires an argument with a compatible node type.");

		static_assert(is_same_v<allocator_type, typename _Hash<_Other_traits>::allocator_type>,
			"merge() requires an argument with the same allocator type.");

  #if 1  /* TRANSITION, if constexpr */
		if (_Check_self(_STD addressof(_That)))
			{
			return;
			}
  #else  /* TRANSITION, if constexpr */
		if constexpr (is_same_v<_Hash, _Hash<_Other_traits>>)
			{
			if (this == _STD addressof(_That))
				{
				return;
				}
			}
  #endif /* TRANSITION, if constexpr */

#if _ITERATOR_DEBUG_LEVEL == 2
		_STL_VERIFY(_List._Getal() == _That._List._Getal(), "allocator incompatible for merge");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */

		_Node_merge_wrapper<_Other_traits> _Wrapper{_That, {}};
		auto _First = _That.begin();
		const auto _Last = _That.end();
		while (_First != _Last)
			{
			_Wrapper._Where = _First;
			++_First;
			_Insert(_Wrapper._Where._Ptr->_Myval, _STD addressof(_Wrapper));
			}
		}

protected:
	_Unchecked_iterator _Buy_if_not_node(_Any_tag, node_type * const _Node_handle)
		{	// Extract node from node handle
		const auto _Ptr = _Node_handle->_Release();
		_List._Relink(_List._Unchecked_begin(), _Ptr);
		return (_List._Unchecked_begin());
		}

	void _Destroy_if_node(node_type *)
		{	// Handle retains ownership of node
		}

	typename _Mylist::_Nodeptr _Extract(const const_iterator _Where)
		{	// Extract node at _Where
		const size_type _Bucket = _Hashval(_Traits::_Kfn(*_Where));
		_Erase_bucket(_Make_iter(_Where), _Bucket);
		return (_List._Unlinknode(_Where));
		}

	typename _Mylist::_Nodeptr _Extract(const key_type& _Keyval)
		{	// Extract node with key equal to _Keyval
		const size_type _Bucket = _Hashval(_Keyval);
		for (_Unchecked_iterator _Where = _Begin(_Bucket); _Where != _End(_Bucket); ++_Where)
			{
			if (!_Traitsobj(_Traits::_Kfn(*_Where), _Keyval))
				{
				if (_Traitsobj(_Keyval, _Traits::_Kfn(*_Where)))
					{
					break;
					}

				const auto _Iter = _Make_iter(_Where);
				_Erase_bucket(_Iter, _Bucket);
				return (_List._Unlinknode(_Iter));
				}
			}

		return (nullptr);
		}

	_Pairib _Insert_node(node_type&& _Handle)
		{	// insert the node (if any) held in _Handle
		if (_Handle.empty())
			{
			return (_Pairib{end(), false});
			}

  #if _ITERATOR_DEBUG_LEVEL == 2
		_STL_VERIFY(_List._Getal() == _Handle._Getal(), "node handle allocator incompatible for insert");
  #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

		return (_Insert(_Handle._Getptr()->_Myval, _STD addressof(_Handle)));
		}

	template<class _Other_traits>
		struct _Node_merge_wrapper
		{
		_Hash<_Other_traits>& _That;
		typename _Hash<_Other_traits>::iterator _Where;
		};

	template<class _Other_traits>
		_Unchecked_iterator _Buy_if_not_node(
			_Any_tag, _Node_merge_wrapper<_Other_traits> * const _Wrapper)
		{	// Transition the denoted node into this container
		auto& _That = _Wrapper->_That;
		const auto _Where = _Wrapper->_Where;
		const size_type _Bucket = _That._Hashval(_Other_traits::_Kfn(*_Where));
		_That._Erase_bucket(_Where, _Bucket);
		_List._Splice(_List.begin(), _That._List, _Where, _STD next(_Where), 1);
		return (_List._Unchecked_begin());
		}

	template<class _Other_traits>
		void _Destroy_if_node(_Node_merge_wrapper<_Other_traits> *)
		{	// Source container retains ownership of node
		}

  #if 1  /* TRANSITION, if constexpr */
private:
	auto _Insert_helper(true_type, node_type&& _Handle)
		{	// insert _Handle, unordered_multi(set|map) case
		const auto _Result = _Insert_node(_STD move(_Handle));
		return (_Result.first);
		}

	auto _Insert_helper(false_type, node_type&& _Handle)
		{	// insert _Handle, unordered_(set|map) case
		const auto _Result = _Insert_node(_STD move(_Handle));
		return (_Insert_return_type<iterator, node_type>{
			_Result.first, _Result.second, _STD move(_Handle)});
		}

	bool _Check_self(const _Hash * const _That) const
		{	// determine if argument points to *this, same-type case
		return (this == _That);
		}
	bool _Check_self(const void *) const
		{	// determine if argument points to *this, different-type case
		return (false);
		}
  #endif /* TRANSITION, if constexpr */
 #endif /* _HAS_CXX17 */

protected:
	template<class _Valty,
		class _Nodety>
		_Pairib _Insert(_Valty&& _Val, _Nodety _Pnode)
		{	// try to insert existing node with value _Val
		size_type _Bucket;
		_Unchecked_iterator _Where;

		_TRY_BEGIN
		_Bucket = _Hashval(_Traits::_Kfn(_Val));
		_Where = _End(_Bucket);
		while (_Where != _Begin(_Bucket))
			{
#pragma warning(push)
#pragma warning(disable: 4127)	// conditional expression is constant
			if (!_Traitsobj(_Traits::_Kfn(_Val), _Traits::_Kfn(*--_Where)))
				{	// not still too high in bucket list
				if (_Multi
					|| (!_Traits::_Standard
						&& _Traitsobj(_Traits::_Kfn(*_Where),
							_Traits::_Kfn(_Val))))
					{	// found insertion point, back up to it
					++_Where;
					break;
					}

				// discard new list element and return existing
				_Destroy_if_node(_Pnode);
				return (_Pairib(_Make_iter(_Where), false));
				}
#pragma warning(pop)
			}
		_CATCH_ALL
		_Destroy_if_node(_Pnode);
		_RERAISE;
		_CATCH_END

		_Unchecked_iterator _Plist =
			_Buy_if_not_node(_STD forward<_Valty>(_Val), _Pnode);
		_Unchecked_iterator _Next = _Plist;

		if (_Where != ++_Next)	// move element into place
			_List._Unchecked_splice(_Where, _Plist, _Next);

		_Insert_bucket(_Plist, _Where, _Bucket);

		_TRY_BEGIN
		_Check_size();
		_CATCH_ALL
		erase(_Make_iter(_Plist));
		_RERAISE;
		_CATCH_END

		return (_Pairib(_Make_iter(_Plist), true));
		}

	_Unchecked_iterator& _Vec_lo(size_type _Bucket)
		{	// return reference to begin() for _Bucket
		return (_Vec[2 * _Bucket]);
		}

	_Unchecked_const_iterator& _Vec_lo(size_type _Bucket) const
		{	// return reference to begin() for _Bucket
		return ((_Unchecked_const_iterator&)_Vec[2 * _Bucket]);
		}

	_Unchecked_iterator& _Vec_hi(size_type _Bucket)
		{	// return reference to end()-1 for _Bucket
		return (_Vec[2 * _Bucket + 1]);
		}

	_Unchecked_const_iterator& _Vec_hi(size_type _Bucket) const
		{	// return reference to end()-1 for _Bucket
		return ((_Unchecked_const_iterator&)_Vec[2 * _Bucket + 1]);
		}

	_Unchecked_iterator _Begin(size_type _Bucket)
		{	// return begin iterator for bucket _Bucket
		return (_Vec_lo(_Bucket));
		}

	_Unchecked_const_iterator _Begin(size_type _Bucket) const
		{	// return begin iterator for bucket _Bucket
		return (_Vec_lo(_Bucket));
		}

	_Unchecked_iterator _End(size_type _Bucket)
		{	// return end iterator for bucket _Bucket
		if (_Vec_lo(_Bucket) == _Unchecked_end())
			return (_Unchecked_end());
		else
			{	// point past last element
			_Unchecked_iterator _Ans = _Vec_hi(_Bucket);
			return (++_Ans);
			}
		}
	_Unchecked_const_iterator _End(size_type _Bucket) const
		{	// return end iterator for bucket _Bucket
		if (_Vec_lo(_Bucket) == _Unchecked_end())
			return (_Unchecked_end());
		else
			{	// point past last element
			_Unchecked_const_iterator _Ans = _Vec_hi(_Bucket);
			return (++_Ans);
			}
		}

	void _Erase_bucket(iterator _Plist_arg, size_type _Bucket)
		{	// fix iterators before erasing _Plist before _Where
		_Unchecked_iterator _Plist = _Plist_arg._Unwrapped();
		if (_Vec_hi(_Bucket) == _Plist)
			{
			if (_Vec_lo(_Bucket) == _Plist)
				{	// make bucket empty
				_Vec_lo(_Bucket) = _Unchecked_end();
				_Vec_hi(_Bucket) = _Unchecked_end();
				}
			else
				{
				_Vec_hi(_Bucket) = --_Plist;	// move end back one element
				}
			}
		else if (_Vec_lo(_Bucket) == _Plist)
			{
			_Vec_lo(_Bucket) = ++_Plist;	// move beginning up one element
			}
		}

	void _Insert_bucket(_Unchecked_iterator _Plist,
		_Unchecked_iterator _Where, size_type _Bucket)
		{	// fix iterators after inserting _Plist before _Where
		if (_Vec_lo(_Bucket) == _Unchecked_end())
			{	// make bucket non-empty
			_Vec_lo(_Bucket) = _Plist;
			_Vec_hi(_Bucket) = _Plist;
			}
		else if (_Vec_lo(_Bucket) == _Where)
			_Vec_lo(_Bucket) = _Plist;	// move beginning back one element
		else if (++_Vec_hi(_Bucket) != _Plist)	// move end up one element
			--_Vec_hi(_Bucket);	// or not
		}

	void _Copy(const _Hash& _Right)
		{	// copy entire hash table
		_Mask = _Right._Mask;
		_Maxidx = _Right._Maxidx;
		_List.clear();

		_TRY_BEGIN
		_Traitsobj = _Right._Traitsobj;
		_Vec.assign(_Right._Vec.size(), _Unchecked_end());
		insert(_Right.begin(), _Right.end());
		_CATCH_ALL
		clear();	// list or compare copy failed, bail out
		_RERAISE;
		_CATCH_END
		}

	size_type _Hashval(const key_type& _Keyval) const
		{	// return hash value, masked to current table size
		return (_Traitsobj(_Keyval) & _Mask);
		}

	void _Init(size_type _Buckets = _Min_buckets)
		{	// initialize hash table with _Buckets buckets, leave list alone
		_Vec.reserve(2 * _Buckets);	// avoid curdling _Vec if exception occurs
		_Vec.assign(2 * _Buckets, _Unchecked_end());
		_Mask = _Buckets - 1;
		_Maxidx = _Buckets;
		}

	void _Check_size()
		{	// grow table as needed
		if (max_load_factor() < load_factor())

			{	// rehash to bigger table
			size_type _Newsize = bucket_count();

			if (_Newsize < 512)
				_Newsize *= 8;	// multiply by 8
			else if (_Newsize < _Vec.max_size() / 2)
				_Newsize *= 2;	// multiply safely by 2
			_Init(_Newsize);
			_Reinsert();
			}
		}

	void _Reinsert()
		{	// insert elements in [begin(), end())
		_Unchecked_iterator _Last = _Unchecked_end();
		if (_Unchecked_begin() != _Last)
			for (--_Last; ; )
				{	// reinsert elements in [begin(), _Last]
				_Unchecked_iterator _First = _Unchecked_begin();
				bool _Done = _First == _Last;
				_Insert(*_First, _First);
				if (_Done)
					break;
				}
		}

	float& _Max_bucket_size() noexcept
		{	// return reference to current maximum bucket size
		return (_Traitsobj._Get_max_bucket_size());
		}

	const float& _Max_bucket_size() const noexcept
		{	// return const reference to current maximum bucket size
		return (_Traitsobj._Get_max_bucket_size());
		}

	_Traits _Traitsobj;	// traits to customize behavior
	_Mylist _List;	// list of elements, must initialize before _Vec
	_Myvec _Vec;	// vector of list iterators, begin() then end()-1
	size_type _Mask;	// the key mask
	size_type _Maxidx;	// current maximum key value
	};

#if _HAS_CXX17
		// ALIAS TEMPLATE _Is_hasher FOR CONSTRAINING DEDUCTION GUIDES, N4687 26.2.7 [unord.req]/17.3
template<class _Hasher>
	using _Is_hasher = negation<disjunction<is_integral<_Hasher>, _Is_allocator<_Hasher>>>;
#endif /* _HAS_CXX17 */

template<class _Traits> inline
	bool _Hash_equal_elements(
		const _Hash<_Traits>& _Left,
		const _Hash<_Traits>& _Right,
		false_type)
	{	// test for _Hash equality (same size, unique keys)
	using _Iter = typename _Hash<_Traits>::const_iterator;
	for (_Iter _Next1 = _Left.begin(); _Next1 != _Left.end(); ++_Next1)
		{	// look for element with equivalent key
		_Iter _Next2 = _Right.find(_Traits::_Kfn(*_Next1));
		if (_Next2 == _Right.end()
			|| !(_Traits::_Nonkfn(*_Next1) == _Traits::_Nonkfn(*_Next2)))
			return (false);
		}
	return (true);
	}

template<class _Traits> inline
	bool _Hash_equal_elements(
		const _Hash<_Traits>& _Left,
		const _Hash<_Traits>& _Right,
		true_type)
	{	// test for _Hash equality (same size, equivalent keys)
	using _Iter = typename _Hash<_Traits>::const_iterator;
	using _Iter_pair = pair<_Iter, _Iter>;

	for (_Iter _Next1 = _Left.begin(); _Next1 != _Left.end(); )
		{	// look for elements with equivalent keys
		_Iter_pair _Lrange = _Left.equal_range(_Traits::_Kfn(*_Next1));
		_Iter_pair _Rrange = _Right.equal_range(_Traits::_Kfn(*_Next1));

		if (!_STD is_permutation(_Lrange.first, _Lrange.second,
			_Rrange.first, _Rrange.second))
			return (false);
		_Next1 = _Lrange.second;	// continue just past range
		}
	return (true);
	}

template<class _Traits> inline
	bool _Hash_equal(
		const _Hash<_Traits>& _Left,
		const _Hash<_Traits>& _Right)
	{	// test for _Hash equality
	return (_Left.size() == _Right.size() && _Hash_equal_elements(
		_Left, _Right, bool_constant<_Traits::_Multi>{}));
	}
_STD_END

 #pragma pop_macro("new")
 _STL_RESTORE_CLANG_WARNINGS
 #pragma warning(pop)
 #pragma pack(pop)
#endif /* RC_INVOKED */
#endif /* _XHASH_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0009 */
