1 // Multiset implementation -*- C++ -*- 2 3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 4 // 2011 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 /* 27 * 28 * Copyright (c) 1994 29 * Hewlett-Packard Company 30 * 31 * Permission to use, copy, modify, distribute and sell this software 32 * and its documentation for any purpose is hereby granted without fee, 33 * provided that the above copyright notice appear in all copies and 34 * that both that copyright notice and this permission notice appear 35 * in supporting documentation. Hewlett-Packard Company makes no 36 * representations about the suitability of this software for any 37 * purpose. It is provided "as is" without express or implied warranty. 38 * 39 * 40 * Copyright (c) 1996 41 * Silicon Graphics Computer Systems, Inc. 42 * 43 * Permission to use, copy, modify, distribute and sell this software 44 * and its documentation for any purpose is hereby granted without fee, 45 * provided that the above copyright notice appear in all copies and 46 * that both that copyright notice and this permission notice appear 47 * in supporting documentation. Silicon Graphics makes no 48 * representations about the suitability of this software for any 49 * purpose. It is provided "as is" without express or implied warranty. 50 */ 51 52 /** @file bits/stl_multiset.h 53 * This is an internal header file, included by other library headers. 54 * Do not attempt to use it directly. @headername{set} 55 */ 56 57 #ifndef _STL_MULTISET_H 58 #define _STL_MULTISET_H 1 59 60 #include <bits/concept_check.h> 61 #include <initializer_list> 62 63 namespace std _GLIBCXX_VISIBILITY(default) 64 { 65 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER 66 67 /** 68 * @brief A standard container made up of elements, which can be retrieved 69 * in logarithmic time. 70 * 71 * @ingroup associative_containers 72 * 73 * Meets the requirements of a <a href="tables.html#65">container</a>, a 74 * <a href="tables.html#66">reversible container</a>, and an 75 * <a href="tables.html#69">associative container</a> (using equivalent 76 * keys). For a @c multiset<Key> the key_type and value_type are Key. 77 * 78 * Multisets support bidirectional iterators. 79 * 80 * The private tree data is declared exactly the same way for set and 81 * multiset; the distinction is made entirely in how the tree functions are 82 * called (*_unique versus *_equal, same as the standard). 83 */ 84 template <typename _Key, typename _Compare = std::less<_Key>, 85 typename _Alloc = std::allocator<_Key> > 86 class multiset 87 { 88 // concept requirements 89 typedef typename _Alloc::value_type _Alloc_value_type; 90 __glibcxx_class_requires(_Key, _SGIAssignableConcept) 91 __glibcxx_class_requires4(_Compare, bool, _Key, _Key, 92 _BinaryFunctionConcept) 93 __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) 94 95 public: 96 // typedefs: 97 typedef _Key key_type; 98 typedef _Key value_type; 99 typedef _Compare key_compare; 100 typedef _Compare value_compare; 101 typedef _Alloc allocator_type; 102 103 private: 104 /// This turns a red-black tree into a [multi]set. 105 typedef typename _Alloc::template rebind<_Key>::other _Key_alloc_type; 106 107 typedef _Rb_tree<key_type, value_type, _Identity<value_type>, 108 key_compare, _Key_alloc_type> _Rep_type; 109 /// The actual tree structure. 110 _Rep_type _M_t; 111 112 public: 113 typedef typename _Key_alloc_type::pointer pointer; 114 typedef typename _Key_alloc_type::const_pointer const_pointer; 115 typedef typename _Key_alloc_type::reference reference; 116 typedef typename _Key_alloc_type::const_reference const_reference; 117 // _GLIBCXX_RESOLVE_LIB_DEFECTS 118 // DR 103. set::iterator is required to be modifiable, 119 // but this allows modification of keys. 120 typedef typename _Rep_type::const_iterator iterator; 121 typedef typename _Rep_type::const_iterator const_iterator; 122 typedef typename _Rep_type::const_reverse_iterator reverse_iterator; 123 typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; 124 typedef typename _Rep_type::size_type size_type; 125 typedef typename _Rep_type::difference_type difference_type; 126 127 // allocation/deallocation 128 /** 129 * @brief Default constructor creates no elements. 130 */ 131 multiset() 132 : _M_t() { } 133 134 /** 135 * @brief Creates a %multiset with no elements. 136 * @param comp Comparator to use. 137 * @param a An allocator object. 138 */ 139 explicit 140 multiset(const _Compare& __comp, 141 const allocator_type& __a = allocator_type()) 142 : _M_t(__comp, __a) { } 143 144 /** 145 * @brief Builds a %multiset from a range. 146 * @param first An input iterator. 147 * @param last An input iterator. 148 * 149 * Create a %multiset consisting of copies of the elements from 150 * [first,last). This is linear in N if the range is already sorted, 151 * and NlogN otherwise (where N is distance(first,last)). 152 */ 153 template<typename _InputIterator> 154 multiset(_InputIterator __first, _InputIterator __last) 155 : _M_t() 156 { _M_t._M_insert_equal(__first, __last); } 157 158 /** 159 * @brief Builds a %multiset from a range. 160 * @param first An input iterator. 161 * @param last An input iterator. 162 * @param comp A comparison functor. 163 * @param a An allocator object. 164 * 165 * Create a %multiset consisting of copies of the elements from 166 * [first,last). This is linear in N if the range is already sorted, 167 * and NlogN otherwise (where N is distance(first,last)). 168 */ 169 template<typename _InputIterator> 170 multiset(_InputIterator __first, _InputIterator __last, 171 const _Compare& __comp, 172 const allocator_type& __a = allocator_type()) 173 : _M_t(__comp, __a) 174 { _M_t._M_insert_equal(__first, __last); } 175 176 /** 177 * @brief %Multiset copy constructor. 178 * @param x A %multiset of identical element and allocator types. 179 * 180 * The newly-created %multiset uses a copy of the allocation object used 181 * by @a x. 182 */ 183 multiset(const multiset& __x) 184 : _M_t(__x._M_t) { } 185 186 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 187 /** 188 * @brief %Multiset move constructor. 189 * @param x A %multiset of identical element and allocator types. 190 * 191 * The newly-created %multiset contains the exact contents of @a x. 192 * The contents of @a x are a valid, but unspecified %multiset. 193 */ 194 multiset(multiset&& __x) 195 : _M_t(std::move(__x._M_t)) { } 196 197 /** 198 * @brief Builds a %multiset from an initializer_list. 199 * @param l An initializer_list. 200 * @param comp A comparison functor. 201 * @param a An allocator object. 202 * 203 * Create a %multiset consisting of copies of the elements from 204 * the list. This is linear in N if the list is already sorted, 205 * and NlogN otherwise (where N is @a l.size()). 206 */ 207 multiset(initializer_list<value_type> __l, 208 const _Compare& __comp = _Compare(), 209 const allocator_type& __a = allocator_type()) 210 : _M_t(__comp, __a) 211 { _M_t._M_insert_equal(__l.begin(), __l.end()); } 212 #endif 213 214 /** 215 * @brief %Multiset assignment operator. 216 * @param x A %multiset of identical element and allocator types. 217 * 218 * All the elements of @a x are copied, but unlike the copy constructor, 219 * the allocator object is not copied. 220 */ 221 multiset& 222 operator=(const multiset& __x) 223 { 224 _M_t = __x._M_t; 225 return *this; 226 } 227 228 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 229 /** 230 * @brief %Multiset move assignment operator. 231 * @param x A %multiset of identical element and allocator types. 232 * 233 * The contents of @a x are moved into this %multiset (without copying). 234 * @a x is a valid, but unspecified %multiset. 235 */ 236 multiset& 237 operator=(multiset&& __x) 238 { 239 // NB: DR 1204. 240 // NB: DR 675. 241 this->clear(); 242 this->swap(__x); 243 return *this; 244 } 245 246 /** 247 * @brief %Multiset list assignment operator. 248 * @param l An initializer_list. 249 * 250 * This function fills a %multiset with copies of the elements in the 251 * initializer list @a l. 252 * 253 * Note that the assignment completely changes the %multiset and 254 * that the resulting %multiset's size is the same as the number 255 * of elements assigned. Old data may be lost. 256 */ 257 multiset& 258 operator=(initializer_list<value_type> __l) 259 { 260 this->clear(); 261 this->insert(__l.begin(), __l.end()); 262 return *this; 263 } 264 #endif 265 266 // accessors: 267 268 /// Returns the comparison object. 269 key_compare 270 key_comp() const 271 { return _M_t.key_comp(); } 272 /// Returns the comparison object. 273 value_compare 274 value_comp() const 275 { return _M_t.key_comp(); } 276 /// Returns the memory allocation object. 277 allocator_type 278 get_allocator() const 279 { return _M_t.get_allocator(); } 280 281 /** 282 * Returns a read-only (constant) iterator that points to the first 283 * element in the %multiset. Iteration is done in ascending order 284 * according to the keys. 285 */ 286 iterator 287 begin() const 288 { return _M_t.begin(); } 289 290 /** 291 * Returns a read-only (constant) iterator that points one past the last 292 * element in the %multiset. Iteration is done in ascending order 293 * according to the keys. 294 */ 295 iterator 296 end() const 297 { return _M_t.end(); } 298 299 /** 300 * Returns a read-only (constant) reverse iterator that points to the 301 * last element in the %multiset. Iteration is done in descending order 302 * according to the keys. 303 */ 304 reverse_iterator 305 rbegin() const 306 { return _M_t.rbegin(); } 307 308 /** 309 * Returns a read-only (constant) reverse iterator that points to the 310 * last element in the %multiset. Iteration is done in descending order 311 * according to the keys. 312 */ 313 reverse_iterator 314 rend() const 315 { return _M_t.rend(); } 316 317 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 318 /** 319 * Returns a read-only (constant) iterator that points to the first 320 * element in the %multiset. Iteration is done in ascending order 321 * according to the keys. 322 */ 323 iterator 324 cbegin() const 325 { return _M_t.begin(); } 326 327 /** 328 * Returns a read-only (constant) iterator that points one past the last 329 * element in the %multiset. Iteration is done in ascending order 330 * according to the keys. 331 */ 332 iterator 333 cend() const 334 { return _M_t.end(); } 335 336 /** 337 * Returns a read-only (constant) reverse iterator that points to the 338 * last element in the %multiset. Iteration is done in descending order 339 * according to the keys. 340 */ 341 reverse_iterator 342 crbegin() const 343 { return _M_t.rbegin(); } 344 345 /** 346 * Returns a read-only (constant) reverse iterator that points to the 347 * last element in the %multiset. Iteration is done in descending order 348 * according to the keys. 349 */ 350 reverse_iterator 351 crend() const 352 { return _M_t.rend(); } 353 #endif 354 355 /// Returns true if the %set is empty. 356 bool 357 empty() const 358 { return _M_t.empty(); } 359 360 /// Returns the size of the %set. 361 size_type 362 size() const 363 { return _M_t.size(); } 364 365 /// Returns the maximum size of the %set. 366 size_type 367 max_size() const 368 { return _M_t.max_size(); } 369 370 /** 371 * @brief Swaps data with another %multiset. 372 * @param x A %multiset of the same element and allocator types. 373 * 374 * This exchanges the elements between two multisets in constant time. 375 * (It is only swapping a pointer, an integer, and an instance of the @c 376 * Compare type (which itself is often stateless and empty), so it should 377 * be quite fast.) 378 * Note that the global std::swap() function is specialized such that 379 * std::swap(s1,s2) will feed to this function. 380 */ 381 void 382 swap(multiset& __x) 383 { _M_t.swap(__x._M_t); } 384 385 // insert/erase 386 /** 387 * @brief Inserts an element into the %multiset. 388 * @param x Element to be inserted. 389 * @return An iterator that points to the inserted element. 390 * 391 * This function inserts an element into the %multiset. Contrary 392 * to a std::set the %multiset does not rely on unique keys and thus 393 * multiple copies of the same element can be inserted. 394 * 395 * Insertion requires logarithmic time. 396 */ 397 iterator 398 insert(const value_type& __x) 399 { return _M_t._M_insert_equal(__x); } 400 401 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 402 iterator 403 insert(value_type&& __x) 404 { return _M_t._M_insert_equal(std::move(__x)); } 405 #endif 406 407 /** 408 * @brief Inserts an element into the %multiset. 409 * @param position An iterator that serves as a hint as to where the 410 * element should be inserted. 411 * @param x Element to be inserted. 412 * @return An iterator that points to the inserted element. 413 * 414 * This function inserts an element into the %multiset. Contrary 415 * to a std::set the %multiset does not rely on unique keys and thus 416 * multiple copies of the same element can be inserted. 417 * 418 * Note that the first parameter is only a hint and can potentially 419 * improve the performance of the insertion process. A bad hint would 420 * cause no gains in efficiency. 421 * 422 * See http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt07ch17.html 423 * for more on @a hinting. 424 * 425 * Insertion requires logarithmic time (if the hint is not taken). 426 */ 427 iterator 428 insert(const_iterator __position, const value_type& __x) 429 { return _M_t._M_insert_equal_(__position, __x); } 430 431 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 432 iterator 433 insert(const_iterator __position, value_type&& __x) 434 { return _M_t._M_insert_equal_(__position, std::move(__x)); } 435 #endif 436 437 /** 438 * @brief A template function that tries to insert a range of elements. 439 * @param first Iterator pointing to the start of the range to be 440 * inserted. 441 * @param last Iterator pointing to the end of the range. 442 * 443 * Complexity similar to that of the range constructor. 444 */ 445 template<typename _InputIterator> 446 void 447 insert(_InputIterator __first, _InputIterator __last) 448 { _M_t._M_insert_equal(__first, __last); } 449 450 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 451 /** 452 * @brief Attempts to insert a list of elements into the %multiset. 453 * @param list A std::initializer_list<value_type> of elements 454 * to be inserted. 455 * 456 * Complexity similar to that of the range constructor. 457 */ 458 void 459 insert(initializer_list<value_type> __l) 460 { this->insert(__l.begin(), __l.end()); } 461 #endif 462 463 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 464 // _GLIBCXX_RESOLVE_LIB_DEFECTS 465 // DR 130. Associative erase should return an iterator. 466 /** 467 * @brief Erases an element from a %multiset. 468 * @param position An iterator pointing to the element to be erased. 469 * @return An iterator pointing to the element immediately following 470 * @a position prior to the element being erased. If no such 471 * element exists, end() is returned. 472 * 473 * This function erases an element, pointed to by the given iterator, 474 * from a %multiset. Note that this function only erases the element, 475 * and that if the element is itself a pointer, the pointed-to memory is 476 * not touched in any way. Managing the pointer is the user's 477 * responsibility. 478 */ 479 iterator 480 erase(const_iterator __position) 481 { return _M_t.erase(__position); } 482 #else 483 /** 484 * @brief Erases an element from a %multiset. 485 * @param position An iterator pointing to the element to be erased. 486 * 487 * This function erases an element, pointed to by the given iterator, 488 * from a %multiset. Note that this function only erases the element, 489 * and that if the element is itself a pointer, the pointed-to memory is 490 * not touched in any way. Managing the pointer is the user's 491 * responsibility. 492 */ 493 void 494 erase(iterator __position) 495 { _M_t.erase(__position); } 496 #endif 497 498 /** 499 * @brief Erases elements according to the provided key. 500 * @param x Key of element to be erased. 501 * @return The number of elements erased. 502 * 503 * This function erases all elements located by the given key from a 504 * %multiset. 505 * Note that this function only erases the element, and that if 506 * the element is itself a pointer, the pointed-to memory is not touched 507 * in any way. Managing the pointer is the user's responsibility. 508 */ 509 size_type 510 erase(const key_type& __x) 511 { return _M_t.erase(__x); } 512 513 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 514 // _GLIBCXX_RESOLVE_LIB_DEFECTS 515 // DR 130. Associative erase should return an iterator. 516 /** 517 * @brief Erases a [first,last) range of elements from a %multiset. 518 * @param first Iterator pointing to the start of the range to be 519 * erased. 520 * @param last Iterator pointing to the end of the range to be erased. 521 * @return The iterator @a last. 522 * 523 * This function erases a sequence of elements from a %multiset. 524 * Note that this function only erases the elements, and that if 525 * the elements themselves are pointers, the pointed-to memory is not 526 * touched in any way. Managing the pointer is the user's 527 * responsibility. 528 */ 529 iterator 530 erase(const_iterator __first, const_iterator __last) 531 { return _M_t.erase(__first, __last); } 532 #else 533 /** 534 * @brief Erases a [first,last) range of elements from a %multiset. 535 * @param first Iterator pointing to the start of the range to be 536 * erased. 537 * @param last Iterator pointing to the end of the range to be erased. 538 * 539 * This function erases a sequence of elements from a %multiset. 540 * Note that this function only erases the elements, and that if 541 * the elements themselves are pointers, the pointed-to memory is not 542 * touched in any way. Managing the pointer is the user's 543 * responsibility. 544 */ 545 void 546 erase(iterator __first, iterator __last) 547 { _M_t.erase(__first, __last); } 548 #endif 549 550 /** 551 * Erases all elements in a %multiset. Note that this function only 552 * erases the elements, and that if the elements themselves are pointers, 553 * the pointed-to memory is not touched in any way. Managing the pointer 554 * is the user's responsibility. 555 */ 556 void 557 clear() 558 { _M_t.clear(); } 559 560 // multiset operations: 561 562 /** 563 * @brief Finds the number of elements with given key. 564 * @param x Key of elements to be located. 565 * @return Number of elements with specified key. 566 */ 567 size_type 568 count(const key_type& __x) const 569 { return _M_t.count(__x); } 570 571 // _GLIBCXX_RESOLVE_LIB_DEFECTS 572 // 214. set::find() missing const overload 573 //@{ 574 /** 575 * @brief Tries to locate an element in a %set. 576 * @param x Element to be located. 577 * @return Iterator pointing to sought-after element, or end() if not 578 * found. 579 * 580 * This function takes a key and tries to locate the element with which 581 * the key matches. If successful the function returns an iterator 582 * pointing to the sought after element. If unsuccessful it returns the 583 * past-the-end ( @c end() ) iterator. 584 */ 585 iterator 586 find(const key_type& __x) 587 { return _M_t.find(__x); } 588 589 const_iterator 590 find(const key_type& __x) const 591 { return _M_t.find(__x); } 592 //@} 593 594 //@{ 595 /** 596 * @brief Finds the beginning of a subsequence matching given key. 597 * @param x Key to be located. 598 * @return Iterator pointing to first element equal to or greater 599 * than key, or end(). 600 * 601 * This function returns the first element of a subsequence of elements 602 * that matches the given key. If unsuccessful it returns an iterator 603 * pointing to the first element that has a greater value than given key 604 * or end() if no such element exists. 605 */ 606 iterator 607 lower_bound(const key_type& __x) 608 { return _M_t.lower_bound(__x); } 609 610 const_iterator 611 lower_bound(const key_type& __x) const 612 { return _M_t.lower_bound(__x); } 613 //@} 614 615 //@{ 616 /** 617 * @brief Finds the end of a subsequence matching given key. 618 * @param x Key to be located. 619 * @return Iterator pointing to the first element 620 * greater than key, or end(). 621 */ 622 iterator 623 upper_bound(const key_type& __x) 624 { return _M_t.upper_bound(__x); } 625 626 const_iterator 627 upper_bound(const key_type& __x) const 628 { return _M_t.upper_bound(__x); } 629 //@} 630 631 //@{ 632 /** 633 * @brief Finds a subsequence matching given key. 634 * @param x Key to be located. 635 * @return Pair of iterators that possibly points to the subsequence 636 * matching given key. 637 * 638 * This function is equivalent to 639 * @code 640 * std::make_pair(c.lower_bound(val), 641 * c.upper_bound(val)) 642 * @endcode 643 * (but is faster than making the calls separately). 644 * 645 * This function probably only makes sense for multisets. 646 */ 647 std::pair<iterator, iterator> 648 equal_range(const key_type& __x) 649 { return _M_t.equal_range(__x); } 650 651 std::pair<const_iterator, const_iterator> 652 equal_range(const key_type& __x) const 653 { return _M_t.equal_range(__x); } 654 655 template<typename _K1, typename _C1, typename _A1> 656 friend bool 657 operator==(const multiset<_K1, _C1, _A1>&, 658 const multiset<_K1, _C1, _A1>&); 659 660 template<typename _K1, typename _C1, typename _A1> 661 friend bool 662 operator< (const multiset<_K1, _C1, _A1>&, 663 const multiset<_K1, _C1, _A1>&); 664 }; 665 666 /** 667 * @brief Multiset equality comparison. 668 * @param x A %multiset. 669 * @param y A %multiset of the same type as @a x. 670 * @return True iff the size and elements of the multisets are equal. 671 * 672 * This is an equivalence relation. It is linear in the size of the 673 * multisets. 674 * Multisets are considered equivalent if their sizes are equal, and if 675 * corresponding elements compare equal. 676 */ 677 template<typename _Key, typename _Compare, typename _Alloc> 678 inline bool 679 operator==(const multiset<_Key, _Compare, _Alloc>& __x, 680 const multiset<_Key, _Compare, _Alloc>& __y) 681 { return __x._M_t == __y._M_t; } 682 683 /** 684 * @brief Multiset ordering relation. 685 * @param x A %multiset. 686 * @param y A %multiset of the same type as @a x. 687 * @return True iff @a x is lexicographically less than @a y. 688 * 689 * This is a total ordering relation. It is linear in the size of the 690 * maps. The elements must be comparable with @c <. 691 * 692 * See std::lexicographical_compare() for how the determination is made. 693 */ 694 template<typename _Key, typename _Compare, typename _Alloc> 695 inline bool 696 operator<(const multiset<_Key, _Compare, _Alloc>& __x, 697 const multiset<_Key, _Compare, _Alloc>& __y) 698 { return __x._M_t < __y._M_t; } 699 700 /// Returns !(x == y). 701 template<typename _Key, typename _Compare, typename _Alloc> 702 inline bool 703 operator!=(const multiset<_Key, _Compare, _Alloc>& __x, 704 const multiset<_Key, _Compare, _Alloc>& __y) 705 { return !(__x == __y); } 706 707 /// Returns y < x. 708 template<typename _Key, typename _Compare, typename _Alloc> 709 inline bool 710 operator>(const multiset<_Key,_Compare,_Alloc>& __x, 711 const multiset<_Key,_Compare,_Alloc>& __y) 712 { return __y < __x; } 713 714 /// Returns !(y < x) 715 template<typename _Key, typename _Compare, typename _Alloc> 716 inline bool 717 operator<=(const multiset<_Key, _Compare, _Alloc>& __x, 718 const multiset<_Key, _Compare, _Alloc>& __y) 719 { return !(__y < __x); } 720 721 /// Returns !(x < y) 722 template<typename _Key, typename _Compare, typename _Alloc> 723 inline bool 724 operator>=(const multiset<_Key, _Compare, _Alloc>& __x, 725 const multiset<_Key, _Compare, _Alloc>& __y) 726 { return !(__x < __y); } 727 728 /// See std::multiset::swap(). 729 template<typename _Key, typename _Compare, typename _Alloc> 730 inline void 731 swap(multiset<_Key, _Compare, _Alloc>& __x, 732 multiset<_Key, _Compare, _Alloc>& __y) 733 { __x.swap(__y); } 734 735 _GLIBCXX_END_NAMESPACE_CONTAINER 736 } // namespace std 737 738 #endif /* _STL_MULTISET_H */ 739