# debug/unordered_map

Go to the documentation of this file.

    00001 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
    00002
    00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    00004 // Free Software Foundation, Inc.
    00005 //
    00006 // This file is part of the GNU ISO C++ Library.  This library is free
    00007 // software; you can redistribute it and/or modify it under the
    00008 // terms of the GNU General Public License as published by the
    00009 // Free Software Foundation; either version 3, or (at your option)
    00010 // any later version.
    00011
    00012 // This library is distributed in the hope that it will be useful,
    00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00015 // GNU General Public License for more details.
    00016
    00017 // Under Section 7 of GPL version 3, you are granted additional
    00018 // permissions described in the GCC Runtime Library Exception, version
    00019 // 3.1, as published by the Free Software Foundation.
    00020
    00021 // You should have received a copy of the GNU General Public License and
    00022 // a copy of the GCC Runtime Library Exception along with this program;
    00023 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    00024 // <http://www.gnu.org/licenses/>.
    00025
    00026 /** @file debug/unordered_map
    00027  *  This file is a GNU debug extension to the Standard C++ Library.
    00028  */
    00029
    00030 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
    00031 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1
    00032
    00033 #ifndef __GXX_EXPERIMENTAL_CXX0X__
    00034 # include <bits/c++0x_warning.h>
    00035 #else
    00036 # include <unordered_map>
    00037
    00038 #include <debug/safe_sequence.h>
    00039 #include <debug/safe_iterator.h>
    00040
    00041 namespace std
    00042 {
    00043 namespace __debug
    00044 {
    00045   /// Class std::unordered_map with safety/checking/debug instrumentation.
    00046   template<typename _Key, typename _Tp,
    00047        typename _Hash = std::hash<_Key>,
    00048        typename _Pred = std::equal_to<_Key>,
    00049        typename _Alloc = std::allocator<_Key> >
    00050     class unordered_map
    00051     : public _GLIBCXX_STD_D::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
    00052       public __gnu_debug::_Safe_sequence<unordered_map<_Key, _Tp, _Hash,
    00053                                _Pred, _Alloc> >
    00054     {
    00055       typedef _GLIBCXX_STD_D::unordered_map<_Key, _Tp, _Hash,
    00056                         _Pred, _Alloc> _Base;
    00057       typedef __gnu_debug::_Safe_sequence<unordered_map> _Safe_base;
    00058
    00059     public:
    00060       typedef typename _Base::size_type       size_type;
    00061       typedef typename _Base::hasher          hasher;
    00062       typedef typename _Base::key_equal       key_equal;
    00063       typedef typename _Base::allocator_type  allocator_type;
    00064
    00065       typedef typename _Base::key_type        key_type;
    00066       typedef typename _Base::value_type      value_type;
    00067
    00068       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,
    00069                       unordered_map> iterator;
    00070       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,
    00071                       unordered_map> const_iterator;
    00072
    00073       explicit
    00074       unordered_map(size_type __n = 10,
    00075             const hasher& __hf = hasher(),
    00076             const key_equal& __eql = key_equal(),
    00077             const allocator_type& __a = allocator_type())
    00078       : _Base(__n, __hf, __eql, __a) { }
    00079
    00080       template<typename _InputIterator>
    00081         unordered_map(_InputIterator __f, _InputIterator __l,
    00082               size_type __n = 10,
    00083               const hasher& __hf = hasher(),
    00084               const key_equal& __eql = key_equal(),
    00085               const allocator_type& __a = allocator_type())
    00086     : _Base(__gnu_debug::__check_valid_range(__f, __l), __l, __n,
    00087         __hf, __eql, __a), _Safe_base() { }
    00088
    00089       unordered_map(const unordered_map& __x)
    00090       : _Base(__x), _Safe_base() { }
    00091
    00092       unordered_map(const _Base& __x)
    00093       : _Base(__x), _Safe_base() { }
    00094
    00095       unordered_map(unordered_map&& __x)
    00096       : _Base(std::forward<unordered_map>(__x)), _Safe_base() { }
    00097
    00098       unordered_map(initializer_list<value_type> __l,
    00099             size_type __n = 10,
    00100             const hasher& __hf = hasher(),
    00101             const key_equal& __eql = key_equal(),
    00102             const allocator_type& __a = allocator_type())
    00103       : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
    00104
    00105       unordered_map&
    00106       operator=(const unordered_map& __x)
    00107       {
    00108     *static_cast<_Base*>(this) = __x;
    00109     this->_M_invalidate_all();
    00110     return *this;
    00111       }
    00112
    00113       unordered_map&
    00114       operator=(unordered_map&& __x)
    00115       {
    00116     // NB: DR 1204.
    00117     // NB: DR 675.
    00118     clear();
    00119     swap(__x);
    00120     return *this;
    00121       }
    00122
    00123       unordered_map&
    00124       operator=(initializer_list<value_type> __l)
    00125       {
    00126     this->clear();
    00127     this->insert(__l);
    00128     return *this;
    00129       }
    00130
    00131       void
    00132       swap(unordered_map& __x)
    00133       {
    00134     _Base::swap(__x);
    00135     _Safe_base::_M_swap(__x);
    00136       }
    00137
    00138       void
    00139       clear()
    00140       {
    00141     _Base::clear();
    00142     this->_M_invalidate_all();
    00143       }
    00144
    00145       iterator
    00146       begin()
    00147       { return iterator(_Base::begin(), this); }
    00148
    00149       const_iterator
    00150       begin() const
    00151       { return const_iterator(_Base::begin(), this); }
    00152
    00153       iterator
    00154       end()
    00155       { return iterator(_Base::end(), this); }
    00156
    00157       const_iterator
    00158       end() const
    00159       { return const_iterator(_Base::end(), this); }
    00160
    00161       const_iterator
    00162       cbegin() const
    00163       { return const_iterator(_Base::begin(), this); }
    00164
    00165       const_iterator
    00166       cend() const
    00167       { return const_iterator(_Base::end(), this); }
    00168
    00169       // local versions
    00170       using _Base::begin;
    00171       using _Base::end;
    00172       using _Base::cbegin;
    00173       using _Base::cend;
    00174
    00175       std::pair<iterator, bool>
    00176       insert(const value_type& __obj)
    00177       {
    00178     typedef std::pair<typename _Base::iterator, bool> __pair_type;
    00179     __pair_type __res = _Base::insert(__obj);
    00180     return std::make_pair(iterator(__res.first, this), __res.second);
    00181       }
    00182
    00183       iterator
    00184       insert(const_iterator, const value_type& __obj)
    00185       {
    00186     typedef std::pair<typename _Base::iterator, bool> __pair_type;
    00187     __pair_type __res = _Base::insert(__obj);
    00188     return iterator(__res.first, this);
    00189       }
    00190
    00191       void
    00192       insert(std::initializer_list<value_type> __l)
    00193       { _Base::insert(__l); }
    00194
    00195       template<typename _InputIterator>
    00196         void
    00197         insert(_InputIterator __first, _InputIterator __last)
    00198         {
    00199       __glibcxx_check_valid_range(__first, __last);
    00200       _Base::insert(__first, __last);
    00201     }
    00202
    00203       iterator
    00204       find(const key_type& __key)
    00205       { return iterator(_Base::find(__key), this); }
    00206
    00207       const_iterator
    00208       find(const key_type& __key) const
    00209       { return const_iterator(_Base::find(__key), this); }
    00210
    00211       std::pair<iterator, iterator>
    00212       equal_range(const key_type& __key)
    00213       {
    00214     typedef typename _Base::iterator _Base_iterator;
    00215     typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
    00216     __pair_type __res = _Base::equal_range(__key);
    00217     return std::make_pair(iterator(__res.first, this),
    00218                   iterator(__res.second, this));
    00219       }
    00220
    00221       std::pair<const_iterator, const_iterator>
    00222       equal_range(const key_type& __key) const
    00223       {
    00224     typedef typename _Base::const_iterator _Base_iterator;
    00225     typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
    00226     __pair_type __res = _Base::equal_range(__key);
    00227     return std::make_pair(const_iterator(__res.first, this),
    00228                   const_iterator(__res.second, this));
    00229       }
    00230
    00231       size_type
    00232       erase(const key_type& __key)
    00233       {
    00234     size_type __ret(0);
    00235     iterator __victim(_Base::find(__key), this);
    00236     if (__victim != end())
    00237       {
    00238         this->erase(__victim);
    00239         __ret = 1;
    00240       }
    00241     return __ret;
    00242       }
    00243
    00244       iterator
    00245       erase(const_iterator __it)
    00246       {
    00247     __glibcxx_check_erase(__it);
    00248     __it._M_invalidate();
    00249     return iterator(_Base::erase(__it.base()), this);
    00250       }
    00251
    00252       iterator
    00253       erase(const_iterator __first, const_iterator __last)
    00254       {
    00255     __glibcxx_check_erase_range(__first, __last);
    00256     for (const_iterator __tmp = __first; __tmp != __last;)
    00257     {
    00258       const_iterator __victim = __tmp++;
    00259       __victim._M_invalidate();
    00260     }
    00261     return iterator(_Base::erase(__first.base(),
    00262                      __last.base()), this);
    00263       }
    00264
    00265       _Base&
    00266       _M_base() { return *this; }
    00267
    00268       const _Base&
    00269       _M_base() const { return *this; }
    00270
    00271     private:
    00272       void
    00273       _M_invalidate_all()
    00274       {
    00275     typedef typename _Base::const_iterator _Base_const_iterator;
    00276     typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
    00277     this->_M_invalidate_if(_Not_equal(_M_base().end()));
    00278       }
    00279     };
    00280
    00281   template<typename _Key, typename _Tp, typename _Hash,
    00282        typename _Pred, typename _Alloc>
    00283     inline void
    00284     swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00285      unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00286     { __x.swap(__y); }
    00287
    00288   template<typename _Key, typename _Tp, typename _Hash,
    00289        typename _Pred, typename _Alloc>
    00290     inline bool
    00291     operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00292            const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00293     { return __x._M_equal(__y); }
    00294
    00295   template<typename _Key, typename _Tp, typename _Hash,
    00296        typename _Pred, typename _Alloc>
    00297     inline bool
    00298     operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00299            const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00300     { return !(__x == __y); }
    00301
    00302
    00303   /// Class std::unordered_multimap with safety/checking/debug instrumentation.
    00304   template<typename _Key, typename _Tp,
    00305        typename _Hash = std::hash<_Key>,
    00306        typename _Pred = std::equal_to<_Key>,
    00307        typename _Alloc = std::allocator<_Key> >
    00308     class unordered_multimap
    00309     : public _GLIBCXX_STD_D::unordered_multimap<_Key, _Tp, _Hash,
    00310                         _Pred, _Alloc>,
    00311       public __gnu_debug::_Safe_sequence<unordered_multimap<_Key, _Tp, _Hash,
    00312                                 _Pred, _Alloc> >
    00313     {
    00314       typedef _GLIBCXX_STD_D::unordered_multimap<_Key, _Tp, _Hash,
    00315                          _Pred, _Alloc> _Base;
    00316       typedef __gnu_debug::_Safe_sequence<unordered_multimap> _Safe_base;
    00317
    00318     public:
    00319       typedef typename _Base::size_type       size_type;
    00320       typedef typename _Base::hasher          hasher;
    00321       typedef typename _Base::key_equal       key_equal;
    00322       typedef typename _Base::allocator_type  allocator_type;
    00323
    00324       typedef typename _Base::key_type        key_type;
    00325       typedef typename _Base::value_type      value_type;
    00326
    00327       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,
    00328                       unordered_multimap> iterator;
    00329       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,
    00330                       unordered_multimap> const_iterator;
    00331
    00332       explicit
    00333       unordered_multimap(size_type __n = 10,
    00334              const hasher& __hf = hasher(),
    00335              const key_equal& __eql = key_equal(),
    00336              const allocator_type& __a = allocator_type())
    00337       : _Base(__n, __hf, __eql, __a) { }
    00338
    00339       template<typename _InputIterator>
    00340         unordered_multimap(_InputIterator __f, _InputIterator __l,
    00341                size_type __n = 10,
    00342                const hasher& __hf = hasher(),
    00343                const key_equal& __eql = key_equal(),
    00344                const allocator_type& __a = allocator_type())
    00345     : _Base(__gnu_debug::__check_valid_range(__f, __l), __l, __n,
    00346         __hf, __eql, __a), _Safe_base() { }
    00347
    00348       unordered_multimap(const unordered_multimap& __x)
    00349       : _Base(__x), _Safe_base() { }
    00350
    00351       unordered_multimap(const _Base& __x)
    00352       : _Base(__x), _Safe_base() { }
    00353
    00354       unordered_multimap(unordered_multimap&& __x)
    00355       : _Base(std::forward<unordered_multimap>(__x)), _Safe_base() { }
    00356
    00357       unordered_multimap(initializer_list<value_type> __l,
    00358              size_type __n = 10,
    00359              const hasher& __hf = hasher(),
    00360              const key_equal& __eql = key_equal(),
    00361              const allocator_type& __a = allocator_type())
    00362       : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
    00363
    00364       unordered_multimap&
    00365       operator=(const unordered_multimap& __x)
    00366       {
    00367     *static_cast<_Base*>(this) = __x;
    00368     this->_M_invalidate_all();
    00369     return *this;
    00370       }
    00371
    00372       unordered_multimap&
    00373       operator=(unordered_multimap&& __x)
    00374       {
    00375     // NB: DR 1204.
    00376     // NB: DR 675.
    00377     clear();
    00378     swap(__x);
    00379     return *this;
    00380       }
    00381
    00382       unordered_multimap&
    00383       operator=(initializer_list<value_type> __l)
    00384       {
    00385     this->clear();
    00386     this->insert(__l);
    00387     return *this;
    00388       }
    00389
    00390       void
    00391       swap(unordered_multimap& __x)
    00392       {
    00393     _Base::swap(__x);
    00394     _Safe_base::_M_swap(__x);
    00395       }
    00396
    00397       void
    00398       clear()
    00399       {
    00400     _Base::clear();
    00401     this->_M_invalidate_all();
    00402       }
    00403
    00404       iterator
    00405       begin()
    00406       { return iterator(_Base::begin(), this); }
    00407
    00408       const_iterator
    00409       begin() const
    00410       { return const_iterator(_Base::begin(), this); }
    00411
    00412       iterator
    00413       end()
    00414       { return iterator(_Base::end(), this); }
    00415
    00416       const_iterator
    00417       end() const
    00418       { return const_iterator(_Base::end(), this); }
    00419
    00420       const_iterator
    00421       cbegin() const
    00422       { return const_iterator(_Base::begin(), this); }
    00423
    00424       const_iterator
    00425       cend() const
    00426       { return const_iterator(_Base::end(), this); }
    00427
    00428       // local versions
    00429       using _Base::begin;
    00430       using _Base::end;
    00431       using _Base::cbegin;
    00432       using _Base::cend;
    00433
    00434       iterator
    00435       insert(const value_type& __obj)
    00436       { return iterator(_Base::insert(__obj), this); }
    00437
    00438       iterator
    00439       insert(const_iterator, const value_type& __obj)
    00440       { return iterator(_Base::insert(__obj), this); }
    00441
    00442       void
    00443       insert(std::initializer_list<value_type> __l)
    00444       { _Base::insert(__l); }
    00445
    00446       template<typename _InputIterator>
    00447         void
    00448         insert(_InputIterator __first, _InputIterator __last)
    00449         {
    00450       __glibcxx_check_valid_range(__first, __last);
    00451       _Base::insert(__first, __last);
    00452     }
    00453
    00454       iterator
    00455       find(const key_type& __key)
    00456       { return iterator(_Base::find(__key), this); }
    00457
    00458       const_iterator
    00459       find(const key_type& __key) const
    00460       { return const_iterator(_Base::find(__key), this); }
    00461
    00462       std::pair<iterator, iterator>
    00463       equal_range(const key_type& __key)
    00464       {
    00465     typedef typename _Base::iterator _Base_iterator;
    00466     typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
    00467     __pair_type __res = _Base::equal_range(__key);
    00468     return std::make_pair(iterator(__res.first, this),
    00469                   iterator(__res.second, this));
    00470       }
    00471
    00472       std::pair<const_iterator, const_iterator>
    00473       equal_range(const key_type& __key) const
    00474       {
    00475     typedef typename _Base::const_iterator _Base_iterator;
    00476     typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
    00477     __pair_type __res = _Base::equal_range(__key);
    00478     return std::make_pair(const_iterator(__res.first, this),
    00479                   const_iterator(__res.second, this));
    00480       }
    00481
    00482       size_type
    00483       erase(const key_type& __key)
    00484       {
    00485     size_type __ret(0);
    00486     iterator __victim(_Base::find(__key), this);
    00487     if (__victim != end())
    00488       {
    00489         this->erase(__victim);
    00490         __ret = 1;
    00491       }
    00492     return __ret;
    00493       }
    00494
    00495       iterator
    00496       erase(const_iterator __it)
    00497       {
    00498     __glibcxx_check_erase(__it);
    00499     __it._M_invalidate();
    00500     return iterator(_Base::erase(__it.base()), this);
    00501       }
    00502
    00503       iterator
    00504       erase(const_iterator __first, const_iterator __last)
    00505       {
    00506     __glibcxx_check_erase_range(__first, __last);
    00507     for (const_iterator __tmp = __first; __tmp != __last;)
    00508     {
    00509       const_iterator __victim = __tmp++;
    00510       __victim._M_invalidate();
    00511     }
    00512     return iterator(_Base::erase(__first.base(),
    00513                      __last.base()), this);
    00514       }
    00515
    00516       _Base&
    00517       _M_base() { return *this; }
    00518
    00519       const _Base&
    00520       _M_base() const { return *this; }
    00521
    00522     private:
    00523       void
    00524       _M_invalidate_all()
    00525       {
    00526     typedef typename _Base::const_iterator _Base_const_iterator;
    00527     typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
    00528     this->_M_invalidate_if(_Not_equal(_M_base().end()));
    00529       }
    00530     };
    00531
    00532   template<typename _Key, typename _Tp, typename _Hash,
    00533        typename _Pred, typename _Alloc>
    00534     inline void
    00535     swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00536      unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00537     { __x.swap(__y); }
    00538
    00539   template<typename _Key, typename _Tp, typename _Hash,
    00540        typename _Pred, typename _Alloc>
    00541     inline bool
    00542     operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00543            const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00544     { return __x._M_equal(__y); }
    00545
    00546   template<typename _Key, typename _Tp, typename _Hash,
    00547        typename _Pred, typename _Alloc>
    00548     inline bool
    00549     operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00550            const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00551     { return !(__x == __y); }
    00552
    00553 } // namespace __debug
    00554 } // namespace std
    00555
    00556 #endif // __GXX_EXPERIMENTAL_CXX0X__
    00557
    00558 #endif