fix doc example typo
[boost.git] / boost / interprocess / containers / container / map.hpp
blobc0033c745c545c768eb47188918ce6672a06b3c5
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
11 // This file comes from SGI's stl_map/stl_multimap files. Modified by Ion Gaztanaga.
12 // Renaming, isolating and porting to generic algorithms. Pointer typedef
13 // set to allocator::pointer to allow placing it in shared memory.
15 ///////////////////////////////////////////////////////////////////////////////
18 * Copyright (c) 1994
19 * Hewlett-Packard Company
21 * Permission to use, copy, modify, distribute and sell this software
22 * and its documentation for any purpose is hereby granted without fee,
23 * provided that the above copyright notice appear in all copies and
24 * that both that copyright notice and this permission notice appear
25 * in supporting documentation. Hewlett-Packard Company makes no
26 * representations about the suitability of this software for any
27 * purpose. It is provided "as is" without express or implied warranty.
30 * Copyright (c) 1996
31 * Silicon Graphics Computer Systems, Inc.
33 * Permission to use, copy, modify, distribute and sell this software
34 * and its documentation for any purpose is hereby granted without fee,
35 * provided that the above copyright notice appear in all copies and
36 * that both that copyright notice and this permission notice appear
37 * in supporting documentation. Silicon Graphics makes no
38 * representations about the suitability of this software for any
39 * purpose. It is provided "as is" without express or implied warranty.
43 #ifndef BOOST_CONTAINERS_MAP_HPP
44 #define BOOST_CONTAINERS_MAP_HPP
46 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
47 # pragma once
48 #endif
50 #include <boost/interprocess/containers/container/detail/config_begin.hpp>
51 #include <boost/interprocess/containers/container/detail/workaround.hpp>
53 #include <boost/interprocess/containers/container/containers_fwd.hpp>
54 #include <utility>
55 #include <functional>
56 #include <memory>
57 #include <stdexcept>
58 #include <boost/interprocess/containers/container/detail/tree.hpp>
59 #include <boost/interprocess/containers/container/detail/value_init.hpp>
60 #include <boost/type_traits/has_trivial_destructor.hpp>
61 #include <boost/interprocess/containers/container/detail/mpl.hpp>
62 #include <boost/interprocess/containers/container/detail/utilities.hpp>
63 #include <boost/interprocess/containers/container/detail/pair.hpp>
64 #include <boost/interprocess/detail/move.hpp>
66 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
67 namespace boost {
68 namespace interprocess {
69 #else
70 namespace boost {
71 namespace interprocess_container {
72 #endif
74 /// @cond
75 // Forward declarations of operators == and <, needed for friend declarations.
76 template <class Key, class T, class Pred, class Alloc>
77 inline bool operator==(const map<Key,T,Pred,Alloc>& x,
78 const map<Key,T,Pred,Alloc>& y);
80 template <class Key, class T, class Pred, class Alloc>
81 inline bool operator<(const map<Key,T,Pred,Alloc>& x,
82 const map<Key,T,Pred,Alloc>& y);
83 /// @endcond
85 //! A map is a kind of associative container that supports unique keys (contains at
86 //! most one of each key value) and provides for fast retrieval of values of another
87 //! type T based on the keys. The map class supports bidirectional iterators.
88 //!
89 //! A map satisfies all of the requirements of a container and of a reversible
90 //! container and of an associative container. For a
91 //! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>.
92 //!
93 //! Pred is the ordering function for Keys (e.g. <i>std::less<Key></i>).
94 //!
95 //! Alloc is the allocator to allocate the value_types
96 //! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
97 template <class Key, class T, class Pred, class Alloc>
98 class map
100 /// @cond
101 private:
102 typedef containers_detail::rbtree<Key,
103 std::pair<const Key, T>,
104 containers_detail::select1st< std::pair<const Key, T> >,
105 Pred,
106 Alloc> tree_t;
107 tree_t m_tree; // red-black tree representing map
108 /// @endcond
110 public:
111 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(map)
113 // typedefs:
114 typedef typename tree_t::key_type key_type;
115 typedef typename tree_t::value_type value_type;
116 typedef typename tree_t::pointer pointer;
117 typedef typename tree_t::const_pointer const_pointer;
118 typedef typename tree_t::reference reference;
119 typedef typename tree_t::const_reference const_reference;
120 typedef T mapped_type;
121 typedef Pred key_compare;
122 typedef typename tree_t::iterator iterator;
123 typedef typename tree_t::const_iterator const_iterator;
124 typedef typename tree_t::reverse_iterator reverse_iterator;
125 typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
126 typedef typename tree_t::size_type size_type;
127 typedef typename tree_t::difference_type difference_type;
128 typedef typename tree_t::allocator_type allocator_type;
129 typedef typename tree_t::stored_allocator_type stored_allocator_type;
130 typedef std::pair<key_type, mapped_type> nonconst_value_type;
131 typedef containers_detail::pair
132 <key_type, mapped_type> nonconst_impl_value_type;
134 /// @cond
135 class value_compare_impl
136 : public Pred,
137 public std::binary_function<value_type, value_type, bool>
139 friend class map<Key,T,Pred,Alloc>;
140 protected :
141 value_compare_impl(const Pred &c) : Pred(c) {}
142 public:
143 bool operator()(const value_type& x, const value_type& y) const {
144 return Pred::operator()(x.first, y.first);
147 /// @endcond
148 typedef value_compare_impl value_compare;
150 //! <b>Effects</b>: Constructs an empty map using the specified comparison object
151 //! and allocator.
152 //!
153 //! <b>Complexity</b>: Constant.
154 explicit map(const Pred& comp = Pred(),
155 const allocator_type& a = allocator_type())
156 : m_tree(comp, a)
159 //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
160 //! allocator, and inserts elements from the range [first ,last ).
161 //!
162 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
163 //! comp and otherwise N logN, where N is last - first.
164 template <class InputIterator>
165 map(InputIterator first, InputIterator last, const Pred& comp = Pred(),
166 const allocator_type& a = allocator_type())
167 : m_tree(first, last, comp, a, true)
170 //! <b>Effects</b>: Copy constructs a map.
171 //!
172 //! <b>Complexity</b>: Linear in x.size().
173 map(const map<Key,T,Pred,Alloc>& x)
174 : m_tree(x.m_tree)
177 //! <b>Effects</b>: Move constructs a map. Constructs *this using x's resources.
178 //!
179 //! <b>Complexity</b>: Construct.
180 //!
181 //! <b>Postcondition</b>: x is emptied.
182 map(BOOST_INTERPROCESS_RV_REF(map) x)
183 : m_tree(boost::interprocess::move(x.m_tree))
186 //! <b>Effects</b>: Makes *this a copy of x.
187 //!
188 //! <b>Complexity</b>: Linear in x.size().
189 map& operator=(const map<Key, T, Pred, Alloc>& x)
190 { m_tree = x.m_tree; return *this; }
192 //! <b>Effects</b>: this->swap(x.get()).
193 //!
194 //! <b>Complexity</b>: Constant.
195 map& operator=(BOOST_INTERPROCESS_RV_REF(map) x)
196 { m_tree = boost::interprocess::move(x.m_tree); return *this; }
198 //! <b>Effects</b>: Returns the comparison object out
199 //! of which a was constructed.
200 //!
201 //! <b>Complexity</b>: Constant.
202 key_compare key_comp() const
203 { return m_tree.key_comp(); }
205 //! <b>Effects</b>: Returns an object of value_compare constructed out
206 //! of the comparison object.
207 //!
208 //! <b>Complexity</b>: Constant.
209 value_compare value_comp() const
210 { return value_compare(m_tree.key_comp()); }
212 //! <b>Effects</b>: Returns a copy of the Allocator that
213 //! was passed to the object's constructor.
214 //!
215 //! <b>Complexity</b>: Constant.
216 allocator_type get_allocator() const
217 { return m_tree.get_allocator(); }
219 const stored_allocator_type &get_stored_allocator() const
220 { return m_tree.get_stored_allocator(); }
222 stored_allocator_type &get_stored_allocator()
223 { return m_tree.get_stored_allocator(); }
225 //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
226 //!
227 //! <b>Throws</b>: Nothing.
228 //!
229 //! <b>Complexity</b>: Constant.
230 iterator begin()
231 { return m_tree.begin(); }
233 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
234 //!
235 //! <b>Throws</b>: Nothing.
236 //!
237 //! <b>Complexity</b>: Constant.
238 const_iterator begin() const
239 { return m_tree.begin(); }
241 //! <b>Effects</b>: Returns an iterator to the end of the container.
242 //!
243 //! <b>Throws</b>: Nothing.
244 //!
245 //! <b>Complexity</b>: Constant.
246 iterator end()
247 { return m_tree.end(); }
249 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
250 //!
251 //! <b>Throws</b>: Nothing.
252 //!
253 //! <b>Complexity</b>: Constant.
254 const_iterator end() const
255 { return m_tree.end(); }
257 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
258 //! of the reversed container.
259 //!
260 //! <b>Throws</b>: Nothing.
261 //!
262 //! <b>Complexity</b>: Constant.
263 reverse_iterator rbegin()
264 { return m_tree.rbegin(); }
266 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
267 //! of the reversed container.
268 //!
269 //! <b>Throws</b>: Nothing.
270 //!
271 //! <b>Complexity</b>: Constant.
272 const_reverse_iterator rbegin() const
273 { return m_tree.rbegin(); }
275 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
276 //! of the reversed container.
277 //!
278 //! <b>Throws</b>: Nothing.
279 //!
280 //! <b>Complexity</b>: Constant.
281 reverse_iterator rend()
282 { return m_tree.rend(); }
284 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
285 //! of the reversed container.
286 //!
287 //! <b>Throws</b>: Nothing.
288 //!
289 //! <b>Complexity</b>: Constant.
290 const_reverse_iterator rend() const
291 { return m_tree.rend(); }
293 //! <b>Effects</b>: Returns true if the container contains no elements.
294 //!
295 //! <b>Throws</b>: Nothing.
296 //!
297 //! <b>Complexity</b>: Constant.
298 bool empty() const
299 { return m_tree.empty(); }
301 //! <b>Effects</b>: Returns the number of the elements contained in the container.
302 //!
303 //! <b>Throws</b>: Nothing.
304 //!
305 //! <b>Complexity</b>: Constant.
306 size_type size() const
307 { return m_tree.size(); }
309 //! <b>Effects</b>: Returns the largest possible size of the container.
310 //!
311 //! <b>Throws</b>: Nothing.
312 //!
313 //! <b>Complexity</b>: Constant.
314 size_type max_size() const
315 { return m_tree.max_size(); }
317 //! Effects: If there is no key equivalent to x in the map, inserts
318 //! value_type(x, T()) into the map.
319 //!
320 //! Returns: A reference to the mapped_type corresponding to x in *this.
321 //!
322 //! Complexity: Logarithmic.
323 T& operator[](const key_type& k)
325 //we can optimize this
326 iterator i = lower_bound(k);
327 // i->first is greater than or equivalent to k.
328 if (i == end() || key_comp()(k, (*i).first)){
329 containers_detail::value_init<T> v;
330 value_type val(k, boost::interprocess::move(v.m_t));
331 i = insert(i, boost::interprocess::move(val));
333 return (*i).second;
336 //! Effects: If there is no key equivalent to x in the map, inserts
337 //! value_type(boost::interprocess::move(x), T()) into the map (the key is move-constructed)
338 //!
339 //! Returns: A reference to the mapped_type corresponding to x in *this.
340 //!
341 //! Complexity: Logarithmic.
342 T& operator[](BOOST_INTERPROCESS_RV_REF(key_type) mk)
344 key_type &k = mk;
345 //we can optimize this
346 iterator i = lower_bound(k);
347 // i->first is greater than or equivalent to k.
348 if (i == end() || key_comp()(k, (*i).first)){
349 value_type val(boost::interprocess::move(k), boost::interprocess::move(T()));
350 i = insert(i, boost::interprocess::move(val));
352 return (*i).second;
355 //! Returns: A reference to the element whose key is equivalent to x.
356 //! Throws: An exception object of type out_of_range if no such element is present.
357 //! Complexity: logarithmic.
358 T& at(const key_type& k)
360 iterator i = this->find(k);
361 if(i == this->end()){
362 throw std::out_of_range("key not found");
364 return i->second;
367 //! Returns: A reference to the element whose key is equivalent to x.
368 //! Throws: An exception object of type out_of_range if no such element is present.
369 //! Complexity: logarithmic.
370 const T& at(const key_type& k) const
372 const_iterator i = this->find(k);
373 if(i == this->end()){
374 throw std::out_of_range("key not found");
376 return i->second;
379 //! <b>Effects</b>: Swaps the contents of *this and x.
380 //! If this->allocator_type() != x.allocator_type() allocators are also swapped.
382 //! <b>Throws</b>: Nothing.
384 //! <b>Complexity</b>: Constant.
385 void swap(map& x)
386 { m_tree.swap(x.m_tree); }
388 //! <b>Effects</b>: Inserts x if and only if there is no element in the container
389 //! with key equivalent to the key of x.
391 //! <b>Returns</b>: The bool component of the returned pair is true if and only
392 //! if the insertion takes place, and the iterator component of the pair
393 //! points to the element with key equivalent to the key of x.
395 //! <b>Complexity</b>: Logarithmic.
396 std::pair<iterator,bool> insert(const value_type& x)
397 { return m_tree.insert_unique(x); }
399 //! <b>Effects</b>: Inserts a new value_type created from the pair if and only if
400 //! there is no element in the container with key equivalent to the key of x.
402 //! <b>Returns</b>: The bool component of the returned pair is true if and only
403 //! if the insertion takes place, and the iterator component of the pair
404 //! points to the element with key equivalent to the key of x.
406 //! <b>Complexity</b>: Logarithmic.
407 std::pair<iterator,bool> insert(const nonconst_value_type& x)
408 { return m_tree.insert_unique(x); }
410 //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
411 //! only if there is no element in the container with key equivalent to the key of x.
413 //! <b>Returns</b>: The bool component of the returned pair is true if and only
414 //! if the insertion takes place, and the iterator component of the pair
415 //! points to the element with key equivalent to the key of x.
417 //! <b>Complexity</b>: Logarithmic.
418 std::pair<iterator,bool> insert(BOOST_INTERPROCESS_RV_REF(nonconst_value_type) x)
419 { return m_tree.insert_unique(boost::interprocess::move(x)); }
421 //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
422 //! only if there is no element in the container with key equivalent to the key of x.
424 //! <b>Returns</b>: The bool component of the returned pair is true if and only
425 //! if the insertion takes place, and the iterator component of the pair
426 //! points to the element with key equivalent to the key of x.
428 //! <b>Complexity</b>: Logarithmic.
429 std::pair<iterator,bool> insert(BOOST_INTERPROCESS_RV_REF(nonconst_impl_value_type) x)
430 { return m_tree.insert_unique(boost::interprocess::move(x)); }
432 //! <b>Effects</b>: Move constructs a new value from x if and only if there is
433 //! no element in the container with key equivalent to the key of x.
435 //! <b>Returns</b>: The bool component of the returned pair is true if and only
436 //! if the insertion takes place, and the iterator component of the pair
437 //! points to the element with key equivalent to the key of x.
439 //! <b>Complexity</b>: Logarithmic.
440 std::pair<iterator,bool> insert(BOOST_INTERPROCESS_RV_REF(value_type) x)
441 { return m_tree.insert_unique(boost::interprocess::move(x)); }
443 //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
444 //! no element in the container with key equivalent to the key of x.
445 //! p is a hint pointing to where the insert should start to search.
447 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
448 //! to the key of x.
450 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
451 //! is inserted right before p.
452 iterator insert(iterator position, const value_type& x)
453 { return m_tree.insert_unique(position, x); }
455 //! <b>Effects</b>: Move constructs a new value from x if and only if there is
456 //! no element in the container with key equivalent to the key of x.
457 //! p is a hint pointing to where the insert should start to search.
459 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
460 //! to the key of x.
462 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
463 //! is inserted right before p.
464 iterator insert(iterator position, BOOST_INTERPROCESS_RV_REF(nonconst_value_type) x)
465 { return m_tree.insert_unique(position, boost::interprocess::move(x)); }
467 //! <b>Effects</b>: Move constructs a new value from x if and only if there is
468 //! no element in the container with key equivalent to the key of x.
469 //! p is a hint pointing to where the insert should start to search.
471 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
472 //! to the key of x.
474 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
475 //! is inserted right before p.
476 iterator insert(iterator position, BOOST_INTERPROCESS_RV_REF(nonconst_impl_value_type) x)
477 { return m_tree.insert_unique(position, boost::interprocess::move(x)); }
479 //! <b>Effects</b>: Inserts a copy of x in the container.
480 //! p is a hint pointing to where the insert should start to search.
482 //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
484 //! <b>Complexity</b>: Logarithmic.
485 iterator insert(iterator position, const nonconst_value_type& x)
486 { return m_tree.insert_unique(position, x); }
488 //! <b>Effects</b>: Inserts an element move constructed from x in the container.
489 //! p is a hint pointing to where the insert should start to search.
491 //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
493 //! <b>Complexity</b>: Logarithmic.
494 iterator insert(iterator position, BOOST_INTERPROCESS_RV_REF(value_type) x)
495 { return m_tree.insert_unique(position, boost::interprocess::move(x)); }
497 //! <b>Requires</b>: i, j are not iterators into *this.
499 //! <b>Effects</b>: inserts each element from the range [i,j) if and only
500 //! if there is no element with key equivalent to the key of that element.
502 //! <b>Complexity</b>: N log(size()+N) (N is the distance from i to j)
503 template <class InputIterator>
504 void insert(InputIterator first, InputIterator last)
505 { m_tree.insert_unique(first, last); }
507 #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
509 //! <b>Effects</b>: Inserts an object of type T constructed with
510 //! std::forward<Args>(args)... in the container if and only if there is
511 //! no element in the container with an equivalent key.
512 //! p is a hint pointing to where the insert should start to search.
514 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
515 //! to the key of x.
517 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
518 //! is inserted right before p.
519 template <class... Args>
520 iterator emplace(Args&&... args)
521 { return m_tree.emplace_unique(boost::interprocess::forward<Args>(args)...); }
523 //! <b>Effects</b>: Inserts an object of type T constructed with
524 //! std::forward<Args>(args)... in the container if and only if there is
525 //! no element in the container with an equivalent key.
526 //! p is a hint pointing to where the insert should start to search.
528 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
529 //! to the key of x.
531 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
532 //! is inserted right before p.
533 template <class... Args>
534 iterator emplace_hint(const_iterator hint, Args&&... args)
535 { return m_tree.emplace_hint_unique(hint, boost::interprocess::forward<Args>(args)...); }
537 #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
539 iterator emplace()
540 { return m_tree.emplace_unique(); }
542 iterator emplace_hint(const_iterator hint)
543 { return m_tree.emplace_hint_unique(hint); }
545 #define BOOST_PP_LOCAL_MACRO(n) \
546 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
547 iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
548 { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \
550 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
551 iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
552 { return m_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));}\
554 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
555 #include BOOST_PP_LOCAL_ITERATE()
557 #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
559 //! <b>Effects</b>: Erases the element pointed to by position.
561 //! <b>Returns</b>: Returns an iterator pointing to the element immediately
562 //! following q prior to the element being erased. If no such element exists,
563 //! returns end().
565 //! <b>Complexity</b>: Amortized constant time
566 iterator erase(const_iterator position)
567 { return m_tree.erase(position); }
569 //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
571 //! <b>Returns</b>: Returns the number of erased elements.
573 //! <b>Complexity</b>: log(size()) + count(k)
574 size_type erase(const key_type& x)
575 { return m_tree.erase(x); }
577 //! <b>Effects</b>: Erases all the elements in the range [first, last).
579 //! <b>Returns</b>: Returns last.
581 //! <b>Complexity</b>: log(size())+N where N is the distance from first to last.
582 iterator erase(const_iterator first, const_iterator last)
583 { return m_tree.erase(first, last); }
585 //! <b>Effects</b>: erase(a.begin(),a.end()).
587 //! <b>Postcondition</b>: size() == 0.
589 //! <b>Complexity</b>: linear in size().
590 void clear()
591 { m_tree.clear(); }
593 //! <b>Returns</b>: An iterator pointing to an element with the key
594 //! equivalent to x, or end() if such an element is not found.
596 //! <b>Complexity</b>: Logarithmic.
597 iterator find(const key_type& x)
598 { return m_tree.find(x); }
600 //! <b>Returns</b>: A const_iterator pointing to an element with the key
601 //! equivalent to x, or end() if such an element is not found.
603 //! <b>Complexity</b>: Logarithmic.
604 const_iterator find(const key_type& x) const
605 { return m_tree.find(x); }
607 //! <b>Returns</b>: The number of elements with key equivalent to x.
609 //! <b>Complexity</b>: log(size())+count(k)
610 size_type count(const key_type& x) const
611 { return m_tree.find(x) == m_tree.end() ? 0 : 1; }
613 //! <b>Returns</b>: An iterator pointing to the first element with key not less
614 //! than k, or a.end() if such an element is not found.
616 //! <b>Complexity</b>: Logarithmic
617 iterator lower_bound(const key_type& x)
618 { return m_tree.lower_bound(x); }
620 //! <b>Returns</b>: A const iterator pointing to the first element with key not
621 //! less than k, or a.end() if such an element is not found.
623 //! <b>Complexity</b>: Logarithmic
624 const_iterator lower_bound(const key_type& x) const
625 { return m_tree.lower_bound(x); }
627 //! <b>Returns</b>: An iterator pointing to the first element with key not less
628 //! than x, or end() if such an element is not found.
630 //! <b>Complexity</b>: Logarithmic
631 iterator upper_bound(const key_type& x)
632 { return m_tree.upper_bound(x); }
634 //! <b>Returns</b>: A const iterator pointing to the first element with key not
635 //! less than x, or end() if such an element is not found.
637 //! <b>Complexity</b>: Logarithmic
638 const_iterator upper_bound(const key_type& x) const
639 { return m_tree.upper_bound(x); }
641 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
643 //! <b>Complexity</b>: Logarithmic
644 std::pair<iterator,iterator> equal_range(const key_type& x)
645 { return m_tree.equal_range(x); }
647 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
649 //! <b>Complexity</b>: Logarithmic
650 std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
651 { return m_tree.equal_range(x); }
653 /// @cond
654 template <class K1, class T1, class C1, class A1>
655 friend bool operator== (const map<K1, T1, C1, A1>&,
656 const map<K1, T1, C1, A1>&);
657 template <class K1, class T1, class C1, class A1>
658 friend bool operator< (const map<K1, T1, C1, A1>&,
659 const map<K1, T1, C1, A1>&);
660 /// @endcond
663 template <class Key, class T, class Pred, class Alloc>
664 inline bool operator==(const map<Key,T,Pred,Alloc>& x,
665 const map<Key,T,Pred,Alloc>& y)
666 { return x.m_tree == y.m_tree; }
668 template <class Key, class T, class Pred, class Alloc>
669 inline bool operator<(const map<Key,T,Pred,Alloc>& x,
670 const map<Key,T,Pred,Alloc>& y)
671 { return x.m_tree < y.m_tree; }
673 template <class Key, class T, class Pred, class Alloc>
674 inline bool operator!=(const map<Key,T,Pred,Alloc>& x,
675 const map<Key,T,Pred,Alloc>& y)
676 { return !(x == y); }
678 template <class Key, class T, class Pred, class Alloc>
679 inline bool operator>(const map<Key,T,Pred,Alloc>& x,
680 const map<Key,T,Pred,Alloc>& y)
681 { return y < x; }
683 template <class Key, class T, class Pred, class Alloc>
684 inline bool operator<=(const map<Key,T,Pred,Alloc>& x,
685 const map<Key,T,Pred,Alloc>& y)
686 { return !(y < x); }
688 template <class Key, class T, class Pred, class Alloc>
689 inline bool operator>=(const map<Key,T,Pred,Alloc>& x,
690 const map<Key,T,Pred,Alloc>& y)
691 { return !(x < y); }
693 template <class Key, class T, class Pred, class Alloc>
694 inline void swap(map<Key,T,Pred,Alloc>& x, map<Key,T,Pred,Alloc>& y)
695 { x.swap(y); }
697 /// @cond
699 // Forward declaration of operators < and ==, needed for friend declaration.
701 template <class Key, class T, class Pred, class Alloc>
702 inline bool operator==(const multimap<Key,T,Pred,Alloc>& x,
703 const multimap<Key,T,Pred,Alloc>& y);
705 template <class Key, class T, class Pred, class Alloc>
706 inline bool operator<(const multimap<Key,T,Pred,Alloc>& x,
707 const multimap<Key,T,Pred,Alloc>& y);
709 } //namespace interprocess_container {
711 namespace interprocess {
713 //!has_trivial_destructor_after_move<> == true_type
714 //!specialization for optimizations
715 template <class K, class T, class C, class A>
716 struct has_trivial_destructor_after_move<boost::interprocess_container::map<K, T, C, A> >
718 static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
721 } //namespace interprocess {
723 namespace interprocess_container {
725 /// @endcond
727 //! A multimap is a kind of associative container that supports equivalent keys
728 //! (possibly containing multiple copies of the same key value) and provides for
729 //! fast retrieval of values of another type T based on the keys. The multimap class
730 //! supports bidirectional iterators.
731 //!
732 //! A multimap satisfies all of the requirements of a container and of a reversible
733 //! container and of an associative container. For a
734 //! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>.
736 //! Pred is the ordering function for Keys (e.g. <i>std::less<Key></i>).
738 //! Alloc is the allocator to allocate the value_types
739 //!(e.g. <i>allocator< std::pair<<b>const</b> Key, T> ></i>).
740 template <class Key, class T, class Pred, class Alloc>
741 class multimap
743 /// @cond
744 private:
745 typedef containers_detail::rbtree<Key,
746 std::pair<const Key, T>,
747 containers_detail::select1st< std::pair<const Key, T> >,
748 Pred,
749 Alloc> tree_t;
750 tree_t m_tree; // red-black tree representing map
751 /// @endcond
753 public:
754 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(multimap)
756 // typedefs:
757 typedef typename tree_t::key_type key_type;
758 typedef typename tree_t::value_type value_type;
759 typedef typename tree_t::pointer pointer;
760 typedef typename tree_t::const_pointer const_pointer;
761 typedef typename tree_t::reference reference;
762 typedef typename tree_t::const_reference const_reference;
763 typedef T mapped_type;
764 typedef Pred key_compare;
765 typedef typename tree_t::iterator iterator;
766 typedef typename tree_t::const_iterator const_iterator;
767 typedef typename tree_t::reverse_iterator reverse_iterator;
768 typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
769 typedef typename tree_t::size_type size_type;
770 typedef typename tree_t::difference_type difference_type;
771 typedef typename tree_t::allocator_type allocator_type;
772 typedef typename tree_t::stored_allocator_type stored_allocator_type;
773 typedef std::pair<key_type, mapped_type> nonconst_value_type;
774 typedef containers_detail::pair
775 <key_type, mapped_type> nonconst_impl_value_type;
777 /// @cond
778 class value_compare_impl
779 : public Pred,
780 public std::binary_function<value_type, value_type, bool>
782 friend class multimap<Key,T,Pred,Alloc>;
783 protected :
784 value_compare_impl(const Pred &c) : Pred(c) {}
785 public:
786 bool operator()(const value_type& x, const value_type& y) const {
787 return Pred::operator()(x.first, y.first);
790 /// @endcond
791 typedef value_compare_impl value_compare;
793 //! <b>Effects</b>: Constructs an empty multimap using the specified comparison
794 //! object and allocator.
795 //!
796 //! <b>Complexity</b>: Constant.
797 explicit multimap(const Pred& comp = Pred(),
798 const allocator_type& a = allocator_type())
799 : m_tree(comp, a)
802 //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object
803 //! and allocator, and inserts elements from the range [first ,last ).
804 //!
805 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
806 //! comp and otherwise N logN, where N is last - first.
807 template <class InputIterator>
808 multimap(InputIterator first, InputIterator last,
809 const Pred& comp = Pred(),
810 const allocator_type& a = allocator_type())
811 : m_tree(first, last, comp, a, false)
814 //! <b>Effects</b>: Copy constructs a multimap.
815 //!
816 //! <b>Complexity</b>: Linear in x.size().
817 multimap(const multimap<Key,T,Pred,Alloc>& x)
818 : m_tree(x.m_tree)
821 //! <b>Effects</b>: Move constructs a multimap. Constructs *this using x's resources.
822 //!
823 //! <b>Complexity</b>: Construct.
824 //!
825 //! <b>Postcondition</b>: x is emptied.
826 multimap(BOOST_INTERPROCESS_RV_REF(multimap) x)
827 : m_tree(boost::interprocess::move(x.m_tree))
830 //! <b>Effects</b>: Makes *this a copy of x.
831 //!
832 //! <b>Complexity</b>: Linear in x.size().
833 multimap& operator=(const multimap<Key,T,Pred,Alloc>& x)
834 { m_tree = x.m_tree; return *this; }
836 //! <b>Effects</b>: this->swap(x.get()).
837 //!
838 //! <b>Complexity</b>: Constant.
839 multimap& operator=(BOOST_INTERPROCESS_RV_REF(multimap) x)
840 { m_tree = boost::interprocess::move(x.m_tree); return *this; }
842 //! <b>Effects</b>: Returns the comparison object out
843 //! of which a was constructed.
844 //!
845 //! <b>Complexity</b>: Constant.
846 key_compare key_comp() const
847 { return m_tree.key_comp(); }
849 //! <b>Effects</b>: Returns an object of value_compare constructed out
850 //! of the comparison object.
851 //!
852 //! <b>Complexity</b>: Constant.
853 value_compare value_comp() const
854 { return value_compare(m_tree.key_comp()); }
856 //! <b>Effects</b>: Returns a copy of the Allocator that
857 //! was passed to the object's constructor.
858 //!
859 //! <b>Complexity</b>: Constant.
860 allocator_type get_allocator() const
861 { return m_tree.get_allocator(); }
863 const stored_allocator_type &get_stored_allocator() const
864 { return m_tree.get_stored_allocator(); }
866 stored_allocator_type &get_stored_allocator()
867 { return m_tree.get_stored_allocator(); }
869 //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
870 //!
871 //! <b>Throws</b>: Nothing.
872 //!
873 //! <b>Complexity</b>: Constant.
874 iterator begin()
875 { return m_tree.begin(); }
877 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
878 //!
879 //! <b>Throws</b>: Nothing.
880 //!
881 //! <b>Complexity</b>: Constant.
882 const_iterator begin() const
883 { return m_tree.begin(); }
885 //! <b>Effects</b>: Returns an iterator to the end of the container.
886 //!
887 //! <b>Throws</b>: Nothing.
888 //!
889 //! <b>Complexity</b>: Constant.
890 iterator end()
891 { return m_tree.end(); }
893 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
894 //!
895 //! <b>Throws</b>: Nothing.
896 //!
897 //! <b>Complexity</b>: Constant.
898 const_iterator end() const
899 { return m_tree.end(); }
901 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
902 //! of the reversed container.
903 //!
904 //! <b>Throws</b>: Nothing.
905 //!
906 //! <b>Complexity</b>: Constant.
907 reverse_iterator rbegin()
908 { return m_tree.rbegin(); }
910 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
911 //! of the reversed container.
912 //!
913 //! <b>Throws</b>: Nothing.
914 //!
915 //! <b>Complexity</b>: Constant.
916 const_reverse_iterator rbegin() const
917 { return m_tree.rbegin(); }
919 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
920 //! of the reversed container.
921 //!
922 //! <b>Throws</b>: Nothing.
923 //!
924 //! <b>Complexity</b>: Constant.
925 reverse_iterator rend()
926 { return m_tree.rend(); }
928 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
929 //! of the reversed container.
930 //!
931 //! <b>Throws</b>: Nothing.
932 //!
933 //! <b>Complexity</b>: Constant.
934 const_reverse_iterator rend() const
935 { return m_tree.rend(); }
937 //! <b>Effects</b>: Returns true if the container contains no elements.
938 //!
939 //! <b>Throws</b>: Nothing.
940 //!
941 //! <b>Complexity</b>: Constant.
942 bool empty() const
943 { return m_tree.empty(); }
945 //! <b>Effects</b>: Returns the number of the elements contained in the container.
946 //!
947 //! <b>Throws</b>: Nothing.
948 //!
949 //! <b>Complexity</b>: Constant.
950 size_type size() const
951 { return m_tree.size(); }
953 //! <b>Effects</b>: Returns the largest possible size of the container.
954 //!
955 //! <b>Throws</b>: Nothing.
956 //!
957 //! <b>Complexity</b>: Constant.
958 size_type max_size() const
959 { return m_tree.max_size(); }
961 //! <b>Effects</b>: Swaps the contents of *this and x.
962 //! If this->allocator_type() != x.allocator_type() allocators are also swapped.
964 //! <b>Throws</b>: Nothing.
966 //! <b>Complexity</b>: Constant.
967 void swap(multimap& x)
968 { m_tree.swap(x.m_tree); }
970 //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
971 //! newly inserted element.
973 //! <b>Complexity</b>: Logarithmic.
974 iterator insert(const value_type& x)
975 { return m_tree.insert_equal(x); }
977 //! <b>Effects</b>: Inserts a new value constructed from x and returns
978 //! the iterator pointing to the newly inserted element.
980 //! <b>Complexity</b>: Logarithmic.
981 iterator insert(const nonconst_value_type& x)
982 { return m_tree.insert_equal(x); }
984 //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
985 //! the iterator pointing to the newly inserted element.
987 //! <b>Complexity</b>: Logarithmic.
988 iterator insert(BOOST_INTERPROCESS_RV_REF(nonconst_value_type) x)
989 { return m_tree.insert_equal(boost::interprocess::move(x)); }
991 //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
992 //! the iterator pointing to the newly inserted element.
994 //! <b>Complexity</b>: Logarithmic.
995 iterator insert(BOOST_INTERPROCESS_RV_REF(nonconst_impl_value_type) x)
996 { return m_tree.insert_equal(boost::interprocess::move(x)); }
998 //! <b>Effects</b>: Inserts a copy of x in the container.
999 //! p is a hint pointing to where the insert should start to search.
1001 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1002 //! to the key of x.
1004 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1005 //! is inserted right before p.
1006 iterator insert(iterator position, const value_type& x)
1007 { return m_tree.insert_equal(position, x); }
1009 //! <b>Effects</b>: Inserts a new value constructed from x in the container.
1010 //! p is a hint pointing to where the insert should start to search.
1012 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1013 //! to the key of x.
1015 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1016 //! is inserted right before p.
1017 iterator insert(iterator position, const nonconst_value_type& x)
1018 { return m_tree.insert_equal(position, x); }
1020 //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
1021 //! p is a hint pointing to where the insert should start to search.
1023 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1024 //! to the key of x.
1026 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1027 //! is inserted right before p.
1028 iterator insert(iterator position, BOOST_INTERPROCESS_RV_REF(nonconst_value_type) x)
1029 { return m_tree.insert_equal(position, boost::interprocess::move(x)); }
1031 //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
1032 //! p is a hint pointing to where the insert should start to search.
1034 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1035 //! to the key of x.
1037 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1038 //! is inserted right before p.
1039 iterator insert(iterator position, BOOST_INTERPROCESS_RV_REF(nonconst_impl_value_type) x)
1040 { return m_tree.insert_equal(position, boost::interprocess::move(x)); }
1042 //! <b>Requires</b>: i, j are not iterators into *this.
1044 //! <b>Effects</b>: inserts each element from the range [i,j) .
1046 //! <b>Complexity</b>: N log(size()+N) (N is the distance from i to j)
1047 template <class InputIterator>
1048 void insert(InputIterator first, InputIterator last)
1049 { m_tree.insert_equal(first, last); }
1051 #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
1053 //! <b>Effects</b>: Inserts an object of type T constructed with
1054 //! std::forward<Args>(args)... in the container.
1055 //! p is a hint pointing to where the insert should start to search.
1057 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1058 //! to the key of x.
1060 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1061 //! is inserted right before p.
1062 template <class... Args>
1063 iterator emplace(Args&&... args)
1064 { return m_tree.emplace_equal(boost::interprocess::forward<Args>(args)...); }
1066 //! <b>Effects</b>: Inserts an object of type T constructed with
1067 //! std::forward<Args>(args)... in the container.
1068 //! p is a hint pointing to where the insert should start to search.
1070 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1071 //! to the key of x.
1073 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1074 //! is inserted right before p.
1075 template <class... Args>
1076 iterator emplace_hint(const_iterator hint, Args&&... args)
1077 { return m_tree.emplace_hint_equal(hint, boost::interprocess::forward<Args>(args)...); }
1079 #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
1081 iterator emplace()
1082 { return m_tree.emplace_equal(); }
1084 iterator emplace_hint(const_iterator hint)
1085 { return m_tree.emplace_hint_equal(hint); }
1087 #define BOOST_PP_LOCAL_MACRO(n) \
1088 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
1089 iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
1090 { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \
1092 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
1093 iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
1094 { return m_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }\
1096 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
1097 #include BOOST_PP_LOCAL_ITERATE()
1099 #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
1101 //! <b>Effects</b>: Erases the element pointed to by position.
1103 //! <b>Returns</b>: Returns an iterator pointing to the element immediately
1104 //! following q prior to the element being erased. If no such element exists,
1105 //! returns end().
1107 //! <b>Complexity</b>: Amortized constant time
1108 iterator erase(const_iterator position)
1109 { return m_tree.erase(position); }
1111 //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
1113 //! <b>Returns</b>: Returns the number of erased elements.
1115 //! <b>Complexity</b>: log(size()) + count(k)
1116 size_type erase(const key_type& x)
1117 { return m_tree.erase(x); }
1119 //! <b>Effects</b>: Erases all the elements in the range [first, last).
1121 //! <b>Returns</b>: Returns last.
1123 //! <b>Complexity</b>: log(size())+N where N is the distance from first to last.
1124 iterator erase(const_iterator first, const_iterator last)
1125 { return m_tree.erase(first, last); }
1127 //! <b>Effects</b>: erase(a.begin(),a.end()).
1129 //! <b>Postcondition</b>: size() == 0.
1131 //! <b>Complexity</b>: linear in size().
1132 void clear()
1133 { m_tree.clear(); }
1135 //! <b>Returns</b>: An iterator pointing to an element with the key
1136 //! equivalent to x, or end() if such an element is not found.
1138 //! <b>Complexity</b>: Logarithmic.
1139 iterator find(const key_type& x)
1140 { return m_tree.find(x); }
1142 //! <b>Returns</b>: A const iterator pointing to an element with the key
1143 //! equivalent to x, or end() if such an element is not found.
1145 //! <b>Complexity</b>: Logarithmic.
1146 const_iterator find(const key_type& x) const
1147 { return m_tree.find(x); }
1149 //! <b>Returns</b>: The number of elements with key equivalent to x.
1151 //! <b>Complexity</b>: log(size())+count(k)
1152 size_type count(const key_type& x) const
1153 { return m_tree.count(x); }
1155 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1156 //! than k, or a.end() if such an element is not found.
1158 //! <b>Complexity</b>: Logarithmic
1159 iterator lower_bound(const key_type& x)
1160 {return m_tree.lower_bound(x); }
1162 //! <b>Returns</b>: A const iterator pointing to the first element with key not
1163 //! less than k, or a.end() if such an element is not found.
1165 //! <b>Complexity</b>: Logarithmic
1166 const_iterator lower_bound(const key_type& x) const
1167 { return m_tree.lower_bound(x); }
1169 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1170 //! than x, or end() if such an element is not found.
1172 //! <b>Complexity</b>: Logarithmic
1173 iterator upper_bound(const key_type& x)
1174 { return m_tree.upper_bound(x); }
1176 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1178 //! <b>Complexity</b>: Logarithmic
1179 std::pair<iterator,iterator> equal_range(const key_type& x)
1180 { return m_tree.equal_range(x); }
1182 //! <b>Returns</b>: A const iterator pointing to the first element with key not
1183 //! less than x, or end() if such an element is not found.
1185 //! <b>Complexity</b>: Logarithmic
1186 const_iterator upper_bound(const key_type& x) const
1187 { return m_tree.upper_bound(x); }
1189 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1191 //! <b>Complexity</b>: Logarithmic
1192 std::pair<const_iterator,const_iterator>
1193 equal_range(const key_type& x) const
1194 { return m_tree.equal_range(x); }
1196 /// @cond
1197 template <class K1, class T1, class C1, class A1>
1198 friend bool operator== (const multimap<K1, T1, C1, A1>& x,
1199 const multimap<K1, T1, C1, A1>& y);
1201 template <class K1, class T1, class C1, class A1>
1202 friend bool operator< (const multimap<K1, T1, C1, A1>& x,
1203 const multimap<K1, T1, C1, A1>& y);
1204 /// @endcond
1207 template <class Key, class T, class Pred, class Alloc>
1208 inline bool operator==(const multimap<Key,T,Pred,Alloc>& x,
1209 const multimap<Key,T,Pred,Alloc>& y)
1210 { return x.m_tree == y.m_tree; }
1212 template <class Key, class T, class Pred, class Alloc>
1213 inline bool operator<(const multimap<Key,T,Pred,Alloc>& x,
1214 const multimap<Key,T,Pred,Alloc>& y)
1215 { return x.m_tree < y.m_tree; }
1217 template <class Key, class T, class Pred, class Alloc>
1218 inline bool operator!=(const multimap<Key,T,Pred,Alloc>& x,
1219 const multimap<Key,T,Pred,Alloc>& y)
1220 { return !(x == y); }
1222 template <class Key, class T, class Pred, class Alloc>
1223 inline bool operator>(const multimap<Key,T,Pred,Alloc>& x,
1224 const multimap<Key,T,Pred,Alloc>& y)
1225 { return y < x; }
1227 template <class Key, class T, class Pred, class Alloc>
1228 inline bool operator<=(const multimap<Key,T,Pred,Alloc>& x,
1229 const multimap<Key,T,Pred,Alloc>& y)
1230 { return !(y < x); }
1232 template <class Key, class T, class Pred, class Alloc>
1233 inline bool operator>=(const multimap<Key,T,Pred,Alloc>& x,
1234 const multimap<Key,T,Pred,Alloc>& y)
1235 { return !(x < y); }
1237 template <class Key, class T, class Pred, class Alloc>
1238 inline void swap(multimap<Key,T,Pred,Alloc>& x, multimap<Key,T,Pred,Alloc>& y)
1239 { x.swap(y); }
1241 /// @cond
1243 } //namespace interprocess_container {
1245 namespace interprocess {
1247 //!has_trivial_destructor_after_move<> == true_type
1248 //!specialization for optimizations
1249 template <class K, class T, class C, class A>
1250 struct has_trivial_destructor_after_move<boost::interprocess_container::multimap<K, T, C, A> >
1252 static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
1255 } //namespace interprocess {
1257 namespace interprocess_container {
1259 /// @endcond
1263 #include <boost/interprocess/containers/container/detail/config_end.hpp>
1265 #endif /* BOOST_CONTAINERS_MAP_HPP */