Home | History | Annotate | Download | only in debug
      1 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
      2 
      3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
      4 // Free Software Foundation, Inc.
      5 //
      6 // This file is part of the GNU ISO C++ Library.  This library is free
      7 // software; you can redistribute it and/or modify it under the
      8 // terms of the GNU General Public License as published by the
      9 // Free Software Foundation; either version 3, or (at your option)
     10 // any later version.
     11 
     12 // This library is distributed in the hope that it will be useful,
     13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 // GNU General Public License for more details.
     16 
     17 // Under Section 7 of GPL version 3, you are granted additional
     18 // permissions described in the GCC Runtime Library Exception, version
     19 // 3.1, as published by the Free Software Foundation.
     20 
     21 // You should have received a copy of the GNU General Public License and
     22 // a copy of the GCC Runtime Library Exception along with this program;
     23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24 // <http://www.gnu.org/licenses/>.
     25 
     26 /** @file debug/unordered_set
     27  *  This file is a GNU debug extension to the Standard C++ Library.
     28  */
     29 
     30 #ifndef _GLIBCXX_DEBUG_UNORDERED_SET
     31 #define _GLIBCXX_DEBUG_UNORDERED_SET 1
     32 
     33 #ifdef __GXX_EXPERIMENTAL_CXX0X__
     34 # include <unordered_set>
     35 #else
     36 # include <c++0x_warning.h>
     37 #endif
     38 
     39 #include <debug/safe_sequence.h>
     40 #include <debug/safe_iterator.h>
     41 #include <initializer_list>
     42 
     43 namespace std
     44 {
     45 namespace __debug
     46 {
     47   template<typename _Value,
     48 	   typename _Hash = std::hash<_Value>,
     49 	   typename _Pred = std::equal_to<_Value>,
     50 	   typename _Alloc = std::allocator<_Value> >
     51     class unordered_set
     52     : public _GLIBCXX_STD_D::unordered_set<_Value, _Hash, _Pred, _Alloc>,
     53       public __gnu_debug::_Safe_sequence<unordered_set<_Value, _Hash,
     54 						       _Pred, _Alloc> >
     55     {
     56       typedef _GLIBCXX_STD_D::unordered_set<_Value, _Hash,
     57 					    _Pred, _Alloc> _Base;
     58       typedef __gnu_debug::_Safe_sequence<unordered_set> _Safe_base;
     59 
     60     public:
     61       typedef typename _Base::size_type       size_type;
     62       typedef typename _Base::hasher          hasher;
     63       typedef typename _Base::key_equal       key_equal;
     64       typedef typename _Base::allocator_type  allocator_type;
     65 
     66       typedef typename _Base::key_type        key_type;
     67       typedef typename _Base::value_type      value_type;
     68 
     69       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,
     70 					  unordered_set> iterator;
     71       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,
     72 					  unordered_set> const_iterator;
     73 
     74       explicit
     75       unordered_set(size_type __n = 10,
     76 		    const hasher& __hf = hasher(),
     77 		    const key_equal& __eql = key_equal(),
     78 		    const allocator_type& __a = allocator_type())
     79       : _Base(__n, __hf, __eql, __a) { }
     80 
     81       template<typename _InputIterator>
     82         unordered_set(_InputIterator __f, _InputIterator __l, 
     83 		      size_type __n = 10,
     84 		      const hasher& __hf = hasher(), 
     85 		      const key_equal& __eql = key_equal(), 
     86 		      const allocator_type& __a = allocator_type())
     87 	: _Base(__gnu_debug::__check_valid_range(__f, __l), __l, __n,
     88 		__hf, __eql, __a), _Safe_base() { }
     89 
     90       unordered_set(const unordered_set& __x) 
     91       : _Base(__x), _Safe_base() { }
     92 
     93       unordered_set(const _Base& __x) 
     94       : _Base(__x), _Safe_base() { }
     95 
     96       unordered_set(unordered_set&& __x) 
     97       : _Base(std::forward<unordered_set>(__x)), _Safe_base() { }
     98 
     99       unordered_set(initializer_list<value_type> __l,
    100 		    size_type __n = 10,
    101 		    const hasher& __hf = hasher(),
    102 		    const key_equal& __eql = key_equal(),
    103 		    const allocator_type& __a = allocator_type())
    104       : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
    105 
    106       unordered_set&
    107       operator=(const unordered_set& __x)
    108       {
    109 	*static_cast<_Base*>(this) = __x;
    110 	this->_M_invalidate_all();
    111 	return *this;
    112       }
    113 
    114       unordered_set&
    115       operator=(unordered_set&& __x)
    116       {
    117         // NB: DR 675.
    118 	clear();
    119 	swap(__x);
    120 	return *this;
    121       }
    122 
    123       unordered_set&
    124       operator=(initializer_list<value_type> __l)
    125       {
    126 	this->clear();
    127 	this->insert(__l);
    128 	return *this;
    129       }
    130 
    131       void
    132       swap(unordered_set&& __x)
    133       {
    134 	_Base::swap(__x);
    135 	_Safe_base::_M_swap(__x);
    136       }
    137 
    138       void
    139       clear()
    140       {
    141 	_Base::clear();
    142 	this->_M_invalidate_all();
    143       }
    144 
    145       iterator 
    146       begin()
    147       { return iterator(_Base::begin(), this); }
    148 
    149       const_iterator
    150       begin() const
    151       { return const_iterator(_Base::begin(), this); }
    152 
    153       iterator
    154       end()
    155       { return iterator(_Base::end(), this); }
    156 
    157       const_iterator
    158       end() const
    159       { return const_iterator(_Base::end(), this); }
    160 
    161       const_iterator
    162       cbegin() const
    163       { return const_iterator(_Base::begin(), this); }
    164 
    165       const_iterator
    166       cend() const
    167       { return const_iterator(_Base::end(), this); }
    168 
    169       // local versions
    170       using _Base::begin;
    171       using _Base::end;
    172       using _Base::cbegin;
    173       using _Base::cend;
    174 
    175       std::pair<iterator, bool>
    176       insert(const value_type& __obj)
    177       {
    178 	typedef std::pair<typename _Base::iterator, bool> __pair_type;
    179 	__pair_type __res = _Base::insert(__obj);
    180 	return std::make_pair(iterator(__res.first, this), __res.second);
    181       }
    182 
    183       iterator
    184       insert(iterator, const value_type& __obj)
    185       {
    186 	typedef std::pair<typename _Base::iterator, bool> __pair_type;
    187 	__pair_type __res = _Base::insert(__obj);
    188 	return iterator(__res.first, this);
    189       }
    190 
    191       const_iterator
    192       insert(const_iterator, const value_type& __obj)
    193       {
    194 	typedef std::pair<typename _Base::iterator, bool> __pair_type;
    195 	__pair_type __res = _Base::insert(__obj);
    196 	return const_iterator(__res.first, this);
    197       }
    198 
    199       void
    200       insert(std::initializer_list<value_type> __l)
    201       { _Base::insert(__l); }
    202 
    203       template<typename _InputIterator>
    204         void
    205         insert(_InputIterator __first, _InputIterator __last)
    206         {
    207 	  __glibcxx_check_valid_range(__first, __last);
    208 	  _Base::insert(__first, __last);
    209 	}
    210 
    211       iterator
    212       find(const key_type& __key)
    213       { return iterator(_Base::find(__key), this); }
    214 
    215       const_iterator
    216       find(const key_type& __key) const
    217       { return const_iterator(_Base::find(__key), this); }
    218 
    219       std::pair<iterator, iterator>
    220       equal_range(const key_type& __key)
    221       {
    222 	typedef typename _Base::iterator _Base_iterator;
    223 	typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
    224 	__pair_type __res = _Base::equal_range(__key);
    225 	return std::make_pair(iterator(__res.first, this),
    226 			      iterator(__res.second, this));
    227       }
    228 
    229       std::pair<const_iterator, const_iterator>
    230       equal_range(const key_type& __key) const
    231       {
    232 	typedef typename _Base::const_iterator _Base_iterator;
    233 	typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
    234 	__pair_type __res = _Base::equal_range(__key);
    235 	return std::make_pair(const_iterator(__res.first, this),
    236 			      const_iterator(__res.second, this));
    237       }
    238 
    239       size_type
    240       erase(const key_type& __key)
    241       {
    242 	size_type __ret(0);
    243 	iterator __victim(_Base::find(__key), this);
    244 	if (__victim != end())
    245 	  {
    246 	    this->erase(__victim);
    247 	    __ret = 1;
    248 	  }
    249 	return __ret;
    250       }
    251 
    252       iterator
    253       erase(iterator __it)
    254       {
    255 	__glibcxx_check_erase(__it);
    256 	__it._M_invalidate();
    257 	return iterator(_Base::erase(__it.base()), this);
    258       }
    259 
    260       const_iterator
    261       erase(const_iterator __it)
    262       {
    263 	__glibcxx_check_erase(__it);
    264 	__it._M_invalidate();
    265 	return const_iterator(_Base::erase(__it.base()), this);
    266       }
    267 
    268       iterator
    269       erase(iterator __first, iterator __last)
    270       {
    271 	__glibcxx_check_erase_range(__first, __last);
    272 	for (iterator __tmp = __first; __tmp != __last;)
    273 	{
    274 	  iterator __victim = __tmp++;
    275 	  __victim._M_invalidate();
    276 	}
    277 	return iterator(_Base::erase(__first.base(),
    278 				     __last.base()), this);
    279       }
    280 
    281       const_iterator
    282       erase(const_iterator __first, const_iterator __last)
    283       {
    284 	__glibcxx_check_erase_range(__first, __last);
    285 	for (const_iterator __tmp = __first; __tmp != __last;)
    286 	{
    287 	  const_iterator __victim = __tmp++;
    288 	  __victim._M_invalidate();
    289 	}
    290 	return const_iterator(_Base::erase(__first.base(),
    291 					   __last.base()), this);
    292       }
    293 
    294       _Base&
    295       _M_base() { return *this; }
    296 
    297       const _Base&
    298       _M_base() const { return *this; }
    299 
    300     private:
    301       void
    302       _M_invalidate_all()
    303       {
    304 	typedef typename _Base::const_iterator _Base_const_iterator;
    305 	typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
    306 	this->_M_invalidate_if(_Not_equal(_M_base().end()));
    307       }
    308     };
    309 
    310   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
    311     inline void
    312     swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
    313 	 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
    314     { __x.swap(__y); }
    315 
    316   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
    317     inline void
    318     swap(unordered_set<_Value, _Hash, _Pred, _Alloc>&& __x,
    319 	 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
    320     { __x.swap(__y); }
    321 
    322   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
    323     inline void
    324     swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
    325 	 unordered_set<_Value, _Hash, _Pred, _Alloc>&& __y)
    326     { __x.swap(__y); }
    327 
    328 
    329   template<typename _Value,
    330 	   typename _Hash = std::hash<_Value>,
    331 	   typename _Pred = std::equal_to<_Value>,
    332 	   typename _Alloc = std::allocator<_Value> >
    333     class unordered_multiset
    334     : public _GLIBCXX_STD_D::unordered_multiset<_Value, _Hash, _Pred, _Alloc>,
    335       public __gnu_debug::_Safe_sequence<unordered_multiset<_Value, _Hash,
    336 							    _Pred, _Alloc> >
    337     {
    338       typedef _GLIBCXX_STD_D::unordered_multiset<_Value, _Hash,
    339 						 _Pred, _Alloc> _Base;
    340       typedef __gnu_debug::_Safe_sequence<unordered_multiset> _Safe_base;
    341 
    342     public:
    343       typedef typename _Base::size_type       size_type;
    344       typedef typename _Base::hasher          hasher;
    345       typedef typename _Base::key_equal       key_equal;
    346       typedef typename _Base::allocator_type  allocator_type;
    347 
    348       typedef typename _Base::key_type        key_type;
    349       typedef typename _Base::value_type      value_type;
    350 
    351       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,
    352 					  unordered_multiset> iterator;
    353       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,
    354 					  unordered_multiset> const_iterator;
    355 
    356       explicit
    357       unordered_multiset(size_type __n = 10,
    358 			 const hasher& __hf = hasher(),
    359 			 const key_equal& __eql = key_equal(),
    360 			 const allocator_type& __a = allocator_type())
    361       : _Base(__n, __hf, __eql, __a) { }
    362 
    363       template<typename _InputIterator>
    364         unordered_multiset(_InputIterator __f, _InputIterator __l, 
    365 			   size_type __n = 10,
    366 			   const hasher& __hf = hasher(), 
    367 			   const key_equal& __eql = key_equal(), 
    368 			   const allocator_type& __a = allocator_type())
    369 	: _Base(__gnu_debug::__check_valid_range(__f, __l), __l, __n,
    370 		__hf, __eql, __a), _Safe_base() { }
    371 
    372       unordered_multiset(const unordered_multiset& __x) 
    373       : _Base(__x), _Safe_base() { }
    374 
    375       unordered_multiset(const _Base& __x) 
    376       : _Base(__x), _Safe_base() { }
    377 
    378       unordered_multiset(unordered_multiset&& __x) 
    379       : _Base(std::forward<unordered_multiset>(__x)), _Safe_base() { }
    380 
    381       unordered_multiset(initializer_list<value_type> __l,
    382 			 size_type __n = 10,
    383 			 const hasher& __hf = hasher(),
    384 			 const key_equal& __eql = key_equal(),
    385 			 const allocator_type& __a = allocator_type())
    386       : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
    387 
    388       unordered_multiset&
    389       operator=(const unordered_multiset& __x)
    390       {
    391 	*static_cast<_Base*>(this) = __x;
    392 	this->_M_invalidate_all();
    393 	return *this;
    394       }
    395 
    396       unordered_multiset&
    397       operator=(unordered_multiset&& __x)
    398       {
    399         // NB: DR 675.
    400 	clear();
    401 	swap(__x);
    402 	return *this;
    403       }
    404 
    405       unordered_multiset&
    406       operator=(initializer_list<value_type> __l)
    407       {
    408 	this->clear();
    409 	this->insert(__l);
    410 	return *this;
    411       }
    412 
    413       void
    414       swap(unordered_multiset&& __x)
    415       {
    416 	_Base::swap(__x);
    417 	_Safe_base::_M_swap(__x);
    418       }
    419 
    420       void
    421       clear()
    422       {
    423 	_Base::clear();
    424 	this->_M_invalidate_all();
    425       }
    426 
    427       iterator
    428       begin()
    429       { return iterator(_Base::begin(), this); }
    430 
    431       const_iterator
    432       begin() const
    433       { return const_iterator(_Base::begin(), this); }
    434 
    435       iterator
    436       end()
    437       { return iterator(_Base::end(), this); }
    438 
    439       const_iterator
    440       end() const
    441       { return const_iterator(_Base::end(), this); }
    442 
    443       const_iterator
    444       cbegin() const
    445       { return const_iterator(_Base::begin(), this); }
    446 
    447       const_iterator
    448       cend() const
    449       { return const_iterator(_Base::end(), this); }
    450 
    451       // local versions
    452       using _Base::begin;
    453       using _Base::end;
    454       using _Base::cbegin;
    455       using _Base::cend;
    456 
    457       iterator
    458       insert(const value_type& __obj)
    459       { return iterator(_Base::insert(__obj), this); }
    460 
    461       iterator
    462       insert(iterator, const value_type& __obj)
    463       { return iterator(_Base::insert(__obj), this); }
    464 
    465       const_iterator
    466       insert(const_iterator, const value_type& __obj)
    467       { return const_iterator(_Base::insert(__obj), this); }
    468 
    469       void
    470       insert(std::initializer_list<value_type> __l)
    471       { _Base::insert(__l); }
    472 
    473       template<typename _InputIterator>
    474         void
    475         insert(_InputIterator __first, _InputIterator __last)
    476         {
    477 	  __glibcxx_check_valid_range(__first, __last);
    478 	  _Base::insert(__first, __last);
    479 	}
    480 
    481       iterator
    482       find(const key_type& __key)
    483       { return iterator(_Base::find(__key), this); }
    484 
    485       const_iterator
    486       find(const key_type& __key) const
    487       { return const_iterator(_Base::find(__key), this); }
    488 
    489       std::pair<iterator, iterator>
    490       equal_range(const key_type& __key)
    491       {
    492 	typedef typename _Base::iterator _Base_iterator;
    493 	typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
    494 	__pair_type __res = _Base::equal_range(__key);
    495 	return std::make_pair(iterator(__res.first, this),
    496 			      iterator(__res.second, this));
    497       }
    498 
    499       std::pair<const_iterator, const_iterator>
    500       equal_range(const key_type& __key) const
    501       {
    502 	typedef typename _Base::const_iterator _Base_iterator;
    503 	typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
    504 	__pair_type __res = _Base::equal_range(__key);
    505 	return std::make_pair(const_iterator(__res.first, this),
    506 			      const_iterator(__res.second, this));
    507       }
    508 
    509       size_type
    510       erase(const key_type& __key)
    511       {
    512 	size_type __ret(0);
    513 	iterator __victim(_Base::find(__key), this);
    514 	if (__victim != end())
    515 	  {
    516 	    this->erase(__victim);
    517 	    __ret = 1;
    518 	  }
    519 	return __ret;
    520       }
    521 
    522       iterator
    523       erase(iterator __it)
    524       {
    525 	__glibcxx_check_erase(__it);
    526 	__it._M_invalidate();
    527 	return iterator(_Base::erase(__it.base()), this);
    528       }
    529 
    530       const_iterator
    531       erase(const_iterator __it)
    532       {
    533 	__glibcxx_check_erase(__it);
    534 	__it._M_invalidate();
    535 	return const_iterator(_Base::erase(__it.base()), this);
    536       }
    537 
    538       iterator
    539       erase(iterator __first, iterator __last)
    540       {
    541 	__glibcxx_check_erase_range(__first, __last);
    542 	for (iterator __tmp = __first; __tmp != __last;)
    543 	{
    544 	  iterator __victim = __tmp++;
    545 	  __victim._M_invalidate();
    546 	}
    547 	return iterator(_Base::erase(__first.base(),
    548 				     __last.base()), this);
    549       }
    550 
    551       const_iterator
    552       erase(const_iterator __first, const_iterator __last)
    553       {
    554 	__glibcxx_check_erase_range(__first, __last);
    555 	for (const_iterator __tmp = __first; __tmp != __last;)
    556 	{
    557 	  const_iterator __victim = __tmp++;
    558 	  __victim._M_invalidate();
    559 	}
    560 	return const_iterator(_Base::erase(__first.base(),
    561 					   __last.base()), this);
    562       }
    563 
    564       _Base&
    565       _M_base() { return *this; }
    566 
    567       const _Base&
    568       _M_base() const { return *this; }
    569 
    570     private:
    571       void
    572       _M_invalidate_all()
    573       {
    574 	typedef typename _Base::const_iterator _Base_const_iterator;
    575 	typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
    576 	this->_M_invalidate_if(_Not_equal(_M_base().end()));
    577       }
    578     };
    579 
    580   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
    581     inline void
    582     swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
    583 	 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
    584     { __x.swap(__y); }
    585 
    586   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
    587     inline void
    588     swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>&& __x,
    589 	 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
    590     { __x.swap(__y); }
    591 
    592   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
    593     inline void
    594     swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
    595 	 unordered_multiset<_Value, _Hash, _Pred, _Alloc>&& __y)
    596     { __x.swap(__y); }
    597 
    598 } // namespace __debug
    599 } // namespace std
    600 
    601 #endif
    602