// -*- C++ -*- //===-------------------------- hash_map ----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_HASH_MAP #define _LIBCPP_HASH_MAP /* hash_map synopsis namespace __gnu_cxx { template , class Pred = equal_to, class Alloc = allocator>> class hash_map { public: // types typedef Key key_type; typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; typedef Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef /unspecified/ iterator; typedef /unspecified/ const_iterator; explicit hash_map(size_type n = 193, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template hash_map(InputIterator f, InputIterator l, size_type n = 193, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); hash_map(const hash_map&); ~hash_map(); hash_map& operator=(const hash_map&); allocator_type get_allocator() const; bool empty() const; size_type size() const; size_type max_size() const; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; pair insert(const value_type& obj); template void insert(InputIterator first, InputIterator last); void erase(const_iterator position); size_type erase(const key_type& k); void erase(const_iterator first, const_iterator last); void clear(); void swap(hash_map&); hasher hash_funct() const; key_equal key_eq() const; iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; mapped_type& operator[](const key_type& k); size_type bucket_count() const; size_type max_bucket_count() const; size_type elems_in_bucket(size_type n) const; void resize(size_type n); }; template void swap(hash_map& x, hash_map& y); template bool operator==(const hash_map& x, const hash_map& y); template bool operator!=(const hash_map& x, const hash_map& y); template , class Pred = equal_to, class Alloc = allocator>> class hash_multimap { public: // types typedef Key key_type; typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; typedef Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef /unspecified/ iterator; typedef /unspecified/ const_iterator; explicit hash_multimap(size_type n = 193, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template hash_multimap(InputIterator f, InputIterator l, size_type n = 193, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); explicit hash_multimap(const allocator_type&); hash_multimap(const hash_multimap&); ~hash_multimap(); hash_multimap& operator=(const hash_multimap&); allocator_type get_allocator() const; bool empty() const; size_type size() const; size_type max_size() const; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; iterator insert(const value_type& obj); template void insert(InputIterator first, InputIterator last); void erase(const_iterator position); size_type erase(const key_type& k); void erase(const_iterator first, const_iterator last); void clear(); void swap(hash_multimap&); hasher hash_funct() const; key_equal key_eq() const; iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; size_type bucket_count() const; size_type max_bucket_count() const; size_type elems_in_bucket(size_type n) const; void resize(size_type n); }; template void swap(hash_multimap& x, hash_multimap& y); template bool operator==(const hash_multimap& x, const hash_multimap& y); template bool operator!=(const hash_multimap& x, const hash_multimap& y); } // __gnu_cxx */ #include <__config> #include <__hash_table> #include #include #warning Use of the header is deprecated. Migrate to #pragma GCC system_header namespace __gnu_cxx { using namespace std; template ::value> class __hash_map_hasher : private _Hash { public: __hash_map_hasher() : _Hash() {} __hash_map_hasher(const _Hash& __h) : _Hash(__h) {} const _Hash& hash_function() const {return *this;} size_t operator()(const _Tp& __x) const {return static_cast(*this)(__x.first);} size_t operator()(const typename _Tp::first_type& __x) const {return static_cast(*this)(__x);} }; template class __hash_map_hasher<_Tp, _Hash, false> { _Hash __hash_; public: __hash_map_hasher() : __hash_() {} __hash_map_hasher(const _Hash& __h) : __hash_(__h) {} const _Hash& hash_function() const {return __hash_;} size_t operator()(const _Tp& __x) const {return __hash_(__x.first);} size_t operator()(const typename _Tp::first_type& __x) const {return __hash_(__x);} }; template ::value> class __hash_map_equal : private _Pred { public: __hash_map_equal() : _Pred() {} __hash_map_equal(const _Pred& __p) : _Pred(__p) {} const _Pred& key_eq() const {return *this;} bool operator()(const _Tp& __x, const _Tp& __y) const {return static_cast(*this)(__x.first, __y.first);} bool operator()(const typename _Tp::first_type& __x, const _Tp& __y) const {return static_cast(*this)(__x, __y.first);} bool operator()(const _Tp& __x, const typename _Tp::first_type& __y) const {return static_cast(*this)(__x.first, __y);} bool operator()(const typename _Tp::first_type& __x, const typename _Tp::first_type& __y) const {return static_cast(*this)(__x, __y);} }; template class __hash_map_equal<_Tp, _Pred, false> { _Pred __pred_; public: __hash_map_equal() : __pred_() {} __hash_map_equal(const _Pred& __p) : __pred_(__p) {} const _Pred& key_eq() const {return __pred_;} bool operator()(const _Tp& __x, const _Tp& __y) const {return __pred_(__x.first, __y.first);} bool operator()(const typename _Tp::first_type& __x, const _Tp& __y) const {return __pred_(__x, __y.first);} bool operator()(const _Tp& __x, const typename _Tp::first_type& __y) const {return __pred_(__x.first, __y);} bool operator()(const typename _Tp::first_type& __x, const typename _Tp::first_type& __y) const {return __pred_(__x, __y);} }; template class __hash_map_node_destructor { typedef _Alloc allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::value_type::value_type value_type; public: typedef typename __alloc_traits::pointer pointer; private: typedef typename value_type::first_type first_type; typedef typename value_type::second_type second_type; allocator_type& __na_; __hash_map_node_destructor& operator=(const __hash_map_node_destructor&); public: bool __first_constructed; bool __second_constructed; explicit __hash_map_node_destructor(allocator_type& __na) : __na_(__na), __first_constructed(false), __second_constructed(false) {} #ifdef _LIBCPP_MOVE __hash_map_node_destructor(__hash_node_destructor&& __x) : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { __x.__value_constructed = false; } #else __hash_map_node_destructor(const __hash_node_destructor& __x) : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { const_cast(__x.__value_constructed) = false; } #endif void operator()(pointer __p) { if (__second_constructed) __alloc_traits::destroy(__na_, addressof(__p->__value_.second)); if (__first_constructed) __alloc_traits::destroy(__na_, addressof(__p->__value_.first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } }; template class __hash_map_iterator { _HashIterator __i_; typedef pointer_traits __pointer_traits; typedef const typename _HashIterator::value_type::first_type key_type; typedef typename _HashIterator::value_type::second_type mapped_type; public: typedef forward_iterator_tag iterator_category; typedef pair value_type; typedef typename _HashIterator::difference_type difference_type; typedef value_type& reference; typedef typename __pointer_traits::template #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES rebind #else rebind::other #endif pointer; __hash_map_iterator() {} __hash_map_iterator(_HashIterator __i) : __i_(__i) {} reference operator*() const {return *operator->();} pointer operator->() const {return (pointer)__i_.operator->();} __hash_map_iterator& operator++() {++__i_; return *this;} __hash_map_iterator operator++(int) { __hash_map_iterator __t(*this); ++(*this); return __t; } friend bool operator==(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ == __y.__i_;} friend bool operator!=(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class hash_map; template friend class hash_multimap; template friend class __hash_const_iterator; template friend class __hash_const_local_iterator; template friend class __hash_map_const_iterator; }; template class __hash_map_const_iterator { _HashIterator __i_; typedef pointer_traits __pointer_traits; typedef const typename _HashIterator::value_type::first_type key_type; typedef typename _HashIterator::value_type::second_type mapped_type; public: typedef forward_iterator_tag iterator_category; typedef pair value_type; typedef typename _HashIterator::difference_type difference_type; typedef const value_type& reference; typedef typename __pointer_traits::template #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES rebind #else rebind::other #endif pointer; __hash_map_const_iterator() {} __hash_map_const_iterator(_HashIterator __i) : __i_(__i) {} __hash_map_const_iterator( __hash_map_iterator __i) : __i_(__i.__i_) {} reference operator*() const {return *operator->();} pointer operator->() const {return (pointer)__i_.operator->();} __hash_map_const_iterator& operator++() {++__i_; return *this;} __hash_map_const_iterator operator++(int) { __hash_map_const_iterator __t(*this); ++(*this); return __t; } friend bool operator==(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ == __y.__i_;} friend bool operator!=(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class hash_map; template friend class hash_multimap; template friend class __hash_const_iterator; template friend class __hash_const_local_iterator; }; template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > class hash_map { public: // types typedef _Key key_type; typedef _Tp mapped_type; typedef _Hash hasher; typedef _Pred key_equal; typedef _Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; private: typedef pair __value_type; typedef __hash_map_hasher<__value_type, hasher> __hasher; typedef __hash_map_equal<__value_type, key_equal> __key_equal; typedef typename allocator_traits::template #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES rebind_alloc<__value_type> #else rebind_alloc<__value_type>::other #endif __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; __table __table_; typedef typename __table::__node_pointer __node_pointer; typedef typename __table::__node_const_pointer __node_const_pointer; typedef typename __table::__node_traits __node_traits; typedef typename __table::__node_allocator __node_allocator; typedef typename __table::__node __node; typedef __hash_map_node_destructor<__node_allocator> _D; typedef unique_ptr<__node, _D> __node_holder; typedef allocator_traits __alloc_traits; public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef __hash_map_iterator iterator; typedef __hash_map_const_iterator const_iterator; hash_map() {__table_.rehash(193);} explicit hash_map(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template hash_map(_InputIterator __first, _InputIterator __last); template hash_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template hash_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); hash_map(const hash_map& __u); allocator_type get_allocator() const {return allocator_type(__table_.__node_alloc());} bool empty() const {return __table_.size() == 0;} size_type size() const {return __table_.size();} size_type max_size() const {return __table_.max_size();} iterator begin() {return __table_.begin();} iterator end() {return __table_.end();} const_iterator begin() const {return __table_.begin();} const_iterator end() const {return __table_.end();} pair insert(const value_type& __x) {return __table_.__insert_unique(__x);} template void insert(_InputIterator __first, _InputIterator __last); void erase(const_iterator __p) {__table_.erase(__p.__i_);} size_type erase(const key_type& __k) {return __table_.__erase_unique(__k);} void erase(const_iterator __first, const_iterator __last) {__table_.erase(__first.__i_, __last.__i_);} void clear() {__table_.clear();} void swap(hash_map& __u) {__table_.swap(__u.__table_);} hasher hash_funct() const {return __table_.hash_function().hash_function();} key_equal key_eq() const {return __table_.key_eq().key_eq();} iterator find(const key_type& __k) {return __table_.find(__k);} const_iterator find(const key_type& __k) const {return __table_.find(__k);} size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} pair equal_range(const key_type& __k) {return __table_.__equal_range_unique(__k);} pair equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} mapped_type& operator[](const key_type& __k); size_type bucket_count() const {return __table_.bucket_count();} size_type max_bucket_count() const {return __table_.max_bucket_count();} size_type elems_in_bucket(size_type __n) const {return __table_.bucket_size(__n);} void resize(size_type __n) {__table_.rehash(__n);} private: __node_holder __construct_node(const key_type& __k); }; template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { __table_.rehash(__n); } template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { __table_.rehash(__n); } template template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( _InputIterator __first, _InputIterator __last) { __table_.rehash(193); insert(__first, __last); } template template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { __table_.rehash(__n); insert(__first, __last); } template template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { __table_.rehash(__n); insert(__first, __last); } template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( const hash_map& __u) : __table_(__u.__table_) { __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } template typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(const key_type& __k) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _D(__na)); __node_traits::construct(__na, addressof(__h->__value_.first), __k); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, addressof(__h->__value_.second)); __h.get_deleter().__second_constructed = true; return _STD::move(__h); } template template inline void hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) __table_.__insert_unique(*__first); } template _Tp& hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k) { iterator __i = find(__k); if (__i != end()) return __i->second; __node_holder __h = __construct_node(__k); pair __r = __table_.__node_insert_unique(__h.get()); __h.release(); return __r.first->second; } template inline void swap(hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { __x.swap(__y); } template bool operator==(const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { if (__x.size() != __y.size()) return false; typedef typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator; for (const_iterator __i = __x.begin(), __ex = __x.end(), __ey = __y.end(); __i != __ex; ++__i) { const_iterator __j = __y.find(__i->first); if (__j == __ey || !(*__i == *__j)) return false; } return true; } template inline bool operator!=(const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { return !(__x == __y); } template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > class hash_multimap { public: // types typedef _Key key_type; typedef _Tp mapped_type; typedef _Hash hasher; typedef _Pred key_equal; typedef _Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; private: typedef pair __value_type; typedef __hash_map_hasher<__value_type, hasher> __hasher; typedef __hash_map_equal<__value_type, key_equal> __key_equal; typedef typename allocator_traits::template #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES rebind_alloc<__value_type> #else rebind_alloc<__value_type>::other #endif __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; __table __table_; typedef typename __table::__node_traits __node_traits; typedef typename __table::__node_allocator __node_allocator; typedef typename __table::__node __node; typedef __hash_map_node_destructor<__node_allocator> _D; typedef unique_ptr<__node, _D> __node_holder; typedef allocator_traits __alloc_traits; public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef __hash_map_iterator iterator; typedef __hash_map_const_iterator const_iterator; hash_multimap() {__table_.rehash(193);} explicit hash_multimap(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template hash_multimap(_InputIterator __first, _InputIterator __last); template hash_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template hash_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); hash_multimap(const hash_multimap& __u); allocator_type get_allocator() const {return allocator_type(__table_.__node_alloc());} bool empty() const {return __table_.size() == 0;} size_type size() const {return __table_.size();} size_type max_size() const {return __table_.max_size();} iterator begin() {return __table_.begin();} iterator end() {return __table_.end();} const_iterator begin() const {return __table_.begin();} const_iterator end() const {return __table_.end();} iterator insert(const value_type& __x) {return __table_.__insert_multi(__x);} template void insert(_InputIterator __first, _InputIterator __last); void erase(const_iterator __p) {__table_.erase(__p.__i_);} size_type erase(const key_type& __k) {return __table_.__erase_multi(__k);} void erase(const_iterator __first, const_iterator __last) {__table_.erase(__first.__i_, __last.__i_);} void clear() {__table_.clear();} void swap(hash_multimap& __u) {__table_.swap(__u.__table_);} hasher hash_funct() const {return __table_.hash_function().hash_function();} key_equal key_eq() const {return __table_.key_eq().key_eq();} iterator find(const key_type& __k) {return __table_.find(__k);} const_iterator find(const key_type& __k) const {return __table_.find(__k);} size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} pair equal_range(const key_type& __k) {return __table_.__equal_range_multi(__k);} pair equal_range(const key_type& __k) const {return __table_.__equal_range_multi(__k);} size_type bucket_count() const {return __table_.bucket_count();} size_type max_bucket_count() const {return __table_.max_bucket_count();} size_type elems_in_bucket(size_type __n) const {return __table_.bucket_size(__n);} void resize(size_type __n) {__table_.rehash(__n);} }; template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { __table_.rehash(__n); } template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { __table_.rehash(__n); } template template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( _InputIterator __first, _InputIterator __last) { __table_.rehash(193); insert(__first, __last); } template template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { __table_.rehash(__n); insert(__first, __last); } template template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { __table_.rehash(__n); insert(__first, __last); } template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( const hash_multimap& __u) : __table_(__u.__table_) { __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } template template inline void hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) __table_.__insert_multi(*__first); } template inline void swap(hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { __x.swap(__y); } template bool operator==(const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { if (__x.size() != __y.size()) return false; typedef typename hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator; typedef pair _EqRng; for (const_iterator __i = __x.begin(), __ex = __x.end(); __i != __ex;) { _EqRng __xeq = __x.equal_range(__i->first); _EqRng __yeq = __y.equal_range(__i->first); if (_STD::distance(__xeq.first, __xeq.second) != _STD::distance(__yeq.first, __yeq.second) || !_STD::is_permutation(__xeq.first, __xeq.second, __yeq.first)) return false; __i = __xeq.second; } return true; } template inline bool operator!=(const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { return !(__x == __y); } } // __gnu_cxx #endif // _LIBCPP_HASH_MAP