1e4b17023SJohn Marino// Debugging unordered_map/unordered_multimap implementation -*- C++ -*- 2e4b17023SJohn Marino 3*5ce9237cSJohn Marino// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 4e4b17023SJohn Marino// Free Software Foundation, Inc. 5e4b17023SJohn Marino// 6e4b17023SJohn Marino// This file is part of the GNU ISO C++ Library. This library is free 7e4b17023SJohn Marino// software; you can redistribute it and/or modify it under the 8e4b17023SJohn Marino// terms of the GNU General Public License as published by the 9e4b17023SJohn Marino// Free Software Foundation; either version 3, or (at your option) 10e4b17023SJohn Marino// any later version. 11e4b17023SJohn Marino 12e4b17023SJohn Marino// This library is distributed in the hope that it will be useful, 13e4b17023SJohn Marino// but WITHOUT ANY WARRANTY; without even the implied warranty of 14e4b17023SJohn Marino// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15e4b17023SJohn Marino// GNU General Public License for more details. 16e4b17023SJohn Marino 17e4b17023SJohn Marino// Under Section 7 of GPL version 3, you are granted additional 18e4b17023SJohn Marino// permissions described in the GCC Runtime Library Exception, version 19e4b17023SJohn Marino// 3.1, as published by the Free Software Foundation. 20e4b17023SJohn Marino 21e4b17023SJohn Marino// You should have received a copy of the GNU General Public License and 22e4b17023SJohn Marino// a copy of the GCC Runtime Library Exception along with this program; 23e4b17023SJohn Marino// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24e4b17023SJohn Marino// <http://www.gnu.org/licenses/>. 25e4b17023SJohn Marino 26e4b17023SJohn Marino/** @file debug/unordered_map 27e4b17023SJohn Marino * This file is a GNU debug extension to the Standard C++ Library. 28e4b17023SJohn Marino */ 29e4b17023SJohn Marino 30e4b17023SJohn Marino#ifndef _GLIBCXX_DEBUG_UNORDERED_MAP 31e4b17023SJohn Marino#define _GLIBCXX_DEBUG_UNORDERED_MAP 1 32e4b17023SJohn Marino 33e4b17023SJohn Marino#ifndef __GXX_EXPERIMENTAL_CXX0X__ 34e4b17023SJohn Marino# include <bits/c++0x_warning.h> 35e4b17023SJohn Marino#else 36e4b17023SJohn Marino# include <unordered_map> 37e4b17023SJohn Marino 38e4b17023SJohn Marino#include <debug/safe_unordered_container.h> 39e4b17023SJohn Marino#include <debug/safe_iterator.h> 40e4b17023SJohn Marino#include <debug/safe_local_iterator.h> 41e4b17023SJohn Marino 42e4b17023SJohn Marinonamespace std _GLIBCXX_VISIBILITY(default) 43e4b17023SJohn Marino{ 44e4b17023SJohn Marinonamespace __debug 45e4b17023SJohn Marino{ 46e4b17023SJohn Marino /// Class std::unordered_map with safety/checking/debug instrumentation. 47e4b17023SJohn Marino template<typename _Key, typename _Tp, 48e4b17023SJohn Marino typename _Hash = std::hash<_Key>, 49e4b17023SJohn Marino typename _Pred = std::equal_to<_Key>, 50e4b17023SJohn Marino typename _Alloc = std::allocator<_Key> > 51e4b17023SJohn Marino class unordered_map 52e4b17023SJohn Marino : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, 53e4b17023SJohn Marino public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp, 54e4b17023SJohn Marino _Hash, _Pred, _Alloc> > 55e4b17023SJohn Marino { 56e4b17023SJohn Marino typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, 57e4b17023SJohn Marino _Pred, _Alloc> _Base; 58e4b17023SJohn Marino typedef __gnu_debug::_Safe_unordered_container<unordered_map> _Safe_base; 59e4b17023SJohn Marino typedef typename _Base::const_iterator _Base_const_iterator; 60e4b17023SJohn Marino typedef typename _Base::iterator _Base_iterator; 61e4b17023SJohn Marino typedef typename _Base::const_local_iterator _Base_const_local_iterator; 62e4b17023SJohn Marino typedef typename _Base::local_iterator _Base_local_iterator; 63e4b17023SJohn Marino 64e4b17023SJohn Marino public: 65e4b17023SJohn Marino typedef typename _Base::size_type size_type; 66e4b17023SJohn Marino typedef typename _Base::hasher hasher; 67e4b17023SJohn Marino typedef typename _Base::key_equal key_equal; 68e4b17023SJohn Marino typedef typename _Base::allocator_type allocator_type; 69e4b17023SJohn Marino 70e4b17023SJohn Marino typedef typename _Base::key_type key_type; 71e4b17023SJohn Marino typedef typename _Base::value_type value_type; 72e4b17023SJohn Marino 73e4b17023SJohn Marino typedef __gnu_debug::_Safe_iterator<_Base_iterator, 74e4b17023SJohn Marino unordered_map> iterator; 75e4b17023SJohn Marino typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, 76e4b17023SJohn Marino unordered_map> const_iterator; 77e4b17023SJohn Marino typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator, 78e4b17023SJohn Marino unordered_map> local_iterator; 79e4b17023SJohn Marino typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator, 80e4b17023SJohn Marino unordered_map> const_local_iterator; 81e4b17023SJohn Marino 82e4b17023SJohn Marino explicit 83e4b17023SJohn Marino unordered_map(size_type __n = 10, 84e4b17023SJohn Marino const hasher& __hf = hasher(), 85e4b17023SJohn Marino const key_equal& __eql = key_equal(), 86e4b17023SJohn Marino const allocator_type& __a = allocator_type()) 87e4b17023SJohn Marino : _Base(__n, __hf, __eql, __a) { } 88e4b17023SJohn Marino 89e4b17023SJohn Marino template<typename _InputIterator> 90e4b17023SJohn Marino unordered_map(_InputIterator __first, _InputIterator __last, 91e4b17023SJohn Marino size_type __n = 0, 92e4b17023SJohn Marino const hasher& __hf = hasher(), 93e4b17023SJohn Marino const key_equal& __eql = key_equal(), 94e4b17023SJohn Marino const allocator_type& __a = allocator_type()) 95e4b17023SJohn Marino : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 96e4b17023SJohn Marino __last)), 97e4b17023SJohn Marino __gnu_debug::__base(__last), __n, 98e4b17023SJohn Marino __hf, __eql, __a) { } 99e4b17023SJohn Marino 100*5ce9237cSJohn Marino unordered_map(const unordered_map& __x) = default; 101e4b17023SJohn Marino 102e4b17023SJohn Marino unordered_map(const _Base& __x) 103e4b17023SJohn Marino : _Base(__x) { } 104e4b17023SJohn Marino 105*5ce9237cSJohn Marino unordered_map(unordered_map&& __x) = default; 106e4b17023SJohn Marino 107e4b17023SJohn Marino unordered_map(initializer_list<value_type> __l, 108e4b17023SJohn Marino size_type __n = 0, 109e4b17023SJohn Marino const hasher& __hf = hasher(), 110e4b17023SJohn Marino const key_equal& __eql = key_equal(), 111e4b17023SJohn Marino const allocator_type& __a = allocator_type()) 112e4b17023SJohn Marino : _Base(__l, __n, __hf, __eql, __a) { } 113e4b17023SJohn Marino 114e4b17023SJohn Marino ~unordered_map() noexcept { } 115e4b17023SJohn Marino 116e4b17023SJohn Marino unordered_map& 117e4b17023SJohn Marino operator=(const unordered_map& __x) 118e4b17023SJohn Marino { 119e4b17023SJohn Marino *static_cast<_Base*>(this) = __x; 120e4b17023SJohn Marino this->_M_invalidate_all(); 121e4b17023SJohn Marino return *this; 122e4b17023SJohn Marino } 123e4b17023SJohn Marino 124e4b17023SJohn Marino unordered_map& 125e4b17023SJohn Marino operator=(unordered_map&& __x) 126e4b17023SJohn Marino { 127e4b17023SJohn Marino // NB: DR 1204. 128e4b17023SJohn Marino // NB: DR 675. 129e4b17023SJohn Marino clear(); 130e4b17023SJohn Marino swap(__x); 131e4b17023SJohn Marino return *this; 132e4b17023SJohn Marino } 133e4b17023SJohn Marino 134e4b17023SJohn Marino unordered_map& 135e4b17023SJohn Marino operator=(initializer_list<value_type> __l) 136e4b17023SJohn Marino { 137e4b17023SJohn Marino this->clear(); 138e4b17023SJohn Marino this->insert(__l); 139e4b17023SJohn Marino return *this; 140e4b17023SJohn Marino } 141e4b17023SJohn Marino 142e4b17023SJohn Marino void 143e4b17023SJohn Marino swap(unordered_map& __x) 144e4b17023SJohn Marino { 145e4b17023SJohn Marino _Base::swap(__x); 146e4b17023SJohn Marino _Safe_base::_M_swap(__x); 147e4b17023SJohn Marino } 148e4b17023SJohn Marino 149e4b17023SJohn Marino void 150e4b17023SJohn Marino clear() noexcept 151e4b17023SJohn Marino { 152e4b17023SJohn Marino _Base::clear(); 153e4b17023SJohn Marino this->_M_invalidate_all(); 154e4b17023SJohn Marino } 155e4b17023SJohn Marino 156e4b17023SJohn Marino iterator 157e4b17023SJohn Marino begin() noexcept 158e4b17023SJohn Marino { return iterator(_Base::begin(), this); } 159e4b17023SJohn Marino 160e4b17023SJohn Marino const_iterator 161e4b17023SJohn Marino begin() const noexcept 162e4b17023SJohn Marino { return const_iterator(_Base::begin(), this); } 163e4b17023SJohn Marino 164e4b17023SJohn Marino iterator 165e4b17023SJohn Marino end() noexcept 166e4b17023SJohn Marino { return iterator(_Base::end(), this); } 167e4b17023SJohn Marino 168e4b17023SJohn Marino const_iterator 169e4b17023SJohn Marino end() const noexcept 170e4b17023SJohn Marino { return const_iterator(_Base::end(), this); } 171e4b17023SJohn Marino 172e4b17023SJohn Marino const_iterator 173e4b17023SJohn Marino cbegin() const noexcept 174e4b17023SJohn Marino { return const_iterator(_Base::begin(), this); } 175e4b17023SJohn Marino 176e4b17023SJohn Marino const_iterator 177e4b17023SJohn Marino cend() const noexcept 178e4b17023SJohn Marino { return const_iterator(_Base::end(), this); } 179e4b17023SJohn Marino 180e4b17023SJohn Marino // local versions 181e4b17023SJohn Marino local_iterator 182e4b17023SJohn Marino begin(size_type __b) 183e4b17023SJohn Marino { return local_iterator(_Base::begin(__b), __b, this); } 184e4b17023SJohn Marino 185e4b17023SJohn Marino local_iterator 186e4b17023SJohn Marino end(size_type __b) 187e4b17023SJohn Marino { return local_iterator(_Base::end(__b), __b, this); } 188e4b17023SJohn Marino 189e4b17023SJohn Marino const_local_iterator 190e4b17023SJohn Marino begin(size_type __b) const 191e4b17023SJohn Marino { return const_local_iterator(_Base::begin(__b), __b, this); } 192e4b17023SJohn Marino 193e4b17023SJohn Marino const_local_iterator 194e4b17023SJohn Marino end(size_type __b) const 195e4b17023SJohn Marino { return const_local_iterator(_Base::end(__b), __b, this); } 196e4b17023SJohn Marino 197e4b17023SJohn Marino const_local_iterator 198e4b17023SJohn Marino cbegin(size_type __b) const 199e4b17023SJohn Marino { return const_local_iterator(_Base::cbegin(__b), __b, this); } 200e4b17023SJohn Marino 201e4b17023SJohn Marino const_local_iterator 202e4b17023SJohn Marino cend(size_type __b) const 203e4b17023SJohn Marino { return const_local_iterator(_Base::cend(__b), __b, this); } 204e4b17023SJohn Marino 205e4b17023SJohn Marino template<typename... _Args> 206e4b17023SJohn Marino std::pair<iterator, bool> 207e4b17023SJohn Marino emplace(_Args&&... __args) 208e4b17023SJohn Marino { 209e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 210e4b17023SJohn Marino std::pair<_Base_iterator, bool> __res 211e4b17023SJohn Marino = _Base::emplace(std::forward<_Args>(__args)...); 212e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 213e4b17023SJohn Marino return std::make_pair(iterator(__res.first, this), __res.second); 214e4b17023SJohn Marino } 215e4b17023SJohn Marino 216e4b17023SJohn Marino template<typename... _Args> 217e4b17023SJohn Marino iterator 218e4b17023SJohn Marino emplace_hint(const_iterator __hint, _Args&&... __args) 219e4b17023SJohn Marino { 220e4b17023SJohn Marino __glibcxx_check_insert(__hint); 221e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 222e4b17023SJohn Marino _Base_iterator __it = _Base::emplace_hint(__hint.base(), 223e4b17023SJohn Marino std::forward<_Args>(__args)...); 224e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 225e4b17023SJohn Marino return iterator(__it, this); 226e4b17023SJohn Marino } 227e4b17023SJohn Marino 228e4b17023SJohn Marino std::pair<iterator, bool> 229e4b17023SJohn Marino insert(const value_type& __obj) 230e4b17023SJohn Marino { 231e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 232e4b17023SJohn Marino std::pair<_Base_iterator, bool> __res = _Base::insert(__obj); 233e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 234e4b17023SJohn Marino return std::make_pair(iterator(__res.first, this), __res.second); 235e4b17023SJohn Marino } 236e4b17023SJohn Marino 237e4b17023SJohn Marino iterator 238e4b17023SJohn Marino insert(const_iterator __hint, const value_type& __obj) 239e4b17023SJohn Marino { 240e4b17023SJohn Marino __glibcxx_check_insert(__hint); 241e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 242e4b17023SJohn Marino _Base_iterator __it = _Base::insert(__hint.base(), __obj); 243e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 244e4b17023SJohn Marino return iterator(__it, this); 245e4b17023SJohn Marino } 246e4b17023SJohn Marino 247e4b17023SJohn Marino template<typename _Pair, typename = typename 248e4b17023SJohn Marino std::enable_if<std::is_constructible<value_type, 249e4b17023SJohn Marino _Pair&&>::value>::type> 250e4b17023SJohn Marino std::pair<iterator, bool> 251e4b17023SJohn Marino insert(_Pair&& __obj) 252e4b17023SJohn Marino { 253e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 254e4b17023SJohn Marino std::pair<_Base_iterator, bool> __res = 255e4b17023SJohn Marino _Base::insert(std::forward<_Pair>(__obj)); 256e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 257e4b17023SJohn Marino return std::make_pair(iterator(__res.first, this), __res.second); 258e4b17023SJohn Marino } 259e4b17023SJohn Marino 260e4b17023SJohn Marino template<typename _Pair, typename = typename 261e4b17023SJohn Marino std::enable_if<std::is_constructible<value_type, 262e4b17023SJohn Marino _Pair&&>::value>::type> 263e4b17023SJohn Marino iterator 264e4b17023SJohn Marino insert(const_iterator __hint, _Pair&& __obj) 265e4b17023SJohn Marino { 266e4b17023SJohn Marino __glibcxx_check_insert(__hint); 267e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 268e4b17023SJohn Marino _Base_iterator __it = 269e4b17023SJohn Marino _Base::insert(__hint.base(), std::forward<_Pair>(__obj)); 270e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 271e4b17023SJohn Marino return iterator(__it, this); 272e4b17023SJohn Marino } 273e4b17023SJohn Marino 274e4b17023SJohn Marino void 275e4b17023SJohn Marino insert(std::initializer_list<value_type> __l) 276e4b17023SJohn Marino { 277e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 278e4b17023SJohn Marino _Base::insert(__l); 279e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 280e4b17023SJohn Marino } 281e4b17023SJohn Marino 282e4b17023SJohn Marino template<typename _InputIterator> 283e4b17023SJohn Marino void 284e4b17023SJohn Marino insert(_InputIterator __first, _InputIterator __last) 285e4b17023SJohn Marino { 286e4b17023SJohn Marino __glibcxx_check_valid_range(__first, __last); 287e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 288e4b17023SJohn Marino _Base::insert(__gnu_debug::__base(__first), 289e4b17023SJohn Marino __gnu_debug::__base(__last)); 290e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 291e4b17023SJohn Marino } 292e4b17023SJohn Marino 293e4b17023SJohn Marino iterator 294e4b17023SJohn Marino find(const key_type& __key) 295e4b17023SJohn Marino { return iterator(_Base::find(__key), this); } 296e4b17023SJohn Marino 297e4b17023SJohn Marino const_iterator 298e4b17023SJohn Marino find(const key_type& __key) const 299e4b17023SJohn Marino { return const_iterator(_Base::find(__key), this); } 300e4b17023SJohn Marino 301e4b17023SJohn Marino std::pair<iterator, iterator> 302e4b17023SJohn Marino equal_range(const key_type& __key) 303e4b17023SJohn Marino { 304e4b17023SJohn Marino std::pair<_Base_iterator, _Base_iterator> __res = 305e4b17023SJohn Marino _Base::equal_range(__key); 306e4b17023SJohn Marino return std::make_pair(iterator(__res.first, this), 307e4b17023SJohn Marino iterator(__res.second, this)); 308e4b17023SJohn Marino } 309e4b17023SJohn Marino 310e4b17023SJohn Marino std::pair<const_iterator, const_iterator> 311e4b17023SJohn Marino equal_range(const key_type& __key) const 312e4b17023SJohn Marino { 313e4b17023SJohn Marino std::pair<_Base_const_iterator, _Base_const_iterator> __res = 314e4b17023SJohn Marino _Base::equal_range(__key); 315e4b17023SJohn Marino return std::make_pair(const_iterator(__res.first, this), 316e4b17023SJohn Marino const_iterator(__res.second, this)); 317e4b17023SJohn Marino } 318e4b17023SJohn Marino 319e4b17023SJohn Marino size_type 320e4b17023SJohn Marino erase(const key_type& __key) 321e4b17023SJohn Marino { 322e4b17023SJohn Marino size_type __ret(0); 323e4b17023SJohn Marino _Base_iterator __victim(_Base::find(__key)); 324e4b17023SJohn Marino if (__victim != _Base::end()) 325e4b17023SJohn Marino { 326e4b17023SJohn Marino this->_M_invalidate_if([__victim](_Base_const_iterator __it) 327e4b17023SJohn Marino { return __it == __victim; }); 328e4b17023SJohn Marino _Base_local_iterator __local_victim = _S_to_local(__victim); 329e4b17023SJohn Marino this->_M_invalidate_local_if( 330e4b17023SJohn Marino [__local_victim](_Base_const_local_iterator __it) 331e4b17023SJohn Marino { return __it == __local_victim; }); 332e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 333e4b17023SJohn Marino _Base::erase(__victim); 334e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 335e4b17023SJohn Marino __ret = 1; 336e4b17023SJohn Marino } 337e4b17023SJohn Marino return __ret; 338e4b17023SJohn Marino } 339e4b17023SJohn Marino 340e4b17023SJohn Marino iterator 341e4b17023SJohn Marino erase(const_iterator __it) 342e4b17023SJohn Marino { 343e4b17023SJohn Marino __glibcxx_check_erase(__it); 344e4b17023SJohn Marino _Base_const_iterator __victim = __it.base(); 345e4b17023SJohn Marino this->_M_invalidate_if([__victim](_Base_const_iterator __it) 346e4b17023SJohn Marino { return __it == __victim; }); 347e4b17023SJohn Marino _Base_const_local_iterator __local_victim = _S_to_local(__victim); 348e4b17023SJohn Marino this->_M_invalidate_local_if( 349e4b17023SJohn Marino [__local_victim](_Base_const_local_iterator __it) 350e4b17023SJohn Marino { return __it == __local_victim; }); 351e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 352e4b17023SJohn Marino _Base_iterator __next = _Base::erase(__it.base()); 353e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 354e4b17023SJohn Marino return iterator(__next, this); 355e4b17023SJohn Marino } 356e4b17023SJohn Marino 357e4b17023SJohn Marino iterator 358e4b17023SJohn Marino erase(iterator __it) 359e4b17023SJohn Marino { return erase(const_iterator(__it)); } 360e4b17023SJohn Marino 361e4b17023SJohn Marino iterator 362e4b17023SJohn Marino erase(const_iterator __first, const_iterator __last) 363e4b17023SJohn Marino { 364e4b17023SJohn Marino __glibcxx_check_erase_range(__first, __last); 365e4b17023SJohn Marino for (_Base_const_iterator __tmp = __first.base(); 366e4b17023SJohn Marino __tmp != __last.base(); ++__tmp) 367e4b17023SJohn Marino { 368e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 369e4b17023SJohn Marino _M_message(__gnu_debug::__msg_valid_range) 370e4b17023SJohn Marino ._M_iterator(__first, "first") 371e4b17023SJohn Marino ._M_iterator(__last, "last")); 372e4b17023SJohn Marino this->_M_invalidate_if([__tmp](_Base_const_iterator __it) 373e4b17023SJohn Marino { return __it == __tmp; }); 374e4b17023SJohn Marino _Base_const_local_iterator __local_tmp = _S_to_local(__tmp); 375e4b17023SJohn Marino this->_M_invalidate_local_if( 376e4b17023SJohn Marino [__local_tmp](_Base_const_local_iterator __it) 377e4b17023SJohn Marino { return __it == __local_tmp; }); 378e4b17023SJohn Marino } 379e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 380e4b17023SJohn Marino _Base_iterator __next = _Base::erase(__first.base(), __last.base()); 381e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 382e4b17023SJohn Marino return iterator(__next, this); 383e4b17023SJohn Marino } 384e4b17023SJohn Marino 385e4b17023SJohn Marino _Base& 386e4b17023SJohn Marino _M_base() noexcept { return *this; } 387e4b17023SJohn Marino 388e4b17023SJohn Marino const _Base& 389e4b17023SJohn Marino _M_base() const noexcept { return *this; } 390e4b17023SJohn Marino 391e4b17023SJohn Marino private: 392e4b17023SJohn Marino void 393e4b17023SJohn Marino _M_invalidate_locals() 394e4b17023SJohn Marino { 395e4b17023SJohn Marino _Base_local_iterator __local_end = _Base::end(0); 396e4b17023SJohn Marino this->_M_invalidate_local_if( 397e4b17023SJohn Marino [__local_end](_Base_const_local_iterator __it) 398e4b17023SJohn Marino { return __it != __local_end; }); 399e4b17023SJohn Marino } 400e4b17023SJohn Marino 401e4b17023SJohn Marino void 402e4b17023SJohn Marino _M_invalidate_all() 403e4b17023SJohn Marino { 404e4b17023SJohn Marino _Base_iterator __end = _Base::end(); 405e4b17023SJohn Marino this->_M_invalidate_if([__end](_Base_const_iterator __it) 406e4b17023SJohn Marino { return __it != __end; }); 407e4b17023SJohn Marino _M_invalidate_locals(); 408e4b17023SJohn Marino } 409e4b17023SJohn Marino 410e4b17023SJohn Marino void 411e4b17023SJohn Marino _M_check_rehashed(size_type __prev_count) 412e4b17023SJohn Marino { 413e4b17023SJohn Marino if (__prev_count != this->bucket_count()) 414e4b17023SJohn Marino _M_invalidate_locals(); 415e4b17023SJohn Marino } 416e4b17023SJohn Marino 417e4b17023SJohn Marino static _Base_local_iterator 418e4b17023SJohn Marino _S_to_local(_Base_iterator __it) 419e4b17023SJohn Marino { 420e4b17023SJohn Marino // The returned local iterator will not be incremented so we don't 421e4b17023SJohn Marino // need to compute __it's node bucket 422e4b17023SJohn Marino return _Base_local_iterator(__it._M_cur, 0, 0); 423e4b17023SJohn Marino } 424e4b17023SJohn Marino 425e4b17023SJohn Marino static _Base_const_local_iterator 426e4b17023SJohn Marino _S_to_local(_Base_const_iterator __it) 427e4b17023SJohn Marino { 428e4b17023SJohn Marino // The returned local iterator will not be incremented so we don't 429e4b17023SJohn Marino // need to compute __it's node bucket 430e4b17023SJohn Marino return _Base_const_local_iterator(__it._M_cur, 0, 0); 431e4b17023SJohn Marino } 432e4b17023SJohn Marino }; 433e4b17023SJohn Marino 434e4b17023SJohn Marino template<typename _Key, typename _Tp, typename _Hash, 435e4b17023SJohn Marino typename _Pred, typename _Alloc> 436e4b17023SJohn Marino inline void 437e4b17023SJohn Marino swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 438e4b17023SJohn Marino unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 439e4b17023SJohn Marino { __x.swap(__y); } 440e4b17023SJohn Marino 441e4b17023SJohn Marino template<typename _Key, typename _Tp, typename _Hash, 442e4b17023SJohn Marino typename _Pred, typename _Alloc> 443e4b17023SJohn Marino inline bool 444e4b17023SJohn Marino operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 445e4b17023SJohn Marino const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 446e4b17023SJohn Marino { return __x._M_equal(__y); } 447e4b17023SJohn Marino 448e4b17023SJohn Marino template<typename _Key, typename _Tp, typename _Hash, 449e4b17023SJohn Marino typename _Pred, typename _Alloc> 450e4b17023SJohn Marino inline bool 451e4b17023SJohn Marino operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 452e4b17023SJohn Marino const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 453e4b17023SJohn Marino { return !(__x == __y); } 454e4b17023SJohn Marino 455e4b17023SJohn Marino 456e4b17023SJohn Marino /// Class std::unordered_multimap with safety/checking/debug instrumentation. 457e4b17023SJohn Marino template<typename _Key, typename _Tp, 458e4b17023SJohn Marino typename _Hash = std::hash<_Key>, 459e4b17023SJohn Marino typename _Pred = std::equal_to<_Key>, 460e4b17023SJohn Marino typename _Alloc = std::allocator<_Key> > 461e4b17023SJohn Marino class unordered_multimap 462e4b17023SJohn Marino : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, 463e4b17023SJohn Marino _Pred, _Alloc>, 464e4b17023SJohn Marino public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key, 465e4b17023SJohn Marino _Tp, _Hash, _Pred, _Alloc> > 466e4b17023SJohn Marino { 467e4b17023SJohn Marino typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, 468e4b17023SJohn Marino _Pred, _Alloc> _Base; 469e4b17023SJohn Marino typedef __gnu_debug::_Safe_unordered_container<unordered_multimap> 470e4b17023SJohn Marino _Safe_base; 471e4b17023SJohn Marino typedef typename _Base::const_iterator _Base_const_iterator; 472e4b17023SJohn Marino typedef typename _Base::iterator _Base_iterator; 473e4b17023SJohn Marino typedef typename _Base::const_local_iterator _Base_const_local_iterator; 474e4b17023SJohn Marino typedef typename _Base::local_iterator _Base_local_iterator; 475e4b17023SJohn Marino 476e4b17023SJohn Marino public: 477e4b17023SJohn Marino typedef typename _Base::size_type size_type; 478e4b17023SJohn Marino typedef typename _Base::hasher hasher; 479e4b17023SJohn Marino typedef typename _Base::key_equal key_equal; 480e4b17023SJohn Marino typedef typename _Base::allocator_type allocator_type; 481e4b17023SJohn Marino 482e4b17023SJohn Marino typedef typename _Base::key_type key_type; 483e4b17023SJohn Marino typedef typename _Base::value_type value_type; 484e4b17023SJohn Marino 485e4b17023SJohn Marino typedef __gnu_debug::_Safe_iterator<_Base_iterator, 486e4b17023SJohn Marino unordered_multimap> iterator; 487e4b17023SJohn Marino typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, 488e4b17023SJohn Marino unordered_multimap> const_iterator; 489e4b17023SJohn Marino typedef __gnu_debug::_Safe_local_iterator< 490e4b17023SJohn Marino _Base_local_iterator, unordered_multimap> local_iterator; 491e4b17023SJohn Marino typedef __gnu_debug::_Safe_local_iterator< 492e4b17023SJohn Marino _Base_const_local_iterator, unordered_multimap> const_local_iterator; 493e4b17023SJohn Marino 494e4b17023SJohn Marino explicit 495e4b17023SJohn Marino unordered_multimap(size_type __n = 10, 496e4b17023SJohn Marino const hasher& __hf = hasher(), 497e4b17023SJohn Marino const key_equal& __eql = key_equal(), 498e4b17023SJohn Marino const allocator_type& __a = allocator_type()) 499e4b17023SJohn Marino : _Base(__n, __hf, __eql, __a) { } 500e4b17023SJohn Marino 501e4b17023SJohn Marino template<typename _InputIterator> 502e4b17023SJohn Marino unordered_multimap(_InputIterator __first, _InputIterator __last, 503e4b17023SJohn Marino size_type __n = 0, 504e4b17023SJohn Marino const hasher& __hf = hasher(), 505e4b17023SJohn Marino const key_equal& __eql = key_equal(), 506e4b17023SJohn Marino const allocator_type& __a = allocator_type()) 507e4b17023SJohn Marino : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 508e4b17023SJohn Marino __last)), 509e4b17023SJohn Marino __gnu_debug::__base(__last), __n, 510e4b17023SJohn Marino __hf, __eql, __a) { } 511e4b17023SJohn Marino 512*5ce9237cSJohn Marino unordered_multimap(const unordered_multimap& __x) = default; 513e4b17023SJohn Marino 514e4b17023SJohn Marino unordered_multimap(const _Base& __x) 515e4b17023SJohn Marino : _Base(__x) { } 516e4b17023SJohn Marino 517*5ce9237cSJohn Marino unordered_multimap(unordered_multimap&& __x) = default; 518e4b17023SJohn Marino 519e4b17023SJohn Marino unordered_multimap(initializer_list<value_type> __l, 520e4b17023SJohn Marino size_type __n = 0, 521e4b17023SJohn Marino const hasher& __hf = hasher(), 522e4b17023SJohn Marino const key_equal& __eql = key_equal(), 523e4b17023SJohn Marino const allocator_type& __a = allocator_type()) 524e4b17023SJohn Marino : _Base(__l, __n, __hf, __eql, __a) { } 525e4b17023SJohn Marino 526e4b17023SJohn Marino ~unordered_multimap() noexcept { } 527e4b17023SJohn Marino 528e4b17023SJohn Marino unordered_multimap& 529e4b17023SJohn Marino operator=(const unordered_multimap& __x) 530e4b17023SJohn Marino { 531e4b17023SJohn Marino *static_cast<_Base*>(this) = __x; 532e4b17023SJohn Marino this->_M_invalidate_all(); 533e4b17023SJohn Marino return *this; 534e4b17023SJohn Marino } 535e4b17023SJohn Marino 536e4b17023SJohn Marino unordered_multimap& 537e4b17023SJohn Marino operator=(unordered_multimap&& __x) 538e4b17023SJohn Marino { 539e4b17023SJohn Marino // NB: DR 1204. 540e4b17023SJohn Marino // NB: DR 675. 541e4b17023SJohn Marino clear(); 542e4b17023SJohn Marino swap(__x); 543e4b17023SJohn Marino return *this; 544e4b17023SJohn Marino } 545e4b17023SJohn Marino 546e4b17023SJohn Marino unordered_multimap& 547e4b17023SJohn Marino operator=(initializer_list<value_type> __l) 548e4b17023SJohn Marino { 549e4b17023SJohn Marino this->clear(); 550e4b17023SJohn Marino this->insert(__l); 551e4b17023SJohn Marino return *this; 552e4b17023SJohn Marino } 553e4b17023SJohn Marino 554e4b17023SJohn Marino void 555e4b17023SJohn Marino swap(unordered_multimap& __x) 556e4b17023SJohn Marino { 557e4b17023SJohn Marino _Base::swap(__x); 558e4b17023SJohn Marino _Safe_base::_M_swap(__x); 559e4b17023SJohn Marino } 560e4b17023SJohn Marino 561e4b17023SJohn Marino void 562e4b17023SJohn Marino clear() noexcept 563e4b17023SJohn Marino { 564e4b17023SJohn Marino _Base::clear(); 565e4b17023SJohn Marino this->_M_invalidate_all(); 566e4b17023SJohn Marino } 567e4b17023SJohn Marino 568e4b17023SJohn Marino iterator 569e4b17023SJohn Marino begin() noexcept 570e4b17023SJohn Marino { return iterator(_Base::begin(), this); } 571e4b17023SJohn Marino 572e4b17023SJohn Marino const_iterator 573e4b17023SJohn Marino begin() const noexcept 574e4b17023SJohn Marino { return const_iterator(_Base::begin(), this); } 575e4b17023SJohn Marino 576e4b17023SJohn Marino iterator 577e4b17023SJohn Marino end() noexcept 578e4b17023SJohn Marino { return iterator(_Base::end(), this); } 579e4b17023SJohn Marino 580e4b17023SJohn Marino const_iterator 581e4b17023SJohn Marino end() const noexcept 582e4b17023SJohn Marino { return const_iterator(_Base::end(), this); } 583e4b17023SJohn Marino 584e4b17023SJohn Marino const_iterator 585e4b17023SJohn Marino cbegin() const noexcept 586e4b17023SJohn Marino { return const_iterator(_Base::begin(), this); } 587e4b17023SJohn Marino 588e4b17023SJohn Marino const_iterator 589e4b17023SJohn Marino cend() const noexcept 590e4b17023SJohn Marino { return const_iterator(_Base::end(), this); } 591e4b17023SJohn Marino 592e4b17023SJohn Marino // local versions 593e4b17023SJohn Marino local_iterator 594e4b17023SJohn Marino begin(size_type __b) 595e4b17023SJohn Marino { return local_iterator(_Base::begin(__b), __b, this); } 596e4b17023SJohn Marino 597e4b17023SJohn Marino local_iterator 598e4b17023SJohn Marino end(size_type __b) 599e4b17023SJohn Marino { return local_iterator(_Base::end(__b), __b, this); } 600e4b17023SJohn Marino 601e4b17023SJohn Marino const_local_iterator 602e4b17023SJohn Marino begin(size_type __b) const 603e4b17023SJohn Marino { return const_local_iterator(_Base::begin(__b), __b, this); } 604e4b17023SJohn Marino 605e4b17023SJohn Marino const_local_iterator 606e4b17023SJohn Marino end(size_type __b) const 607e4b17023SJohn Marino { return const_local_iterator(_Base::end(__b), __b, this); } 608e4b17023SJohn Marino 609e4b17023SJohn Marino const_local_iterator 610e4b17023SJohn Marino cbegin(size_type __b) const 611e4b17023SJohn Marino { return const_local_iterator(_Base::cbegin(__b), __b, this); } 612e4b17023SJohn Marino 613e4b17023SJohn Marino const_local_iterator 614e4b17023SJohn Marino cend(size_type __b) const 615e4b17023SJohn Marino { return const_local_iterator(_Base::cend(__b), __b, this); } 616e4b17023SJohn Marino 617e4b17023SJohn Marino template<typename... _Args> 618e4b17023SJohn Marino iterator 619e4b17023SJohn Marino emplace(_Args&&... __args) 620e4b17023SJohn Marino { 621e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 622e4b17023SJohn Marino _Base_iterator __it 623e4b17023SJohn Marino = _Base::emplace(std::forward<_Args>(__args)...); 624e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 625e4b17023SJohn Marino return iterator(__it, this); 626e4b17023SJohn Marino } 627e4b17023SJohn Marino 628e4b17023SJohn Marino template<typename... _Args> 629e4b17023SJohn Marino iterator 630e4b17023SJohn Marino emplace_hint(const_iterator __hint, _Args&&... __args) 631e4b17023SJohn Marino { 632e4b17023SJohn Marino __glibcxx_check_insert(__hint); 633e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 634e4b17023SJohn Marino _Base_iterator __it = _Base::emplace_hint(__hint.base(), 635e4b17023SJohn Marino std::forward<_Args>(__args)...); 636e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 637e4b17023SJohn Marino return iterator(__it, this); 638e4b17023SJohn Marino } 639e4b17023SJohn Marino 640e4b17023SJohn Marino iterator 641e4b17023SJohn Marino insert(const value_type& __obj) 642e4b17023SJohn Marino { 643e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 644e4b17023SJohn Marino _Base_iterator __it = _Base::insert(__obj); 645e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 646e4b17023SJohn Marino return iterator(__it, this); 647e4b17023SJohn Marino } 648e4b17023SJohn Marino 649e4b17023SJohn Marino iterator 650e4b17023SJohn Marino insert(const_iterator __hint, const value_type& __obj) 651e4b17023SJohn Marino { 652e4b17023SJohn Marino __glibcxx_check_insert(__hint); 653e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 654e4b17023SJohn Marino _Base_iterator __it = _Base::insert(__hint.base(), __obj); 655e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 656e4b17023SJohn Marino return iterator(__it, this); 657e4b17023SJohn Marino } 658e4b17023SJohn Marino 659e4b17023SJohn Marino template<typename _Pair, typename = typename 660e4b17023SJohn Marino std::enable_if<std::is_constructible<value_type, 661e4b17023SJohn Marino _Pair&&>::value>::type> 662e4b17023SJohn Marino iterator 663e4b17023SJohn Marino insert(_Pair&& __obj) 664e4b17023SJohn Marino { 665e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 666e4b17023SJohn Marino _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj)); 667e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 668e4b17023SJohn Marino return iterator(__it, this); 669e4b17023SJohn Marino } 670e4b17023SJohn Marino 671e4b17023SJohn Marino template<typename _Pair, typename = typename 672e4b17023SJohn Marino std::enable_if<std::is_constructible<value_type, 673e4b17023SJohn Marino _Pair&&>::value>::type> 674e4b17023SJohn Marino iterator 675e4b17023SJohn Marino insert(const_iterator __hint, _Pair&& __obj) 676e4b17023SJohn Marino { 677e4b17023SJohn Marino __glibcxx_check_insert(__hint); 678e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 679e4b17023SJohn Marino _Base_iterator __it = 680e4b17023SJohn Marino _Base::insert(__hint.base(), std::forward<_Pair>(__obj)); 681e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 682e4b17023SJohn Marino return iterator(__it, this); 683e4b17023SJohn Marino } 684e4b17023SJohn Marino 685e4b17023SJohn Marino void 686e4b17023SJohn Marino insert(std::initializer_list<value_type> __l) 687e4b17023SJohn Marino { _Base::insert(__l); } 688e4b17023SJohn Marino 689e4b17023SJohn Marino template<typename _InputIterator> 690e4b17023SJohn Marino void 691e4b17023SJohn Marino insert(_InputIterator __first, _InputIterator __last) 692e4b17023SJohn Marino { 693e4b17023SJohn Marino __glibcxx_check_valid_range(__first, __last); 694e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 695e4b17023SJohn Marino _Base::insert(__gnu_debug::__base(__first), 696e4b17023SJohn Marino __gnu_debug::__base(__last)); 697e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 698e4b17023SJohn Marino } 699e4b17023SJohn Marino 700e4b17023SJohn Marino iterator 701e4b17023SJohn Marino find(const key_type& __key) 702e4b17023SJohn Marino { return iterator(_Base::find(__key), this); } 703e4b17023SJohn Marino 704e4b17023SJohn Marino const_iterator 705e4b17023SJohn Marino find(const key_type& __key) const 706e4b17023SJohn Marino { return const_iterator(_Base::find(__key), this); } 707e4b17023SJohn Marino 708e4b17023SJohn Marino std::pair<iterator, iterator> 709e4b17023SJohn Marino equal_range(const key_type& __key) 710e4b17023SJohn Marino { 711e4b17023SJohn Marino std::pair<_Base_iterator, _Base_iterator> __res = 712e4b17023SJohn Marino _Base::equal_range(__key); 713e4b17023SJohn Marino return std::make_pair(iterator(__res.first, this), 714e4b17023SJohn Marino iterator(__res.second, this)); 715e4b17023SJohn Marino } 716e4b17023SJohn Marino 717e4b17023SJohn Marino std::pair<const_iterator, const_iterator> 718e4b17023SJohn Marino equal_range(const key_type& __key) const 719e4b17023SJohn Marino { 720e4b17023SJohn Marino std::pair<_Base_const_iterator, _Base_const_iterator> __res = 721e4b17023SJohn Marino _Base::equal_range(__key); 722e4b17023SJohn Marino return std::make_pair(const_iterator(__res.first, this), 723e4b17023SJohn Marino const_iterator(__res.second, this)); 724e4b17023SJohn Marino } 725e4b17023SJohn Marino 726e4b17023SJohn Marino size_type 727e4b17023SJohn Marino erase(const key_type& __key) 728e4b17023SJohn Marino { 729e4b17023SJohn Marino size_type __ret(0); 730e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 731e4b17023SJohn Marino std::pair<_Base_iterator, _Base_iterator> __pair = 732e4b17023SJohn Marino _Base::equal_range(__key); 733e4b17023SJohn Marino for (_Base_iterator __victim = __pair.first; __victim != __pair.second;) 734e4b17023SJohn Marino { 735e4b17023SJohn Marino this->_M_invalidate_if([__victim](_Base_const_iterator __it) 736e4b17023SJohn Marino { return __it == __victim; }); 737e4b17023SJohn Marino _Base_local_iterator __local_victim = _S_to_local(__victim); 738e4b17023SJohn Marino this->_M_invalidate_local_if( 739e4b17023SJohn Marino [__local_victim](_Base_const_local_iterator __it) 740e4b17023SJohn Marino { return __it == __local_victim; }); 741e4b17023SJohn Marino _Base::erase(__victim++); 742e4b17023SJohn Marino ++__ret; 743e4b17023SJohn Marino } 744e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 745e4b17023SJohn Marino return __ret; 746e4b17023SJohn Marino } 747e4b17023SJohn Marino 748e4b17023SJohn Marino iterator 749e4b17023SJohn Marino erase(const_iterator __it) 750e4b17023SJohn Marino { 751e4b17023SJohn Marino __glibcxx_check_erase(__it); 752e4b17023SJohn Marino _Base_const_iterator __victim = __it.base(); 753e4b17023SJohn Marino this->_M_invalidate_if([__victim](_Base_const_iterator __it) 754e4b17023SJohn Marino { return __it == __victim; }); 755e4b17023SJohn Marino _Base_const_local_iterator __local_victim = _S_to_local(__victim); 756e4b17023SJohn Marino this->_M_invalidate_local_if( 757e4b17023SJohn Marino [__local_victim](_Base_const_local_iterator __it) 758e4b17023SJohn Marino { return __it == __local_victim; }); 759e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 760e4b17023SJohn Marino _Base_iterator __next = _Base::erase(__it.base()); 761e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 762e4b17023SJohn Marino return iterator(__next, this); 763e4b17023SJohn Marino } 764e4b17023SJohn Marino 765e4b17023SJohn Marino iterator 766e4b17023SJohn Marino erase(iterator __it) 767e4b17023SJohn Marino { return erase(const_iterator(__it)); } 768e4b17023SJohn Marino 769e4b17023SJohn Marino iterator 770e4b17023SJohn Marino erase(const_iterator __first, const_iterator __last) 771e4b17023SJohn Marino { 772e4b17023SJohn Marino __glibcxx_check_erase_range(__first, __last); 773e4b17023SJohn Marino for (_Base_const_iterator __tmp = __first.base(); 774e4b17023SJohn Marino __tmp != __last.base(); ++__tmp) 775e4b17023SJohn Marino { 776e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 777e4b17023SJohn Marino _M_message(__gnu_debug::__msg_valid_range) 778e4b17023SJohn Marino ._M_iterator(__first, "first") 779e4b17023SJohn Marino ._M_iterator(__last, "last")); 780e4b17023SJohn Marino this->_M_invalidate_if([__tmp](_Base_const_iterator __it) 781e4b17023SJohn Marino { return __it == __tmp; }); 782e4b17023SJohn Marino _Base_const_local_iterator __local_tmp = _S_to_local(__tmp); 783e4b17023SJohn Marino this->_M_invalidate_local_if( 784e4b17023SJohn Marino [__local_tmp](_Base_const_local_iterator __it) 785e4b17023SJohn Marino { return __it == __local_tmp; }); 786e4b17023SJohn Marino } 787e4b17023SJohn Marino size_type __bucket_count = this->bucket_count(); 788e4b17023SJohn Marino _Base_iterator __next = _Base::erase(__first.base(), __last.base()); 789e4b17023SJohn Marino _M_check_rehashed(__bucket_count); 790e4b17023SJohn Marino return iterator(__next, this); 791e4b17023SJohn Marino } 792e4b17023SJohn Marino 793e4b17023SJohn Marino _Base& 794e4b17023SJohn Marino _M_base() noexcept { return *this; } 795e4b17023SJohn Marino 796e4b17023SJohn Marino const _Base& 797e4b17023SJohn Marino _M_base() const noexcept { return *this; } 798e4b17023SJohn Marino 799e4b17023SJohn Marino private: 800e4b17023SJohn Marino void 801e4b17023SJohn Marino _M_invalidate_locals() 802e4b17023SJohn Marino { 803e4b17023SJohn Marino _Base_local_iterator __local_end = _Base::end(0); 804e4b17023SJohn Marino this->_M_invalidate_local_if( 805e4b17023SJohn Marino [__local_end](_Base_const_local_iterator __it) 806e4b17023SJohn Marino { return __it != __local_end; }); 807e4b17023SJohn Marino } 808e4b17023SJohn Marino 809e4b17023SJohn Marino void 810e4b17023SJohn Marino _M_invalidate_all() 811e4b17023SJohn Marino { 812e4b17023SJohn Marino _Base_iterator __end = _Base::end(); 813e4b17023SJohn Marino this->_M_invalidate_if([__end](_Base_const_iterator __it) 814e4b17023SJohn Marino { return __it != __end; }); 815e4b17023SJohn Marino _M_invalidate_locals(); 816e4b17023SJohn Marino } 817e4b17023SJohn Marino 818e4b17023SJohn Marino void 819e4b17023SJohn Marino _M_check_rehashed(size_type __prev_count) 820e4b17023SJohn Marino { 821e4b17023SJohn Marino if (__prev_count != this->bucket_count()) 822e4b17023SJohn Marino _M_invalidate_locals(); 823e4b17023SJohn Marino } 824e4b17023SJohn Marino 825e4b17023SJohn Marino static _Base_local_iterator 826e4b17023SJohn Marino _S_to_local(_Base_iterator __it) 827e4b17023SJohn Marino { 828e4b17023SJohn Marino // The returned local iterator will not be incremented so we don't 829e4b17023SJohn Marino // need to compute __it's node bucket 830e4b17023SJohn Marino return _Base_local_iterator(__it._M_cur, 0, 0); 831e4b17023SJohn Marino } 832e4b17023SJohn Marino 833e4b17023SJohn Marino static _Base_const_local_iterator 834e4b17023SJohn Marino _S_to_local(_Base_const_iterator __it) 835e4b17023SJohn Marino { 836e4b17023SJohn Marino // The returned local iterator will not be incremented so we don't 837e4b17023SJohn Marino // need to compute __it's node bucket 838e4b17023SJohn Marino return _Base_const_local_iterator(__it._M_cur, 0, 0); 839e4b17023SJohn Marino } 840e4b17023SJohn Marino }; 841e4b17023SJohn Marino 842e4b17023SJohn Marino template<typename _Key, typename _Tp, typename _Hash, 843e4b17023SJohn Marino typename _Pred, typename _Alloc> 844e4b17023SJohn Marino inline void 845e4b17023SJohn Marino swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 846e4b17023SJohn Marino unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 847e4b17023SJohn Marino { __x.swap(__y); } 848e4b17023SJohn Marino 849e4b17023SJohn Marino template<typename _Key, typename _Tp, typename _Hash, 850e4b17023SJohn Marino typename _Pred, typename _Alloc> 851e4b17023SJohn Marino inline bool 852e4b17023SJohn Marino operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 853e4b17023SJohn Marino const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 854e4b17023SJohn Marino { return __x._M_equal(__y); } 855e4b17023SJohn Marino 856e4b17023SJohn Marino template<typename _Key, typename _Tp, typename _Hash, 857e4b17023SJohn Marino typename _Pred, typename _Alloc> 858e4b17023SJohn Marino inline bool 859e4b17023SJohn Marino operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 860e4b17023SJohn Marino const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 861e4b17023SJohn Marino { return !(__x == __y); } 862e4b17023SJohn Marino 863e4b17023SJohn Marino} // namespace __debug 864e4b17023SJohn Marino} // namespace std 865e4b17023SJohn Marino 866e4b17023SJohn Marino#endif // __GXX_EXPERIMENTAL_CXX0X__ 867e4b17023SJohn Marino 868e4b17023SJohn Marino#endif 869