Home | History | Annotate | Line # | Download | only in backward
      1 // Hashing set implementation -*- C++ -*-
      2 
      3 // Copyright (C) 2001-2024 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /*
     26  * Copyright (c) 1996
     27  * Silicon Graphics Computer Systems, Inc.
     28  *
     29  * Permission to use, copy, modify, distribute and sell this software
     30  * and its documentation for any purpose is hereby granted without fee,
     31  * provided that the above copyright notice appear in all copies and
     32  * that both that copyright notice and this permission notice appear
     33  * in supporting documentation.  Silicon Graphics makes no
     34  * representations about the suitability of this software for any
     35  * purpose.  It is provided "as is" without express or implied warranty.
     36  *
     37  *
     38  * Copyright (c) 1994
     39  * Hewlett-Packard Company
     40  *
     41  * Permission to use, copy, modify, distribute and sell this software
     42  * and its documentation for any purpose is hereby granted without fee,
     43  * provided that the above copyright notice appear in all copies and
     44  * that both that copyright notice and this permission notice appear
     45  * in supporting documentation.  Hewlett-Packard Company makes no
     46  * representations about the suitability of this software for any
     47  * purpose.  It is provided "as is" without express or implied warranty.
     48  *
     49  */
     50 
     51 /** @file backward/hash_set
     52  *  This file is a GNU extension to the Standard C++ Library (possibly
     53  *  containing extensions from the HP/SGI STL subset).
     54  */
     55 
     56 #ifndef _BACKWARD_HASH_SET
     57 #define _BACKWARD_HASH_SET 1
     58 
     59 #ifndef _GLIBCXX_PERMIT_BACKWARD_HASH
     60 #include <backward/backward_warning.h>
     61 #endif
     62 
     63 #include <bits/c++config.h>
     64 #include <backward/hashtable.h>
     65 #include <bits/concept_check.h>
     66 
     67 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
     68 {
     69 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     70 
     71   using std::equal_to;
     72   using std::allocator;
     73   using std::pair;
     74   using std::_Identity;
     75 
     76   /**
     77    *  This is an SGI extension.
     78    *  @ingroup SGIextensions
     79    *  @doctodo
     80    */
     81   template<class _Value, class _HashFcn  = hash<_Value>,
     82 	   class _EqualKey = equal_to<_Value>,
     83 	   class _Alloc = allocator<_Value> >
     84     class hash_set
     85     {
     86       // concept requirements
     87       __glibcxx_class_requires(_Value, _SGIAssignableConcept)
     88       __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept)
     89       __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept)
     90 
     91       typedef __alloc_traits<_Alloc> _Alloc_traits;
     92 
     93     private:
     94       typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>,
     95 			_EqualKey, _Alloc> _Ht;
     96       _Ht _M_ht;
     97 
     98     public:
     99       typedef typename _Ht::key_type key_type;
    100       typedef typename _Ht::value_type value_type;
    101       typedef typename _Ht::hasher hasher;
    102       typedef typename _Ht::key_equal key_equal;
    103       
    104       typedef typename _Ht::size_type size_type;
    105       typedef typename _Ht::difference_type difference_type;
    106       typedef typename _Alloc_traits::pointer pointer;
    107       typedef typename _Alloc_traits::const_pointer const_pointer;
    108       typedef typename _Alloc_traits::reference reference;
    109       typedef typename _Alloc_traits::const_reference const_reference;
    110       
    111       typedef typename _Ht::const_iterator iterator;
    112       typedef typename _Ht::const_iterator const_iterator;
    113       
    114       typedef typename _Ht::allocator_type allocator_type;
    115       
    116       hasher
    117       hash_funct() const
    118       { return _M_ht.hash_funct(); }
    119 
    120       key_equal
    121       key_eq() const
    122       { return _M_ht.key_eq(); }
    123 
    124       allocator_type
    125       get_allocator() const
    126       { return _M_ht.get_allocator(); }
    127 
    128       hash_set()
    129       : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
    130 
    131       explicit
    132       hash_set(size_type __n)
    133       : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
    134 
    135       hash_set(size_type __n, const hasher& __hf)
    136       : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
    137 
    138       hash_set(size_type __n, const hasher& __hf, const key_equal& __eql,
    139 	       const allocator_type& __a = allocator_type())
    140       : _M_ht(__n, __hf, __eql, __a) {}
    141 
    142       template<class _InputIterator>
    143         hash_set(_InputIterator __f, _InputIterator __l)
    144 	: _M_ht(100, hasher(), key_equal(), allocator_type())
    145         { _M_ht.insert_unique(__f, __l); }
    146 
    147       template<class _InputIterator>
    148         hash_set(_InputIterator __f, _InputIterator __l, size_type __n)
    149 	: _M_ht(__n, hasher(), key_equal(), allocator_type())
    150         { _M_ht.insert_unique(__f, __l); }
    151 
    152       template<class _InputIterator>
    153         hash_set(_InputIterator __f, _InputIterator __l, size_type __n,
    154 		 const hasher& __hf)
    155 	: _M_ht(__n, __hf, key_equal(), allocator_type())
    156         { _M_ht.insert_unique(__f, __l); }
    157 
    158       template<class _InputIterator>
    159         hash_set(_InputIterator __f, _InputIterator __l, size_type __n,
    160 		 const hasher& __hf, const key_equal& __eql,
    161 		 const allocator_type& __a = allocator_type())
    162 	: _M_ht(__n, __hf, __eql, __a)
    163         { _M_ht.insert_unique(__f, __l); }
    164 
    165       size_type
    166       size() const
    167       { return _M_ht.size(); }
    168 
    169       size_type
    170       max_size() const
    171       { return _M_ht.max_size(); }
    172       
    173       _GLIBCXX_NODISCARD bool
    174       empty() const
    175       { return _M_ht.empty(); }
    176       
    177       void
    178       swap(hash_set& __hs)
    179       { _M_ht.swap(__hs._M_ht); }
    180 
    181       template<class _Val, class _HF, class _EqK, class _Al>
    182         friend bool
    183         operator==(const hash_set<_Val, _HF, _EqK, _Al>&,
    184 		   const hash_set<_Val, _HF, _EqK, _Al>&);
    185 
    186       iterator
    187       begin() const
    188       { return _M_ht.begin(); }
    189       
    190       iterator
    191       end() const
    192       { return _M_ht.end(); }
    193 
    194       pair<iterator, bool>
    195       insert(const value_type& __obj)
    196       {
    197 	pair<typename _Ht::iterator, bool> __p = _M_ht.insert_unique(__obj);
    198 	return pair<iterator,bool>(__p.first, __p.second);
    199       }
    200 
    201       template<class _InputIterator>
    202         void
    203         insert(_InputIterator __f, _InputIterator __l)
    204         { _M_ht.insert_unique(__f, __l); }
    205 
    206       pair<iterator, bool>
    207       insert_noresize(const value_type& __obj)
    208       {
    209 	pair<typename _Ht::iterator, bool> __p
    210 	  = _M_ht.insert_unique_noresize(__obj);
    211 	return pair<iterator, bool>(__p.first, __p.second);
    212       }
    213 
    214       iterator
    215       find(const key_type& __key) const
    216       { return _M_ht.find(__key); }
    217 
    218       size_type
    219       count(const key_type& __key) const
    220       { return _M_ht.count(__key); }
    221 
    222       pair<iterator, iterator>
    223       equal_range(const key_type& __key) const
    224       { return _M_ht.equal_range(__key); }
    225 
    226       size_type
    227       erase(const key_type& __key)
    228       {return _M_ht.erase(__key); }
    229       
    230       void
    231       erase(iterator __it)
    232       { _M_ht.erase(__it); }
    233       
    234       void
    235       erase(iterator __f, iterator __l)
    236       { _M_ht.erase(__f, __l); }
    237       
    238       void
    239       clear()
    240       { _M_ht.clear(); }
    241 
    242       void
    243       resize(size_type __hint)
    244       { _M_ht.resize(__hint); }
    245       
    246       size_type
    247       bucket_count() const
    248       { return _M_ht.bucket_count(); }
    249       
    250       size_type
    251       max_bucket_count() const
    252       { return _M_ht.max_bucket_count(); }
    253       
    254       size_type
    255       elems_in_bucket(size_type __n) const
    256       { return _M_ht.elems_in_bucket(__n); }
    257     };
    258 
    259   template<class _Value, class _HashFcn, class _EqualKey, class _Alloc>
    260     inline bool
    261     operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1,
    262 	       const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2)
    263     { return __hs1._M_ht == __hs2._M_ht; }
    264 
    265   template<class _Value, class _HashFcn, class _EqualKey, class _Alloc>
    266     inline bool
    267     operator!=(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1,
    268 	       const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2)
    269     { return !(__hs1 == __hs2); }
    270 
    271   template<class _Val, class _HashFcn, class _EqualKey, class _Alloc>
    272     inline void
    273     swap(hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
    274 	 hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2)
    275     { __hs1.swap(__hs2); }
    276 
    277 
    278   /**
    279    *  This is an SGI extension.
    280    *  @ingroup SGIextensions
    281    *  @doctodo
    282    */
    283   template<class _Value,
    284 	   class _HashFcn = hash<_Value>,
    285 	   class _EqualKey = equal_to<_Value>,
    286 	   class _Alloc = allocator<_Value> >
    287     class hash_multiset
    288     {
    289       // concept requirements
    290       __glibcxx_class_requires(_Value, _SGIAssignableConcept)
    291       __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept)
    292       __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept)
    293 
    294     private:
    295       typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>,
    296 			_EqualKey, _Alloc> _Ht;
    297       _Ht _M_ht;
    298 
    299     public:
    300       typedef typename _Ht::key_type key_type;
    301       typedef typename _Ht::value_type value_type;
    302       typedef typename _Ht::hasher hasher;
    303       typedef typename _Ht::key_equal key_equal;
    304       
    305       typedef typename _Ht::size_type size_type;
    306       typedef typename _Ht::difference_type difference_type;
    307       typedef typename _Alloc::pointer pointer;
    308       typedef typename _Alloc::const_pointer const_pointer;
    309       typedef typename _Alloc::reference reference;
    310       typedef typename _Alloc::const_reference const_reference;
    311 
    312       typedef typename _Ht::const_iterator iterator;
    313       typedef typename _Ht::const_iterator const_iterator;
    314       
    315       typedef typename _Ht::allocator_type allocator_type;
    316       
    317       hasher
    318       hash_funct() const
    319       { return _M_ht.hash_funct(); }
    320       
    321       key_equal
    322       key_eq() const
    323       { return _M_ht.key_eq(); }
    324       
    325       allocator_type
    326       get_allocator() const
    327       { return _M_ht.get_allocator(); }
    328 
    329       hash_multiset()
    330       : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
    331 
    332       explicit
    333       hash_multiset(size_type __n)
    334       : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
    335 
    336       hash_multiset(size_type __n, const hasher& __hf)
    337       : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
    338       
    339       hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql,
    340 		    const allocator_type& __a = allocator_type())
    341       : _M_ht(__n, __hf, __eql, __a) {}
    342 
    343       template<class _InputIterator>
    344         hash_multiset(_InputIterator __f, _InputIterator __l)
    345 	: _M_ht(100, hasher(), key_equal(), allocator_type())
    346         { _M_ht.insert_equal(__f, __l); }
    347 
    348       template<class _InputIterator>
    349         hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n)
    350 	: _M_ht(__n, hasher(), key_equal(), allocator_type())
    351         { _M_ht.insert_equal(__f, __l); }
    352 
    353       template<class _InputIterator>
    354         hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n,
    355 		      const hasher& __hf)
    356 	: _M_ht(__n, __hf, key_equal(), allocator_type())
    357         { _M_ht.insert_equal(__f, __l); }
    358 
    359       template<class _InputIterator>
    360         hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n,
    361 		      const hasher& __hf, const key_equal& __eql,
    362 		      const allocator_type& __a = allocator_type())
    363 	: _M_ht(__n, __hf, __eql, __a)
    364         { _M_ht.insert_equal(__f, __l); }
    365 
    366       size_type
    367       size() const
    368       { return _M_ht.size(); }
    369 
    370       size_type
    371       max_size() const
    372       { return _M_ht.max_size(); }
    373 
    374       _GLIBCXX_NODISCARD bool
    375       empty() const
    376       { return _M_ht.empty(); }
    377 
    378       void
    379       swap(hash_multiset& hs)
    380       { _M_ht.swap(hs._M_ht); }
    381 
    382       template<class _Val, class _HF, class _EqK, class _Al>
    383         friend bool
    384         operator==(const hash_multiset<_Val, _HF, _EqK, _Al>&,
    385 		   const hash_multiset<_Val, _HF, _EqK, _Al>&);
    386 
    387       iterator
    388       begin() const
    389       { return _M_ht.begin(); }
    390       
    391       iterator
    392       end() const
    393       { return _M_ht.end(); }
    394 
    395       iterator
    396       insert(const value_type& __obj)
    397       { return _M_ht.insert_equal(__obj); }
    398   
    399       template<class _InputIterator>
    400         void
    401         insert(_InputIterator __f, _InputIterator __l)
    402         { _M_ht.insert_equal(__f,__l); }
    403   
    404       iterator
    405       insert_noresize(const value_type& __obj)
    406       { return _M_ht.insert_equal_noresize(__obj); }
    407 
    408       iterator
    409       find(const key_type& __key) const
    410       { return _M_ht.find(__key); }
    411 
    412       size_type
    413       count(const key_type& __key) const
    414       { return _M_ht.count(__key); }
    415 
    416       pair<iterator, iterator>
    417       equal_range(const key_type& __key) const
    418       { return _M_ht.equal_range(__key); }
    419 
    420       size_type
    421       erase(const key_type& __key)
    422       { return _M_ht.erase(__key); }
    423   
    424       void
    425       erase(iterator __it)
    426       { _M_ht.erase(__it); }
    427   
    428       void
    429       erase(iterator __f, iterator __l)
    430       { _M_ht.erase(__f, __l); }
    431   
    432       void
    433       clear()
    434       { _M_ht.clear(); }
    435 
    436       void
    437       resize(size_type __hint)
    438       { _M_ht.resize(__hint); }
    439   
    440       size_type
    441       bucket_count() const
    442       { return _M_ht.bucket_count(); }
    443 
    444       size_type
    445       max_bucket_count() const
    446       { return _M_ht.max_bucket_count(); }
    447 
    448       size_type
    449       elems_in_bucket(size_type __n) const
    450       { return _M_ht.elems_in_bucket(__n); }
    451     };
    452 
    453   template<class _Val, class _HashFcn, class _EqualKey, class _Alloc>
    454     inline bool
    455     operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
    456 	       const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2)
    457     { return __hs1._M_ht == __hs2._M_ht; }
    458 
    459   template<class _Val, class _HashFcn, class _EqualKey, class _Alloc>
    460     inline bool
    461     operator!=(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
    462 	       const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2)
    463     { return !(__hs1 == __hs2); }
    464 
    465   template<class _Val, class _HashFcn, class _EqualKey, class _Alloc>
    466     inline void
    467     swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
    468 	 hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2)
    469     { __hs1.swap(__hs2); }
    470 
    471 _GLIBCXX_END_NAMESPACE_VERSION
    472 } // namespace
    473 
    474 namespace std _GLIBCXX_VISIBILITY(default)
    475 {
    476 _GLIBCXX_BEGIN_NAMESPACE_VERSION
    477 
    478   // Specialization of insert_iterator so that it will work for hash_set
    479   // and hash_multiset.
    480   template<class _Value, class _HashFcn, class _EqualKey, class _Alloc>
    481     class insert_iterator<__gnu_cxx::hash_set<_Value, _HashFcn,
    482 					      _EqualKey, _Alloc> >
    483     {
    484     protected:
    485       typedef __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc>
    486         _Container;
    487       _Container* container;
    488 
    489     public:
    490       typedef _Container          container_type;
    491       typedef output_iterator_tag iterator_category;
    492       typedef void                value_type;
    493       typedef void                difference_type;
    494       typedef void                pointer;
    495       typedef void                reference;
    496 
    497       insert_iterator(_Container& __x)
    498       : container(&__x) {}
    499       
    500       insert_iterator(_Container& __x, typename _Container::iterator)
    501       : container(&__x) {}
    502 
    503       insert_iterator<_Container>&
    504       operator=(const typename _Container::value_type& __value)
    505       {
    506 	container->insert(__value);
    507 	return *this;
    508       }
    509 
    510       insert_iterator<_Container>&
    511       operator*()
    512       { return *this; }
    513       
    514       insert_iterator<_Container>&
    515       operator++()
    516       { return *this; }
    517       
    518       insert_iterator<_Container>&
    519       operator++(int)
    520       { return *this; }
    521     };
    522 
    523   template<class _Value, class _HashFcn, class _EqualKey, class _Alloc>
    524     class insert_iterator<__gnu_cxx::hash_multiset<_Value, _HashFcn,
    525 						   _EqualKey, _Alloc> >
    526     {
    527     protected:
    528       typedef __gnu_cxx::hash_multiset<_Value, _HashFcn, _EqualKey, _Alloc>
    529         _Container;
    530       _Container* container;
    531       typename _Container::iterator iter;
    532 
    533     public:
    534       typedef _Container          container_type;
    535       typedef output_iterator_tag iterator_category;
    536       typedef void                value_type;
    537       typedef void                difference_type;
    538       typedef void                pointer;
    539       typedef void                reference;
    540       
    541       insert_iterator(_Container& __x)
    542       : container(&__x) {}
    543       
    544       insert_iterator(_Container& __x, typename _Container::iterator)
    545       : container(&__x) {}
    546 
    547       insert_iterator<_Container>&
    548       operator=(const typename _Container::value_type& __value)
    549       {
    550 	container->insert(__value);
    551 	return *this;
    552       }
    553 
    554       insert_iterator<_Container>&
    555       operator*()
    556       { return *this; }
    557 
    558       insert_iterator<_Container>&
    559       operator++()
    560       { return *this; }
    561 
    562       insert_iterator<_Container>&
    563       operator++(int) { return *this; }
    564     };
    565 
    566 _GLIBCXX_END_NAMESPACE_VERSION
    567 } // namespace
    568 
    569 #endif
    570