libstdc++
stl_multiset.h
Go to the documentation of this file.
00001 // Multiset implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
00004 // 2011 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 /*
00027  *
00028  * Copyright (c) 1994
00029  * Hewlett-Packard Company
00030  *
00031  * Permission to use, copy, modify, distribute and sell this software
00032  * and its documentation for any purpose is hereby granted without fee,
00033  * provided that the above copyright notice appear in all copies and
00034  * that both that copyright notice and this permission notice appear
00035  * in supporting documentation.  Hewlett-Packard Company makes no
00036  * representations about the suitability of this software for any
00037  * purpose.  It is provided "as is" without express or implied warranty.
00038  *
00039  *
00040  * Copyright (c) 1996
00041  * Silicon Graphics Computer Systems, Inc.
00042  *
00043  * Permission to use, copy, modify, distribute and sell this software
00044  * and its documentation for any purpose is hereby granted without fee,
00045  * provided that the above copyright notice appear in all copies and
00046  * that both that copyright notice and this permission notice appear
00047  * in supporting documentation.  Silicon Graphics makes no
00048  * representations about the suitability of this software for any
00049  * purpose.  It is provided "as is" without express or implied warranty.
00050  */
00051 
00052 /** @file bits/stl_multiset.h
00053  *  This is an internal header file, included by other library headers.
00054  *  Do not attempt to use it directly. @headername{set}
00055  */
00056 
00057 #ifndef _STL_MULTISET_H
00058 #define _STL_MULTISET_H 1
00059 
00060 #include <bits/concept_check.h>
00061 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00062 #include <initializer_list>
00063 #endif
00064 
00065 namespace std _GLIBCXX_VISIBILITY(default)
00066 {
00067 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
00068 
00069   /**
00070    *  @brief A standard container made up of elements, which can be retrieved
00071    *  in logarithmic time.
00072    *
00073    *  @ingroup associative_containers
00074    *
00075    *
00076    *  @tparam _Key  Type of key objects.
00077    *  @tparam _Compare  Comparison function object type, defaults to less<_Key>.
00078    *  @tparam _Alloc  Allocator type, defaults to allocator<_Key>.
00079    *
00080    *  Meets the requirements of a <a href="tables.html#65">container</a>, a
00081    *  <a href="tables.html#66">reversible container</a>, and an
00082    *  <a href="tables.html#69">associative container</a> (using equivalent
00083    *  keys).  For a @c multiset<Key> the key_type and value_type are Key.
00084    *
00085    *  Multisets support bidirectional iterators.
00086    *
00087    *  The private tree data is declared exactly the same way for set and
00088    *  multiset; the distinction is made entirely in how the tree functions are
00089    *  called (*_unique versus *_equal, same as the standard).
00090   */
00091   template <typename _Key, typename _Compare = std::less<_Key>,
00092         typename _Alloc = std::allocator<_Key> >
00093     class multiset
00094     {
00095       // concept requirements
00096       typedef typename _Alloc::value_type                   _Alloc_value_type;
00097       __glibcxx_class_requires(_Key, _SGIAssignableConcept)
00098       __glibcxx_class_requires4(_Compare, bool, _Key, _Key,
00099                 _BinaryFunctionConcept)
00100       __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept)  
00101 
00102     public:
00103       // typedefs:
00104       typedef _Key     key_type;
00105       typedef _Key     value_type;
00106       typedef _Compare key_compare;
00107       typedef _Compare value_compare;
00108       typedef _Alloc   allocator_type;
00109 
00110     private:
00111       /// This turns a red-black tree into a [multi]set.
00112       typedef typename _Alloc::template rebind<_Key>::other _Key_alloc_type;
00113 
00114       typedef _Rb_tree<key_type, value_type, _Identity<value_type>,
00115                key_compare, _Key_alloc_type> _Rep_type;
00116       /// The actual tree structure.
00117       _Rep_type _M_t;
00118 
00119     public:
00120       typedef typename _Key_alloc_type::pointer             pointer;
00121       typedef typename _Key_alloc_type::const_pointer       const_pointer;
00122       typedef typename _Key_alloc_type::reference           reference;
00123       typedef typename _Key_alloc_type::const_reference     const_reference;
00124       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00125       // DR 103. set::iterator is required to be modifiable,
00126       // but this allows modification of keys.
00127       typedef typename _Rep_type::const_iterator            iterator;
00128       typedef typename _Rep_type::const_iterator            const_iterator;
00129       typedef typename _Rep_type::const_reverse_iterator    reverse_iterator;
00130       typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
00131       typedef typename _Rep_type::size_type                 size_type;
00132       typedef typename _Rep_type::difference_type           difference_type;
00133 
00134       // allocation/deallocation
00135       /**
00136        *  @brief  Default constructor creates no elements.
00137        */
00138       multiset()
00139       : _M_t() { }
00140 
00141       /**
00142        *  @brief  Creates a %multiset with no elements.
00143        *  @param  __comp  Comparator to use.
00144        *  @param  __a  An allocator object.
00145        */
00146       explicit
00147       multiset(const _Compare& __comp,
00148            const allocator_type& __a = allocator_type())
00149       : _M_t(__comp, _Key_alloc_type(__a)) { }
00150 
00151       /**
00152        *  @brief  Builds a %multiset from a range.
00153        *  @param  __first  An input iterator.
00154        *  @param  __last  An input iterator.
00155        *
00156        *  Create a %multiset consisting of copies of the elements from
00157        *  [first,last).  This is linear in N if the range is already sorted,
00158        *  and NlogN otherwise (where N is distance(__first,__last)).
00159        */
00160       template<typename _InputIterator>
00161         multiset(_InputIterator __first, _InputIterator __last)
00162     : _M_t()
00163         { _M_t._M_insert_equal(__first, __last); }
00164 
00165       /**
00166        *  @brief  Builds a %multiset from a range.
00167        *  @param  __first  An input iterator.
00168        *  @param  __last  An input iterator.
00169        *  @param  __comp  A comparison functor.
00170        *  @param  __a  An allocator object.
00171        *
00172        *  Create a %multiset consisting of copies of the elements from
00173        *  [__first,__last).  This is linear in N if the range is already sorted,
00174        *  and NlogN otherwise (where N is distance(__first,__last)).
00175        */
00176       template<typename _InputIterator>
00177         multiset(_InputIterator __first, _InputIterator __last,
00178          const _Compare& __comp,
00179          const allocator_type& __a = allocator_type())
00180     : _M_t(__comp, _Key_alloc_type(__a))
00181         { _M_t._M_insert_equal(__first, __last); }
00182 
00183       /**
00184        *  @brief  %Multiset copy constructor.
00185        *  @param  __x  A %multiset of identical element and allocator types.
00186        *
00187        *  The newly-created %multiset uses a copy of the allocation object used
00188        *  by @a __x.
00189        */
00190       multiset(const multiset& __x)
00191       : _M_t(__x._M_t) { }
00192 
00193 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00194      /**
00195        *  @brief  %Multiset move constructor.
00196        *  @param  __x  A %multiset of identical element and allocator types.
00197        *
00198        *  The newly-created %multiset contains the exact contents of @a __x.
00199        *  The contents of @a __x are a valid, but unspecified %multiset.
00200        */
00201       multiset(multiset&& __x)
00202       noexcept(is_nothrow_copy_constructible<_Compare>::value)
00203       : _M_t(std::move(__x._M_t)) { }
00204 
00205       /**
00206        *  @brief  Builds a %multiset from an initializer_list.
00207        *  @param  __l  An initializer_list.
00208        *  @param  __comp  A comparison functor.
00209        *  @param  __a  An allocator object.
00210        *
00211        *  Create a %multiset consisting of copies of the elements from
00212        *  the list.  This is linear in N if the list is already sorted,
00213        *  and NlogN otherwise (where N is @a __l.size()).
00214        */
00215       multiset(initializer_list<value_type> __l,
00216            const _Compare& __comp = _Compare(),
00217            const allocator_type& __a = allocator_type())
00218       : _M_t(__comp, _Key_alloc_type(__a))
00219       { _M_t._M_insert_equal(__l.begin(), __l.end()); }
00220 #endif
00221 
00222       /**
00223        *  @brief  %Multiset assignment operator.
00224        *  @param  __x  A %multiset of identical element and allocator types.
00225        *
00226        *  All the elements of @a __x are copied, but unlike the copy
00227        *  constructor, the allocator object is not copied.
00228        */
00229       multiset&
00230       operator=(const multiset& __x)
00231       {
00232     _M_t = __x._M_t;
00233     return *this;
00234       }
00235 
00236 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00237       /**
00238        *  @brief  %Multiset move assignment operator.
00239        *  @param  __x  A %multiset of identical element and allocator types.
00240        *
00241        *  The contents of @a __x are moved into this %multiset
00242        *  (without copying).  @a __x is a valid, but unspecified
00243        *  %multiset.
00244        */
00245       multiset&
00246       operator=(multiset&& __x)
00247       {
00248     // NB: DR 1204.
00249     // NB: DR 675.
00250     this->clear();
00251     this->swap(__x);
00252     return *this;
00253       }
00254 
00255       /**
00256        *  @brief  %Multiset list assignment operator.
00257        *  @param  __l  An initializer_list.
00258        *
00259        *  This function fills a %multiset with copies of the elements in the
00260        *  initializer list @a __l.
00261        *
00262        *  Note that the assignment completely changes the %multiset and
00263        *  that the resulting %multiset's size is the same as the number
00264        *  of elements assigned.  Old data may be lost.
00265        */
00266       multiset&
00267       operator=(initializer_list<value_type> __l)
00268       {
00269     this->clear();
00270     this->insert(__l.begin(), __l.end());
00271     return *this;
00272       }
00273 #endif
00274 
00275       // accessors:
00276 
00277       ///  Returns the comparison object.
00278       key_compare
00279       key_comp() const
00280       { return _M_t.key_comp(); }
00281       ///  Returns the comparison object.
00282       value_compare
00283       value_comp() const
00284       { return _M_t.key_comp(); }
00285       ///  Returns the memory allocation object.
00286       allocator_type
00287       get_allocator() const _GLIBCXX_NOEXCEPT
00288       { return allocator_type(_M_t.get_allocator()); }
00289 
00290       /**
00291        *  Returns a read-only (constant) iterator that points to the first
00292        *  element in the %multiset.  Iteration is done in ascending order
00293        *  according to the keys.
00294        */
00295       iterator
00296       begin() const _GLIBCXX_NOEXCEPT
00297       { return _M_t.begin(); }
00298 
00299       /**
00300        *  Returns a read-only (constant) iterator that points one past the last
00301        *  element in the %multiset.  Iteration is done in ascending order
00302        *  according to the keys.
00303        */
00304       iterator
00305       end() const _GLIBCXX_NOEXCEPT
00306       { return _M_t.end(); }
00307 
00308       /**
00309        *  Returns a read-only (constant) reverse iterator that points to the
00310        *  last element in the %multiset.  Iteration is done in descending order
00311        *  according to the keys.
00312        */
00313       reverse_iterator
00314       rbegin() const _GLIBCXX_NOEXCEPT
00315       { return _M_t.rbegin(); }
00316 
00317       /**
00318        *  Returns a read-only (constant) reverse iterator that points to the
00319        *  last element in the %multiset.  Iteration is done in descending order
00320        *  according to the keys.
00321        */
00322       reverse_iterator
00323       rend() const _GLIBCXX_NOEXCEPT
00324       { return _M_t.rend(); }
00325 
00326 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00327       /**
00328        *  Returns a read-only (constant) iterator that points to the first
00329        *  element in the %multiset.  Iteration is done in ascending order
00330        *  according to the keys.
00331        */
00332       iterator
00333       cbegin() const noexcept
00334       { return _M_t.begin(); }
00335 
00336       /**
00337        *  Returns a read-only (constant) iterator that points one past the last
00338        *  element in the %multiset.  Iteration is done in ascending order
00339        *  according to the keys.
00340        */
00341       iterator
00342       cend() const noexcept
00343       { return _M_t.end(); }
00344 
00345       /**
00346        *  Returns a read-only (constant) reverse iterator that points to the
00347        *  last element in the %multiset.  Iteration is done in descending order
00348        *  according to the keys.
00349        */
00350       reverse_iterator
00351       crbegin() const noexcept
00352       { return _M_t.rbegin(); }
00353 
00354       /**
00355        *  Returns a read-only (constant) reverse iterator that points to the
00356        *  last element in the %multiset.  Iteration is done in descending order
00357        *  according to the keys.
00358        */
00359       reverse_iterator
00360       crend() const noexcept
00361       { return _M_t.rend(); }
00362 #endif
00363 
00364       ///  Returns true if the %set is empty.
00365       bool
00366       empty() const _GLIBCXX_NOEXCEPT
00367       { return _M_t.empty(); }
00368 
00369       ///  Returns the size of the %set.
00370       size_type
00371       size() const _GLIBCXX_NOEXCEPT
00372       { return _M_t.size(); }
00373 
00374       ///  Returns the maximum size of the %set.
00375       size_type
00376       max_size() const _GLIBCXX_NOEXCEPT
00377       { return _M_t.max_size(); }
00378 
00379       /**
00380        *  @brief  Swaps data with another %multiset.
00381        *  @param  __x  A %multiset of the same element and allocator types.
00382        *
00383        *  This exchanges the elements between two multisets in constant time.
00384        *  (It is only swapping a pointer, an integer, and an instance of the @c
00385        *  Compare type (which itself is often stateless and empty), so it should
00386        *  be quite fast.)
00387        *  Note that the global std::swap() function is specialized such that
00388        *  std::swap(s1,s2) will feed to this function.
00389        */
00390       void
00391       swap(multiset& __x)
00392       { _M_t.swap(__x._M_t); }
00393 
00394       // insert/erase
00395       /**
00396        *  @brief Inserts an element into the %multiset.
00397        *  @param  __x  Element to be inserted.
00398        *  @return An iterator that points to the inserted element.
00399        *
00400        *  This function inserts an element into the %multiset.  Contrary
00401        *  to a std::set the %multiset does not rely on unique keys and thus
00402        *  multiple copies of the same element can be inserted.
00403        *
00404        *  Insertion requires logarithmic time.
00405        */
00406       iterator
00407       insert(const value_type& __x)
00408       { return _M_t._M_insert_equal(__x); }
00409 
00410 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00411       iterator
00412       insert(value_type&& __x)
00413       { return _M_t._M_insert_equal(std::move(__x)); }
00414 #endif
00415 
00416       /**
00417        *  @brief Inserts an element into the %multiset.
00418        *  @param  __position  An iterator that serves as a hint as to where the
00419        *                    element should be inserted.
00420        *  @param  __x  Element to be inserted.
00421        *  @return An iterator that points to the inserted element.
00422        *
00423        *  This function inserts an element into the %multiset.  Contrary
00424        *  to a std::set the %multiset does not rely on unique keys and thus
00425        *  multiple copies of the same element can be inserted.
00426        *
00427        *  Note that the first parameter is only a hint and can potentially
00428        *  improve the performance of the insertion process.  A bad hint would
00429        *  cause no gains in efficiency.
00430        *
00431        *  See http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt07ch17.html
00432        *  for more on @a hinting.
00433        *
00434        *  Insertion requires logarithmic time (if the hint is not taken).
00435        */
00436       iterator
00437       insert(const_iterator __position, const value_type& __x)
00438       { return _M_t._M_insert_equal_(__position, __x); }
00439 
00440 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00441       iterator
00442       insert(const_iterator __position, value_type&& __x)
00443       { return _M_t._M_insert_equal_(__position, std::move(__x)); }
00444 #endif
00445 
00446       /**
00447        *  @brief A template function that tries to insert a range of elements.
00448        *  @param  __first  Iterator pointing to the start of the range to be
00449        *                   inserted.
00450        *  @param  __last  Iterator pointing to the end of the range.
00451        *
00452        *  Complexity similar to that of the range constructor.
00453        */
00454       template<typename _InputIterator>
00455         void
00456         insert(_InputIterator __first, _InputIterator __last)
00457         { _M_t._M_insert_equal(__first, __last); }
00458 
00459 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00460       /**
00461        *  @brief Attempts to insert a list of elements into the %multiset.
00462        *  @param  __l  A std::initializer_list<value_type> of elements
00463        *               to be inserted.
00464        *
00465        *  Complexity similar to that of the range constructor.
00466        */
00467       void
00468       insert(initializer_list<value_type> __l)
00469       { this->insert(__l.begin(), __l.end()); }
00470 #endif
00471 
00472 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00473       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00474       // DR 130. Associative erase should return an iterator.
00475       /**
00476        *  @brief Erases an element from a %multiset.
00477        *  @param  __position  An iterator pointing to the element to be erased.
00478        *  @return An iterator pointing to the element immediately following
00479        *          @a position prior to the element being erased. If no such 
00480        *          element exists, end() is returned.
00481        *
00482        *  This function erases an element, pointed to by the given iterator,
00483        *  from a %multiset.  Note that this function only erases the element,
00484        *  and that if the element is itself a pointer, the pointed-to memory is
00485        *  not touched in any way.  Managing the pointer is the user's
00486        *  responsibility.
00487        */
00488       iterator
00489       erase(const_iterator __position)
00490       { return _M_t.erase(__position); }
00491 #else
00492       /**
00493        *  @brief Erases an element from a %multiset.
00494        *  @param  __position  An iterator pointing to the element to be erased.
00495        *
00496        *  This function erases an element, pointed to by the given iterator,
00497        *  from a %multiset.  Note that this function only erases the element,
00498        *  and that if the element is itself a pointer, the pointed-to memory is
00499        *  not touched in any way.  Managing the pointer is the user's
00500        *  responsibility.
00501        */
00502       void
00503       erase(iterator __position)
00504       { _M_t.erase(__position); }
00505 #endif
00506 
00507       /**
00508        *  @brief Erases elements according to the provided key.
00509        *  @param  __x  Key of element to be erased.
00510        *  @return  The number of elements erased.
00511        *
00512        *  This function erases all elements located by the given key from a
00513        *  %multiset.
00514        *  Note that this function only erases the element, and that if
00515        *  the element is itself a pointer, the pointed-to memory is not touched
00516        *  in any way.  Managing the pointer is the user's responsibility.
00517        */
00518       size_type
00519       erase(const key_type& __x)
00520       { return _M_t.erase(__x); }
00521 
00522 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00523       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00524       // DR 130. Associative erase should return an iterator.
00525       /**
00526        *  @brief Erases a [first,last) range of elements from a %multiset.
00527        *  @param  __first  Iterator pointing to the start of the range to be
00528        *                   erased.
00529        *  @param __last Iterator pointing to the end of the range to
00530        *                be erased.
00531        *  @return The iterator @a last.
00532        *
00533        *  This function erases a sequence of elements from a %multiset.
00534        *  Note that this function only erases the elements, and that if
00535        *  the elements themselves are pointers, the pointed-to memory is not
00536        *  touched in any way.  Managing the pointer is the user's
00537        *  responsibility.
00538        */
00539       iterator
00540       erase(const_iterator __first, const_iterator __last)
00541       { return _M_t.erase(__first, __last); }
00542 #else
00543       /**
00544        *  @brief Erases a [first,last) range of elements from a %multiset.
00545        *  @param  first  Iterator pointing to the start of the range to be
00546        *                 erased.
00547        *  @param  last  Iterator pointing to the end of the range to be erased.
00548        *
00549        *  This function erases a sequence of elements from a %multiset.
00550        *  Note that this function only erases the elements, and that if
00551        *  the elements themselves are pointers, the pointed-to memory is not
00552        *  touched in any way.  Managing the pointer is the user's
00553        *  responsibility.
00554        */
00555       void
00556       erase(iterator __first, iterator __last)
00557       { _M_t.erase(__first, __last); }
00558 #endif
00559 
00560       /**
00561        *  Erases all elements in a %multiset.  Note that this function only
00562        *  erases the elements, and that if the elements themselves are pointers,
00563        *  the pointed-to memory is not touched in any way.  Managing the pointer
00564        *  is the user's responsibility.
00565        */
00566       void
00567       clear() _GLIBCXX_NOEXCEPT
00568       { _M_t.clear(); }
00569 
00570       // multiset operations:
00571 
00572       /**
00573        *  @brief Finds the number of elements with given key.
00574        *  @param  __x  Key of elements to be located.
00575        *  @return Number of elements with specified key.
00576        */
00577       size_type
00578       count(const key_type& __x) const
00579       { return _M_t.count(__x); }
00580 
00581       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00582       // 214.  set::find() missing const overload
00583       //@{
00584       /**
00585        *  @brief Tries to locate an element in a %set.
00586        *  @param  __x  Element to be located.
00587        *  @return  Iterator pointing to sought-after element, or end() if not
00588        *           found.
00589        *
00590        *  This function takes a key and tries to locate the element with which
00591        *  the key matches.  If successful the function returns an iterator
00592        *  pointing to the sought after element.  If unsuccessful it returns the
00593        *  past-the-end ( @c end() ) iterator.
00594        */
00595       iterator
00596       find(const key_type& __x)
00597       { return _M_t.find(__x); }
00598 
00599       const_iterator
00600       find(const key_type& __x) const
00601       { return _M_t.find(__x); }
00602       //@}
00603 
00604       //@{
00605       /**
00606        *  @brief Finds the beginning of a subsequence matching given key.
00607        *  @param  __x  Key to be located.
00608        *  @return  Iterator pointing to first element equal to or greater
00609        *           than key, or end().
00610        *
00611        *  This function returns the first element of a subsequence of elements
00612        *  that matches the given key.  If unsuccessful it returns an iterator
00613        *  pointing to the first element that has a greater value than given key
00614        *  or end() if no such element exists.
00615        */
00616       iterator
00617       lower_bound(const key_type& __x)
00618       { return _M_t.lower_bound(__x); }
00619 
00620       const_iterator
00621       lower_bound(const key_type& __x) const
00622       { return _M_t.lower_bound(__x); }
00623       //@}
00624 
00625       //@{
00626       /**
00627        *  @brief Finds the end of a subsequence matching given key.
00628        *  @param  __x  Key to be located.
00629        *  @return Iterator pointing to the first element
00630        *          greater than key, or end().
00631        */
00632       iterator
00633       upper_bound(const key_type& __x)
00634       { return _M_t.upper_bound(__x); }
00635 
00636       const_iterator
00637       upper_bound(const key_type& __x) const
00638       { return _M_t.upper_bound(__x); }
00639       //@}
00640 
00641       //@{
00642       /**
00643        *  @brief Finds a subsequence matching given key.
00644        *  @param  __x  Key to be located.
00645        *  @return  Pair of iterators that possibly points to the subsequence
00646        *           matching given key.
00647        *
00648        *  This function is equivalent to
00649        *  @code
00650        *    std::make_pair(c.lower_bound(val),
00651        *                   c.upper_bound(val))
00652        *  @endcode
00653        *  (but is faster than making the calls separately).
00654        *
00655        *  This function probably only makes sense for multisets.
00656        */
00657       std::pair<iterator, iterator>
00658       equal_range(const key_type& __x)
00659       { return _M_t.equal_range(__x); }
00660 
00661       std::pair<const_iterator, const_iterator>
00662       equal_range(const key_type& __x) const
00663       { return _M_t.equal_range(__x); }
00664       //@}
00665 
00666       template<typename _K1, typename _C1, typename _A1>
00667         friend bool
00668         operator==(const multiset<_K1, _C1, _A1>&,
00669            const multiset<_K1, _C1, _A1>&);
00670 
00671       template<typename _K1, typename _C1, typename _A1>
00672         friend bool
00673         operator< (const multiset<_K1, _C1, _A1>&,
00674            const multiset<_K1, _C1, _A1>&);
00675     };
00676 
00677   /**
00678    *  @brief  Multiset equality comparison.
00679    *  @param  __x  A %multiset.
00680    *  @param  __y  A %multiset of the same type as @a __x.
00681    *  @return  True iff the size and elements of the multisets are equal.
00682    *
00683    *  This is an equivalence relation.  It is linear in the size of the
00684    *  multisets.
00685    *  Multisets are considered equivalent if their sizes are equal, and if
00686    *  corresponding elements compare equal.
00687   */
00688   template<typename _Key, typename _Compare, typename _Alloc>
00689     inline bool
00690     operator==(const multiset<_Key, _Compare, _Alloc>& __x,
00691            const multiset<_Key, _Compare, _Alloc>& __y)
00692     { return __x._M_t == __y._M_t; }
00693 
00694   /**
00695    *  @brief  Multiset ordering relation.
00696    *  @param  __x  A %multiset.
00697    *  @param  __y  A %multiset of the same type as @a __x.
00698    *  @return  True iff @a __x is lexicographically less than @a __y.
00699    *
00700    *  This is a total ordering relation.  It is linear in the size of the
00701    *  maps.  The elements must be comparable with @c <.
00702    *
00703    *  See std::lexicographical_compare() for how the determination is made.
00704   */
00705   template<typename _Key, typename _Compare, typename _Alloc>
00706     inline bool
00707     operator<(const multiset<_Key, _Compare, _Alloc>& __x,
00708           const multiset<_Key, _Compare, _Alloc>& __y)
00709     { return __x._M_t < __y._M_t; }
00710 
00711   ///  Returns !(x == y).
00712   template<typename _Key, typename _Compare, typename _Alloc>
00713     inline bool
00714     operator!=(const multiset<_Key, _Compare, _Alloc>& __x,
00715            const multiset<_Key, _Compare, _Alloc>& __y)
00716     { return !(__x == __y); }
00717 
00718   ///  Returns y < x.
00719   template<typename _Key, typename _Compare, typename _Alloc>
00720     inline bool
00721     operator>(const multiset<_Key,_Compare,_Alloc>& __x,
00722           const multiset<_Key,_Compare,_Alloc>& __y)
00723     { return __y < __x; }
00724 
00725   ///  Returns !(y < x)
00726   template<typename _Key, typename _Compare, typename _Alloc>
00727     inline bool
00728     operator<=(const multiset<_Key, _Compare, _Alloc>& __x,
00729            const multiset<_Key, _Compare, _Alloc>& __y)
00730     { return !(__y < __x); }
00731 
00732   ///  Returns !(x < y)
00733   template<typename _Key, typename _Compare, typename _Alloc>
00734     inline bool
00735     operator>=(const multiset<_Key, _Compare, _Alloc>& __x,
00736            const multiset<_Key, _Compare, _Alloc>& __y)
00737     { return !(__x < __y); }
00738 
00739   /// See std::multiset::swap().
00740   template<typename _Key, typename _Compare, typename _Alloc>
00741     inline void
00742     swap(multiset<_Key, _Compare, _Alloc>& __x,
00743      multiset<_Key, _Compare, _Alloc>& __y)
00744     { __x.swap(__y); }
00745 
00746 _GLIBCXX_END_NAMESPACE_CONTAINER
00747 } // namespace std
00748 
00749 #endif /* _STL_MULTISET_H */