comparison DEPENDENCIES/generic/include/boost/container/map.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2012. 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 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_CONTAINER_MAP_HPP
12 #define BOOST_CONTAINER_MAP_HPP
13
14 #if defined(_MSC_VER)
15 # pragma once
16 #endif
17
18 #include <boost/container/detail/config_begin.hpp>
19 #include <boost/container/detail/workaround.hpp>
20
21 #include <boost/container/container_fwd.hpp>
22 #include <utility>
23 #include <functional>
24 #include <memory>
25 #include <boost/container/detail/tree.hpp>
26 #include <boost/container/detail/value_init.hpp>
27 #include <boost/type_traits/has_trivial_destructor.hpp>
28 #include <boost/container/detail/mpl.hpp>
29 #include <boost/container/detail/utilities.hpp>
30 #include <boost/container/detail/pair.hpp>
31 #include <boost/container/detail/type_traits.hpp>
32 #include <boost/container/throw_exception.hpp>
33 #include <boost/move/utility.hpp>
34 #include <boost/move/detail/move_helpers.hpp>
35 #include <boost/static_assert.hpp>
36 #include <boost/container/detail/value_init.hpp>
37 #include <boost/detail/no_exceptions_support.hpp>
38
39 namespace boost {
40 namespace container {
41
42 /// @cond
43 // Forward declarations of operators == and <, needed for friend declarations.
44 template <class Key, class T, class Compare, class Allocator>
45 inline bool operator==(const map<Key,T,Compare,Allocator>& x,
46 const map<Key,T,Compare,Allocator>& y);
47
48 template <class Key, class T, class Compare, class Allocator>
49 inline bool operator<(const map<Key,T,Compare,Allocator>& x,
50 const map<Key,T,Compare,Allocator>& y);
51 /// @endcond
52
53 //! A map is a kind of associative container that supports unique keys (contains at
54 //! most one of each key value) and provides for fast retrieval of values of another
55 //! type T based on the keys. The map class supports bidirectional iterators.
56 //!
57 //! A map satisfies all of the requirements of a container and of a reversible
58 //! container and of an associative container. For a
59 //! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>.
60 //!
61 //! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
62 //!
63 //! Allocator is the allocator to allocate the value_types
64 //! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
65 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
66 template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > >
67 #else
68 template <class Key, class T, class Compare, class Allocator>
69 #endif
70 class map
71 {
72 /// @cond
73 private:
74 BOOST_COPYABLE_AND_MOVABLE(map)
75
76 typedef std::pair<const Key, T> value_type_impl;
77 typedef container_detail::rbtree
78 <Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator> tree_t;
79 typedef container_detail::pair <Key, T> movable_value_type_impl;
80 typedef container_detail::tree_value_compare
81 < Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
82 > value_compare_impl;
83 tree_t m_tree; // red-black tree representing map
84 /// @endcond
85
86 public:
87 //////////////////////////////////////////////
88 //
89 // types
90 //
91 //////////////////////////////////////////////
92
93 typedef Key key_type;
94 typedef T mapped_type;
95 typedef std::pair<const Key, T> value_type;
96 typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
97 typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
98 typedef typename boost::container::allocator_traits<Allocator>::reference reference;
99 typedef typename boost::container::allocator_traits<Allocator>::const_reference const_reference;
100 typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
101 typedef typename boost::container::allocator_traits<Allocator>::difference_type difference_type;
102 typedef Allocator allocator_type;
103 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
104 typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare;
105 typedef Compare key_compare;
106 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::iterator) iterator;
107 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_iterator) const_iterator;
108 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::reverse_iterator) reverse_iterator;
109 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_reverse_iterator) const_reverse_iterator;
110 typedef std::pair<key_type, mapped_type> nonconst_value_type;
111 typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type;
112
113 //////////////////////////////////////////////
114 //
115 // construct/copy/destroy
116 //
117 //////////////////////////////////////////////
118
119 //! <b>Effects</b>: Default constructs an empty map.
120 //!
121 //! <b>Complexity</b>: Constant.
122 map()
123 : m_tree()
124 {
125 //Allocator type must be std::pair<CONST Key, T>
126 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
127 }
128
129 //! <b>Effects</b>: Constructs an empty map using the specified comparison object
130 //! and allocator.
131 //!
132 //! <b>Complexity</b>: Constant.
133 explicit map(const Compare& comp,
134 const allocator_type& a = allocator_type())
135 : m_tree(comp, a)
136 {
137 //Allocator type must be std::pair<CONST Key, T>
138 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
139 }
140
141 //! <b>Effects</b>: Constructs an empty map using the specified allocator.
142 //!
143 //! <b>Complexity</b>: Constant.
144 explicit map(const allocator_type& a)
145 : m_tree(a)
146 {
147 //Allocator type must be std::pair<CONST Key, T>
148 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
149 }
150
151 //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
152 //! allocator, and inserts elements from the range [first ,last ).
153 //!
154 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
155 //! comp and otherwise N logN, where N is last - first.
156 template <class InputIterator>
157 map(InputIterator first, InputIterator last, const Compare& comp = Compare(),
158 const allocator_type& a = allocator_type())
159 : m_tree(true, first, last, comp, a)
160 {
161 //Allocator type must be std::pair<CONST Key, T>
162 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
163 }
164
165 //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
166 //! allocator, and inserts elements from the ordered unique range [first ,last). This function
167 //! is more efficient than the normal range creation for ordered ranges.
168 //!
169 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
170 //! unique values.
171 //!
172 //! <b>Complexity</b>: Linear in N.
173 //!
174 //! <b>Note</b>: Non-standard extension.
175 template <class InputIterator>
176 map( ordered_unique_range_t, InputIterator first, InputIterator last
177 , const Compare& comp = Compare(), const allocator_type& a = allocator_type())
178 : m_tree(ordered_range, first, last, comp, a)
179 {
180 //Allocator type must be std::pair<CONST Key, T>
181 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
182 }
183
184 //! <b>Effects</b>: Copy constructs a map.
185 //!
186 //! <b>Complexity</b>: Linear in x.size().
187 map(const map& x)
188 : m_tree(x.m_tree)
189 {
190 //Allocator type must be std::pair<CONST Key, T>
191 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
192 }
193
194 //! <b>Effects</b>: Move constructs a map. Constructs *this using x's resources.
195 //!
196 //! <b>Complexity</b>: Constant.
197 //!
198 //! <b>Postcondition</b>: x is emptied.
199 map(BOOST_RV_REF(map) x)
200 : m_tree(boost::move(x.m_tree))
201 {
202 //Allocator type must be std::pair<CONST Key, T>
203 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
204 }
205
206 //! <b>Effects</b>: Copy constructs a map using the specified allocator.
207 //!
208 //! <b>Complexity</b>: Linear in x.size().
209 map(const map& x, const allocator_type &a)
210 : m_tree(x.m_tree, a)
211 {
212 //Allocator type must be std::pair<CONST Key, T>
213 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
214 }
215
216 //! <b>Effects</b>: Move constructs a map using the specified allocator.
217 //! Constructs *this using x's resources.
218 //!
219 //! <b>Complexity</b>: Constant if x == x.get_allocator(), linear otherwise.
220 //!
221 //! <b>Postcondition</b>: x is emptied.
222 map(BOOST_RV_REF(map) x, const allocator_type &a)
223 : m_tree(boost::move(x.m_tree), a)
224 {
225 //Allocator type must be std::pair<CONST Key, T>
226 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
227 }
228
229 //! <b>Effects</b>: Makes *this a copy of x.
230 //!
231 //! <b>Complexity</b>: Linear in x.size().
232 map& operator=(BOOST_COPY_ASSIGN_REF(map) x)
233 { m_tree = x.m_tree; return *this; }
234
235 //! <b>Effects</b>: this->swap(x.get()).
236 //!
237 //! <b>Complexity</b>: Constant.
238 map& operator=(BOOST_RV_REF(map) x)
239 { m_tree = boost::move(x.m_tree); return *this; }
240
241 //! <b>Effects</b>: Returns a copy of the Allocator that
242 //! was passed to the object's constructor.
243 //!
244 //! <b>Complexity</b>: Constant.
245 allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
246 { return m_tree.get_allocator(); }
247
248 //! <b>Effects</b>: Returns a reference to the internal allocator.
249 //!
250 //! <b>Throws</b>: Nothing
251 //!
252 //! <b>Complexity</b>: Constant.
253 //!
254 //! <b>Note</b>: Non-standard extension.
255 stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
256 { return m_tree.get_stored_allocator(); }
257
258 //! <b>Effects</b>: Returns a reference to the internal allocator.
259 //!
260 //! <b>Throws</b>: Nothing
261 //!
262 //! <b>Complexity</b>: Constant.
263 //!
264 //! <b>Note</b>: Non-standard extension.
265 const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
266 { return m_tree.get_stored_allocator(); }
267
268 //////////////////////////////////////////////
269 //
270 // iterators
271 //
272 //////////////////////////////////////////////
273
274 //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
275 //!
276 //! <b>Throws</b>: Nothing.
277 //!
278 //! <b>Complexity</b>: Constant.
279 iterator begin() BOOST_CONTAINER_NOEXCEPT
280 { return m_tree.begin(); }
281
282 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
283 //!
284 //! <b>Throws</b>: Nothing.
285 //!
286 //! <b>Complexity</b>: Constant.
287 const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
288 { return this->cbegin(); }
289
290 //! <b>Effects</b>: Returns an iterator to the end of the container.
291 //!
292 //! <b>Throws</b>: Nothing.
293 //!
294 //! <b>Complexity</b>: Constant.
295 iterator end() BOOST_CONTAINER_NOEXCEPT
296 { return m_tree.end(); }
297
298 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
299 //!
300 //! <b>Throws</b>: Nothing.
301 //!
302 //! <b>Complexity</b>: Constant.
303 const_iterator end() const BOOST_CONTAINER_NOEXCEPT
304 { return this->cend(); }
305
306 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
307 //! of the reversed container.
308 //!
309 //! <b>Throws</b>: Nothing.
310 //!
311 //! <b>Complexity</b>: Constant.
312 reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
313 { return m_tree.rbegin(); }
314
315 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
316 //! of the reversed container.
317 //!
318 //! <b>Throws</b>: Nothing.
319 //!
320 //! <b>Complexity</b>: Constant.
321 const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
322 { return this->crbegin(); }
323
324 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
325 //! of the reversed container.
326 //!
327 //! <b>Throws</b>: Nothing.
328 //!
329 //! <b>Complexity</b>: Constant.
330 reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
331 { return m_tree.rend(); }
332
333 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
334 //! of the reversed container.
335 //!
336 //! <b>Throws</b>: Nothing.
337 //!
338 //! <b>Complexity</b>: Constant.
339 const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
340 { return this->crend(); }
341
342 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
343 //!
344 //! <b>Throws</b>: Nothing.
345 //!
346 //! <b>Complexity</b>: Constant.
347 const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
348 { return m_tree.begin(); }
349
350 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
351 //!
352 //! <b>Throws</b>: Nothing.
353 //!
354 //! <b>Complexity</b>: Constant.
355 const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
356 { return m_tree.end(); }
357
358 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
359 //! of the reversed container.
360 //!
361 //! <b>Throws</b>: Nothing.
362 //!
363 //! <b>Complexity</b>: Constant.
364 const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
365 { return m_tree.rbegin(); }
366
367 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
368 //! of the reversed container.
369 //!
370 //! <b>Throws</b>: Nothing.
371 //!
372 //! <b>Complexity</b>: Constant.
373 const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
374 { return m_tree.rend(); }
375
376 //////////////////////////////////////////////
377 //
378 // capacity
379 //
380 //////////////////////////////////////////////
381
382 //! <b>Effects</b>: Returns true if the container contains no elements.
383 //!
384 //! <b>Throws</b>: Nothing.
385 //!
386 //! <b>Complexity</b>: Constant.
387 bool empty() const BOOST_CONTAINER_NOEXCEPT
388 { return m_tree.empty(); }
389
390 //! <b>Effects</b>: Returns the number of the elements contained in the container.
391 //!
392 //! <b>Throws</b>: Nothing.
393 //!
394 //! <b>Complexity</b>: Constant.
395 size_type size() const BOOST_CONTAINER_NOEXCEPT
396 { return m_tree.size(); }
397
398 //! <b>Effects</b>: Returns the largest possible size of the container.
399 //!
400 //! <b>Throws</b>: Nothing.
401 //!
402 //! <b>Complexity</b>: Constant.
403 size_type max_size() const BOOST_CONTAINER_NOEXCEPT
404 { return m_tree.max_size(); }
405
406 //////////////////////////////////////////////
407 //
408 // element access
409 //
410 //////////////////////////////////////////////
411
412 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
413 //! Effects: If there is no key equivalent to x in the map, inserts
414 //! value_type(x, T()) into the map.
415 //!
416 //! Returns: Allocator reference to the mapped_type corresponding to x in *this.
417 //!
418 //! Complexity: Logarithmic.
419 mapped_type& operator[](const key_type &k);
420
421 //! Effects: If there is no key equivalent to x in the map, inserts
422 //! value_type(boost::move(x), T()) into the map (the key is move-constructed)
423 //!
424 //! Returns: Allocator reference to the mapped_type corresponding to x in *this.
425 //!
426 //! Complexity: Logarithmic.
427 mapped_type& operator[](key_type &&k);
428 #else
429 BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
430 #endif
431
432 //! Returns: Allocator reference to the element whose key is equivalent to x.
433 //! Throws: An exception object of type out_of_range if no such element is present.
434 //! Complexity: logarithmic.
435 T& at(const key_type& k)
436 {
437 iterator i = this->find(k);
438 if(i == this->end()){
439 throw_out_of_range("map::at key not found");
440 }
441 return i->second;
442 }
443
444 //! Returns: Allocator reference to the element whose key is equivalent to x.
445 //! Throws: An exception object of type out_of_range if no such element is present.
446 //! Complexity: logarithmic.
447 const T& at(const key_type& k) const
448 {
449 const_iterator i = this->find(k);
450 if(i == this->end()){
451 throw_out_of_range("map::at key not found");
452 }
453 return i->second;
454 }
455
456 //////////////////////////////////////////////
457 //
458 // modifiers
459 //
460 //////////////////////////////////////////////
461
462 //! <b>Effects</b>: Inserts x if and only if there is no element in the container
463 //! with key equivalent to the key of x.
464 //!
465 //! <b>Returns</b>: The bool component of the returned pair is true if and only
466 //! if the insertion takes place, and the iterator component of the pair
467 //! points to the element with key equivalent to the key of x.
468 //!
469 //! <b>Complexity</b>: Logarithmic.
470 std::pair<iterator,bool> insert(const value_type& x)
471 { return m_tree.insert_unique(x); }
472
473 //! <b>Effects</b>: Inserts a new value_type created from the pair if and only if
474 //! there is no element in the container with key equivalent to the key of x.
475 //!
476 //! <b>Returns</b>: The bool component of the returned pair is true if and only
477 //! if the insertion takes place, and the iterator component of the pair
478 //! points to the element with key equivalent to the key of x.
479 //!
480 //! <b>Complexity</b>: Logarithmic.
481 std::pair<iterator,bool> insert(const nonconst_value_type& x)
482 { return m_tree.insert_unique(x); }
483
484 //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
485 //! only if there is no element in the container with key equivalent to the key of x.
486 //!
487 //! <b>Returns</b>: The bool component of the returned pair is true if and only
488 //! if the insertion takes place, and the iterator component of the pair
489 //! points to the element with key equivalent to the key of x.
490 //!
491 //! <b>Complexity</b>: Logarithmic.
492 std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_value_type) x)
493 { return m_tree.insert_unique(boost::move(x)); }
494
495 //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
496 //! only if there is no element in the container with key equivalent to the key of x.
497 //!
498 //! <b>Returns</b>: The bool component of the returned pair is true if and only
499 //! if the insertion takes place, and the iterator component of the pair
500 //! points to the element with key equivalent to the key of x.
501 //!
502 //! <b>Complexity</b>: Logarithmic.
503 std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
504 { return m_tree.insert_unique(boost::move(x)); }
505
506 //! <b>Effects</b>: Move constructs a new value from x if and only if there is
507 //! no element in the container with key equivalent to the key of x.
508 //!
509 //! <b>Returns</b>: The bool component of the returned pair is true if and only
510 //! if the insertion takes place, and the iterator component of the pair
511 //! points to the element with key equivalent to the key of x.
512 //!
513 //! <b>Complexity</b>: Logarithmic.
514 std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
515 { return m_tree.insert_unique(boost::move(x)); }
516
517 //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
518 //! no element in the container with key equivalent to the key of x.
519 //! p is a hint pointing to where the insert should start to search.
520 //!
521 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
522 //! to the key of x.
523 //!
524 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
525 //! is inserted right before p.
526 iterator insert(const_iterator position, const value_type& x)
527 { return m_tree.insert_unique(position, x); }
528
529 //! <b>Effects</b>: Move constructs a new value from x if and only if there is
530 //! no element in the container with key equivalent to the key of x.
531 //! p is a hint pointing to where the insert should start to search.
532 //!
533 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
534 //! to the key of x.
535 //!
536 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
537 //! is inserted right before p.
538 iterator insert(const_iterator position, BOOST_RV_REF(nonconst_value_type) x)
539 { return m_tree.insert_unique(position, boost::move(x)); }
540
541 //! <b>Effects</b>: Move constructs a new value from x if and only if there is
542 //! no element in the container with key equivalent to the key of x.
543 //! p is a hint pointing to where the insert should start to search.
544 //!
545 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
546 //! to the key of x.
547 //!
548 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
549 //! is inserted right before p.
550 iterator insert(const_iterator position, BOOST_RV_REF(movable_value_type) x)
551 { return m_tree.insert_unique(position, boost::move(x)); }
552
553 //! <b>Effects</b>: Inserts a copy of x in the container.
554 //! p is a hint pointing to where the insert should start to search.
555 //!
556 //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
557 //!
558 //! <b>Complexity</b>: Logarithmic.
559 iterator insert(const_iterator position, const nonconst_value_type& x)
560 { return m_tree.insert_unique(position, x); }
561
562 //! <b>Effects</b>: Inserts an element move constructed from x in the container.
563 //! p is a hint pointing to where the insert should start to search.
564 //!
565 //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
566 //!
567 //! <b>Complexity</b>: Logarithmic.
568 iterator insert(const_iterator position, BOOST_RV_REF(value_type) x)
569 { return m_tree.insert_unique(position, boost::move(x)); }
570
571 //! <b>Requires</b>: first, last are not iterators into *this.
572 //!
573 //! <b>Effects</b>: inserts each element from the range [first,last) if and only
574 //! if there is no element with key equivalent to the key of that element.
575 //!
576 //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
577 template <class InputIterator>
578 void insert(InputIterator first, InputIterator last)
579 { m_tree.insert_unique(first, last); }
580
581 #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
582
583 //! <b>Effects</b>: Inserts an object x of type T constructed with
584 //! std::forward<Args>(args)... in the container if and only if there is
585 //! no element in the container with an equivalent key.
586 //! p is a hint pointing to where the insert should start to search.
587 //!
588 //! <b>Returns</b>: The bool component of the returned pair is true if and only
589 //! if the insertion takes place, and the iterator component of the pair
590 //! points to the element with key equivalent to the key of x.
591 //!
592 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
593 //! is inserted right before p.
594 template <class... Args>
595 std::pair<iterator,bool> emplace(Args&&... args)
596 { return m_tree.emplace_unique(boost::forward<Args>(args)...); }
597
598 //! <b>Effects</b>: Inserts an object of type T constructed with
599 //! std::forward<Args>(args)... in the container if and only if there is
600 //! no element in the container with an equivalent key.
601 //! p is a hint pointing to where the insert should start to search.
602 //!
603 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
604 //! to the key of x.
605 //!
606 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
607 //! is inserted right before p.
608 template <class... Args>
609 iterator emplace_hint(const_iterator hint, Args&&... args)
610 { return m_tree.emplace_hint_unique(hint, boost::forward<Args>(args)...); }
611
612 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
613
614 #define BOOST_PP_LOCAL_MACRO(n) \
615 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
616 std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
617 { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
618 \
619 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
620 iterator emplace_hint(const_iterator hint \
621 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
622 { return m_tree.emplace_hint_unique(hint \
623 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
624 //!
625 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
626 #include BOOST_PP_LOCAL_ITERATE()
627
628 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
629
630 //! <b>Effects</b>: Erases the element pointed to by position.
631 //!
632 //! <b>Returns</b>: Returns an iterator pointing to the element immediately
633 //! following q prior to the element being erased. If no such element exists,
634 //! returns end().
635 //!
636 //! <b>Complexity</b>: Amortized constant time
637 iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT
638 { return m_tree.erase(position); }
639
640 //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
641 //!
642 //! <b>Returns</b>: Returns the number of erased elements.
643 //!
644 //! <b>Complexity</b>: log(size()) + count(k)
645 size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT
646 { return m_tree.erase(x); }
647
648 //! <b>Effects</b>: Erases all the elements in the range [first, last).
649 //!
650 //! <b>Returns</b>: Returns last.
651 //!
652 //! <b>Complexity</b>: log(size())+N where N is the distance from first to last.
653 iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
654 { return m_tree.erase(first, last); }
655
656 //! <b>Effects</b>: Swaps the contents of *this and x.
657 //!
658 //! <b>Throws</b>: Nothing.
659 //!
660 //! <b>Complexity</b>: Constant.
661 void swap(map& x)
662 { m_tree.swap(x.m_tree); }
663
664 //! <b>Effects</b>: erase(a.begin(),a.end()).
665 //!
666 //! <b>Postcondition</b>: size() == 0.
667 //!
668 //! <b>Complexity</b>: linear in size().
669 void clear() BOOST_CONTAINER_NOEXCEPT
670 { m_tree.clear(); }
671
672 //////////////////////////////////////////////
673 //
674 // observers
675 //
676 //////////////////////////////////////////////
677
678 //! <b>Effects</b>: Returns the comparison object out
679 //! of which a was constructed.
680 //!
681 //! <b>Complexity</b>: Constant.
682 key_compare key_comp() const
683 { return m_tree.key_comp(); }
684
685 //! <b>Effects</b>: Returns an object of value_compare constructed out
686 //! of the comparison object.
687 //!
688 //! <b>Complexity</b>: Constant.
689 value_compare value_comp() const
690 { return value_compare(m_tree.key_comp()); }
691
692 //////////////////////////////////////////////
693 //
694 // map operations
695 //
696 //////////////////////////////////////////////
697
698 //! <b>Returns</b>: An iterator pointing to an element with the key
699 //! equivalent to x, or end() if such an element is not found.
700 //!
701 //! <b>Complexity</b>: Logarithmic.
702 iterator find(const key_type& x)
703 { return m_tree.find(x); }
704
705 //! <b>Returns</b>: Allocator const_iterator pointing to an element with the key
706 //! equivalent to x, or end() if such an element is not found.
707 //!
708 //! <b>Complexity</b>: Logarithmic.
709 const_iterator find(const key_type& x) const
710 { return m_tree.find(x); }
711
712 //! <b>Returns</b>: The number of elements with key equivalent to x.
713 //!
714 //! <b>Complexity</b>: log(size())+count(k)
715 size_type count(const key_type& x) const
716 { return static_cast<size_type>(m_tree.find(x) != m_tree.end()); }
717
718 //! <b>Returns</b>: An iterator pointing to the first element with key not less
719 //! than k, or a.end() if such an element is not found.
720 //!
721 //! <b>Complexity</b>: Logarithmic
722 iterator lower_bound(const key_type& x)
723 { return m_tree.lower_bound(x); }
724
725 //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not
726 //! less than k, or a.end() if such an element is not found.
727 //!
728 //! <b>Complexity</b>: Logarithmic
729 const_iterator lower_bound(const key_type& x) const
730 { return m_tree.lower_bound(x); }
731
732 //! <b>Returns</b>: An iterator pointing to the first element with key not less
733 //! than x, or end() if such an element is not found.
734 //!
735 //! <b>Complexity</b>: Logarithmic
736 iterator upper_bound(const key_type& x)
737 { return m_tree.upper_bound(x); }
738
739 //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not
740 //! less than x, or end() if such an element is not found.
741 //!
742 //! <b>Complexity</b>: Logarithmic
743 const_iterator upper_bound(const key_type& x) const
744 { return m_tree.upper_bound(x); }
745
746 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
747 //!
748 //! <b>Complexity</b>: Logarithmic
749 std::pair<iterator,iterator> equal_range(const key_type& x)
750 { return m_tree.equal_range(x); }
751
752 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
753 //!
754 //! <b>Complexity</b>: Logarithmic
755 std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
756 { return m_tree.equal_range(x); }
757
758 /// @cond
759 template <class K1, class T1, class C1, class A1>
760 friend bool operator== (const map<K1, T1, C1, A1>&,
761 const map<K1, T1, C1, A1>&);
762 template <class K1, class T1, class C1, class A1>
763 friend bool operator< (const map<K1, T1, C1, A1>&,
764 const map<K1, T1, C1, A1>&);
765 private:
766 mapped_type& priv_subscript(const key_type &k)
767 {
768 //we can optimize this
769 iterator i = lower_bound(k);
770 // i->first is greater than or equivalent to k.
771 if (i == end() || key_comp()(k, (*i).first)){
772 container_detail::value_init<mapped_type> m;
773 movable_value_type val(k, boost::move(m.m_t));
774 i = insert(i, boost::move(val));
775 }
776 return (*i).second;
777 }
778
779 mapped_type& priv_subscript(BOOST_RV_REF(key_type) mk)
780 {
781 key_type &k = mk;
782 //we can optimize this
783 iterator i = lower_bound(k);
784 // i->first is greater than or equivalent to k.
785 if (i == end() || key_comp()(k, (*i).first)){
786 container_detail::value_init<mapped_type> m;
787 movable_value_type val(boost::move(k), boost::move(m.m_t));
788 i = insert(i, boost::move(val));
789 }
790 return (*i).second;
791 }
792
793 /// @endcond
794 };
795
796 template <class Key, class T, class Compare, class Allocator>
797 inline bool operator==(const map<Key,T,Compare,Allocator>& x,
798 const map<Key,T,Compare,Allocator>& y)
799 { return x.m_tree == y.m_tree; }
800
801 template <class Key, class T, class Compare, class Allocator>
802 inline bool operator<(const map<Key,T,Compare,Allocator>& x,
803 const map<Key,T,Compare,Allocator>& y)
804 { return x.m_tree < y.m_tree; }
805
806 template <class Key, class T, class Compare, class Allocator>
807 inline bool operator!=(const map<Key,T,Compare,Allocator>& x,
808 const map<Key,T,Compare,Allocator>& y)
809 { return !(x == y); }
810
811 template <class Key, class T, class Compare, class Allocator>
812 inline bool operator>(const map<Key,T,Compare,Allocator>& x,
813 const map<Key,T,Compare,Allocator>& y)
814 { return y < x; }
815
816 template <class Key, class T, class Compare, class Allocator>
817 inline bool operator<=(const map<Key,T,Compare,Allocator>& x,
818 const map<Key,T,Compare,Allocator>& y)
819 { return !(y < x); }
820
821 template <class Key, class T, class Compare, class Allocator>
822 inline bool operator>=(const map<Key,T,Compare,Allocator>& x,
823 const map<Key,T,Compare,Allocator>& y)
824 { return !(x < y); }
825
826 template <class Key, class T, class Compare, class Allocator>
827 inline void swap(map<Key,T,Compare,Allocator>& x, map<Key,T,Compare,Allocator>& y)
828 { x.swap(y); }
829
830 /// @cond
831
832 // Forward declaration of operators < and ==, needed for friend declaration.
833
834 template <class Key, class T, class Compare, class Allocator>
835 inline bool operator==(const multimap<Key,T,Compare,Allocator>& x,
836 const multimap<Key,T,Compare,Allocator>& y);
837
838 template <class Key, class T, class Compare, class Allocator>
839 inline bool operator<(const multimap<Key,T,Compare,Allocator>& x,
840 const multimap<Key,T,Compare,Allocator>& y);
841
842 } //namespace container {
843
844 //!has_trivial_destructor_after_move<> == true_type
845 //!specialization for optimizations
846 template <class K, class T, class C, class Allocator>
847 struct has_trivial_destructor_after_move<boost::container::map<K, T, C, Allocator> >
848 {
849 static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
850 };
851
852 namespace container {
853
854 /// @endcond
855
856 //! A multimap is a kind of associative container that supports equivalent keys
857 //! (possibly containing multiple copies of the same key value) and provides for
858 //! fast retrieval of values of another type T based on the keys. The multimap class
859 //! supports bidirectional iterators.
860 //!
861 //! A multimap satisfies all of the requirements of a container and of a reversible
862 //! container and of an associative container. For a
863 //! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>.
864 //!
865 //! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
866 //!
867 //! Allocator is the allocator to allocate the value_types
868 //!(e.g. <i>allocator< std::pair<<b>const</b> Key, T> ></i>).
869 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
870 template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > >
871 #else
872 template <class Key, class T, class Compare, class Allocator>
873 #endif
874 class multimap
875 {
876 /// @cond
877 private:
878 BOOST_COPYABLE_AND_MOVABLE(multimap)
879
880 typedef std::pair<const Key, T> value_type_impl;
881 typedef container_detail::rbtree
882 <Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator> tree_t;
883 typedef container_detail::pair <Key, T> movable_value_type_impl;
884 typedef container_detail::tree_value_compare
885 < Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
886 > value_compare_impl;
887 tree_t m_tree; // red-black tree representing map
888 /// @endcond
889
890 public:
891 //////////////////////////////////////////////
892 //
893 // types
894 //
895 //////////////////////////////////////////////
896
897 typedef Key key_type;
898 typedef T mapped_type;
899 typedef std::pair<const Key, T> value_type;
900 typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
901 typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
902 typedef typename boost::container::allocator_traits<Allocator>::reference reference;
903 typedef typename boost::container::allocator_traits<Allocator>::const_reference const_reference;
904 typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
905 typedef typename boost::container::allocator_traits<Allocator>::difference_type difference_type;
906 typedef Allocator allocator_type;
907 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
908 typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare;
909 typedef Compare key_compare;
910 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::iterator) iterator;
911 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_iterator) const_iterator;
912 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::reverse_iterator) reverse_iterator;
913 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_reverse_iterator) const_reverse_iterator;
914 typedef std::pair<key_type, mapped_type> nonconst_value_type;
915 typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type;
916
917 //////////////////////////////////////////////
918 //
919 // construct/copy/destroy
920 //
921 //////////////////////////////////////////////
922
923 //! <b>Effects</b>: Default constructs an empty multimap.
924 //!
925 //! <b>Complexity</b>: Constant.
926 multimap()
927 : m_tree()
928 {
929 //Allocator type must be std::pair<CONST Key, T>
930 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
931 }
932
933 //! <b>Effects</b>: Constructs an empty multimap using the specified allocator.
934 //!
935 //! <b>Complexity</b>: Constant.
936 explicit multimap(const Compare& comp, const allocator_type& a = allocator_type())
937 : m_tree(comp, a)
938 {
939 //Allocator type must be std::pair<CONST Key, T>
940 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
941 }
942
943 //! <b>Effects</b>: Constructs an empty multimap using the specified comparison
944 //! object and allocator.
945 //!
946 //! <b>Complexity</b>: Constant.
947 explicit multimap(const allocator_type& a)
948 : m_tree(a)
949 {
950 //Allocator type must be std::pair<CONST Key, T>
951 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
952 }
953
954 //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object
955 //! and allocator, and inserts elements from the range [first ,last ).
956 //!
957 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
958 //! comp and otherwise N logN, where N is last - first.
959 template <class InputIterator>
960 multimap(InputIterator first, InputIterator last,
961 const Compare& comp = Compare(),
962 const allocator_type& a = allocator_type())
963 : m_tree(false, first, last, comp, a)
964 {
965 //Allocator type must be std::pair<CONST Key, T>
966 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
967 }
968
969 //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
970 //! allocator, and inserts elements from the ordered range [first ,last). This function
971 //! is more efficient than the normal range creation for ordered ranges.
972 //!
973 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
974 //!
975 //! <b>Complexity</b>: Linear in N.
976 //!
977 //! <b>Note</b>: Non-standard extension.
978 template <class InputIterator>
979 multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(),
980 const allocator_type& a = allocator_type())
981 : m_tree(ordered_range, first, last, comp, a)
982 {}
983
984 //! <b>Effects</b>: Copy constructs a multimap.
985 //!
986 //! <b>Complexity</b>: Linear in x.size().
987 multimap(const multimap& x)
988 : m_tree(x.m_tree)
989 {
990 //Allocator type must be std::pair<CONST Key, T>
991 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
992 }
993
994 //! <b>Effects</b>: Move constructs a multimap. Constructs *this using x's resources.
995 //!
996 //! <b>Complexity</b>: Constant.
997 //!
998 //! <b>Postcondition</b>: x is emptied.
999 multimap(BOOST_RV_REF(multimap) x)
1000 : m_tree(boost::move(x.m_tree))
1001 {
1002 //Allocator type must be std::pair<CONST Key, T>
1003 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
1004 }
1005
1006 //! <b>Effects</b>: Copy constructs a multimap.
1007 //!
1008 //! <b>Complexity</b>: Linear in x.size().
1009 multimap(const multimap& x, const allocator_type &a)
1010 : m_tree(x.m_tree, a)
1011 {
1012 //Allocator type must be std::pair<CONST Key, T>
1013 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
1014 }
1015
1016 //! <b>Effects</b>: Move constructs a multimap using the specified allocator.
1017 //! Constructs *this using x's resources.
1018 //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
1019 //!
1020 //! <b>Postcondition</b>: x is emptied.
1021 multimap(BOOST_RV_REF(multimap) x, const allocator_type &a)
1022 : m_tree(boost::move(x.m_tree), a)
1023 {
1024 //Allocator type must be std::pair<CONST Key, T>
1025 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
1026 }
1027
1028 //! <b>Effects</b>: Makes *this a copy of x.
1029 //!
1030 //! <b>Complexity</b>: Linear in x.size().
1031 multimap& operator=(BOOST_COPY_ASSIGN_REF(multimap) x)
1032 { m_tree = x.m_tree; return *this; }
1033
1034 //! <b>Effects</b>: this->swap(x.get()).
1035 //!
1036 //! <b>Complexity</b>: Constant.
1037 multimap& operator=(BOOST_RV_REF(multimap) x)
1038 { m_tree = boost::move(x.m_tree); return *this; }
1039
1040 //! <b>Effects</b>: Returns a copy of the Allocator that
1041 //! was passed to the object's constructor.
1042 //!
1043 //! <b>Complexity</b>: Constant.
1044 allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
1045 { return m_tree.get_allocator(); }
1046
1047 //! <b>Effects</b>: Returns a reference to the internal allocator.
1048 //!
1049 //! <b>Throws</b>: Nothing
1050 //!
1051 //! <b>Complexity</b>: Constant.
1052 //!
1053 //! <b>Note</b>: Non-standard extension.
1054 stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
1055 { return m_tree.get_stored_allocator(); }
1056
1057 //! <b>Effects</b>: Returns a reference to the internal allocator.
1058 //!
1059 //! <b>Throws</b>: Nothing
1060 //!
1061 //! <b>Complexity</b>: Constant.
1062 //!
1063 //! <b>Note</b>: Non-standard extension.
1064 const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
1065 { return m_tree.get_stored_allocator(); }
1066
1067 //////////////////////////////////////////////
1068 //
1069 // iterators
1070 //
1071 //////////////////////////////////////////////
1072
1073 //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
1074 //!
1075 //! <b>Throws</b>: Nothing.
1076 //!
1077 //! <b>Complexity</b>: Constant.
1078 iterator begin() BOOST_CONTAINER_NOEXCEPT
1079 { return m_tree.begin(); }
1080
1081 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
1082 //!
1083 //! <b>Throws</b>: Nothing.
1084 //!
1085 //! <b>Complexity</b>: Constant.
1086 const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
1087 { return this->cbegin(); }
1088
1089 //! <b>Effects</b>: Returns an iterator to the end of the container.
1090 //!
1091 //! <b>Throws</b>: Nothing.
1092 //!
1093 //! <b>Complexity</b>: Constant.
1094 iterator end() BOOST_CONTAINER_NOEXCEPT
1095 { return m_tree.end(); }
1096
1097 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
1098 //!
1099 //! <b>Throws</b>: Nothing.
1100 //!
1101 //! <b>Complexity</b>: Constant.
1102 const_iterator end() const BOOST_CONTAINER_NOEXCEPT
1103 { return this->cend(); }
1104
1105 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
1106 //! of the reversed container.
1107 //!
1108 //! <b>Throws</b>: Nothing.
1109 //!
1110 //! <b>Complexity</b>: Constant.
1111 reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
1112 { return m_tree.rbegin(); }
1113
1114 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1115 //! of the reversed container.
1116 //!
1117 //! <b>Throws</b>: Nothing.
1118 //!
1119 //! <b>Complexity</b>: Constant.
1120 const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
1121 { return this->crbegin(); }
1122
1123 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
1124 //! of the reversed container.
1125 //!
1126 //! <b>Throws</b>: Nothing.
1127 //!
1128 //! <b>Complexity</b>: Constant.
1129 reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
1130 { return m_tree.rend(); }
1131
1132 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1133 //! of the reversed container.
1134 //!
1135 //! <b>Throws</b>: Nothing.
1136 //!
1137 //! <b>Complexity</b>: Constant.
1138 const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
1139 { return this->crend(); }
1140
1141 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
1142 //!
1143 //! <b>Throws</b>: Nothing.
1144 //!
1145 //! <b>Complexity</b>: Constant.
1146 const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
1147 { return m_tree.begin(); }
1148
1149 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
1150 //!
1151 //! <b>Throws</b>: Nothing.
1152 //!
1153 //! <b>Complexity</b>: Constant.
1154 const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
1155 { return m_tree.end(); }
1156
1157 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1158 //! of the reversed container.
1159 //!
1160 //! <b>Throws</b>: Nothing.
1161 //!
1162 //! <b>Complexity</b>: Constant.
1163 const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
1164 { return m_tree.rbegin(); }
1165
1166 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1167 //! of the reversed container.
1168 //!
1169 //! <b>Throws</b>: Nothing.
1170 //!
1171 //! <b>Complexity</b>: Constant.
1172 const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
1173 { return m_tree.rend(); }
1174
1175 //////////////////////////////////////////////
1176 //
1177 // capacity
1178 //
1179 //////////////////////////////////////////////
1180
1181 //! <b>Effects</b>: Returns true if the container contains no elements.
1182 //!
1183 //! <b>Throws</b>: Nothing.
1184 //!
1185 //! <b>Complexity</b>: Constant.
1186 bool empty() const BOOST_CONTAINER_NOEXCEPT
1187 { return m_tree.empty(); }
1188
1189 //! <b>Effects</b>: Returns the number of the elements contained in the container.
1190 //!
1191 //! <b>Throws</b>: Nothing.
1192 //!
1193 //! <b>Complexity</b>: Constant.
1194 size_type size() const BOOST_CONTAINER_NOEXCEPT
1195 { return m_tree.size(); }
1196
1197 //! <b>Effects</b>: Returns the largest possible size of the container.
1198 //!
1199 //! <b>Throws</b>: Nothing.
1200 //!
1201 //! <b>Complexity</b>: Constant.
1202 size_type max_size() const BOOST_CONTAINER_NOEXCEPT
1203 { return m_tree.max_size(); }
1204
1205 //////////////////////////////////////////////
1206 //
1207 // modifiers
1208 //
1209 //////////////////////////////////////////////
1210
1211 #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1212
1213 //! <b>Effects</b>: Inserts an object of type T constructed with
1214 //! std::forward<Args>(args)... in the container.
1215 //! p is a hint pointing to where the insert should start to search.
1216 //!
1217 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1218 //! to the key of x.
1219 //!
1220 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1221 //! is inserted right before p.
1222 template <class... Args>
1223 iterator emplace(Args&&... args)
1224 { return m_tree.emplace_equal(boost::forward<Args>(args)...); }
1225
1226 //! <b>Effects</b>: Inserts an object of type T constructed with
1227 //! std::forward<Args>(args)... in the container.
1228 //! p is a hint pointing to where the insert should start to search.
1229 //!
1230 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1231 //! to the key of x.
1232 //!
1233 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1234 //! is inserted right before p.
1235 template <class... Args>
1236 iterator emplace_hint(const_iterator hint, Args&&... args)
1237 { return m_tree.emplace_hint_equal(hint, boost::forward<Args>(args)...); }
1238
1239 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
1240
1241 #define BOOST_PP_LOCAL_MACRO(n) \
1242 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
1243 iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
1244 { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
1245 \
1246 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
1247 iterator emplace_hint(const_iterator hint \
1248 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
1249 { return m_tree.emplace_hint_equal(hint \
1250 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
1251 //!
1252 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
1253 #include BOOST_PP_LOCAL_ITERATE()
1254
1255 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
1256
1257 //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
1258 //! newly inserted element.
1259 //!
1260 //! <b>Complexity</b>: Logarithmic.
1261 iterator insert(const value_type& x)
1262 { return m_tree.insert_equal(x); }
1263
1264 //! <b>Effects</b>: Inserts a new value constructed from x and returns
1265 //! the iterator pointing to the newly inserted element.
1266 //!
1267 //! <b>Complexity</b>: Logarithmic.
1268 iterator insert(const nonconst_value_type& x)
1269 { return m_tree.insert_equal(x); }
1270
1271 //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
1272 //! the iterator pointing to the newly inserted element.
1273 //!
1274 //! <b>Complexity</b>: Logarithmic.
1275 iterator insert(BOOST_RV_REF(nonconst_value_type) x)
1276 { return m_tree.insert_equal(boost::move(x)); }
1277
1278 //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
1279 //! the iterator pointing to the newly inserted element.
1280 //!
1281 //! <b>Complexity</b>: Logarithmic.
1282 iterator insert(BOOST_RV_REF(movable_value_type) x)
1283 { return m_tree.insert_equal(boost::move(x)); }
1284
1285 //! <b>Effects</b>: Inserts a copy of x in the container.
1286 //! p is a hint pointing to where the insert should start to search.
1287 //!
1288 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1289 //! to the key of x.
1290 //!
1291 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1292 //! is inserted right before p.
1293 iterator insert(const_iterator position, const value_type& x)
1294 { return m_tree.insert_equal(position, x); }
1295
1296 //! <b>Effects</b>: Inserts a new value constructed from x in the container.
1297 //! p is a hint pointing to where the insert should start to search.
1298 //!
1299 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1300 //! to the key of x.
1301 //!
1302 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1303 //! is inserted right before p.
1304 iterator insert(const_iterator position, const nonconst_value_type& x)
1305 { return m_tree.insert_equal(position, x); }
1306
1307 //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
1308 //! p is a hint pointing to where the insert should start to search.
1309 //!
1310 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1311 //! to the key of x.
1312 //!
1313 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1314 //! is inserted right before p.
1315 iterator insert(const_iterator position, BOOST_RV_REF(nonconst_value_type) x)
1316 { return m_tree.insert_equal(position, boost::move(x)); }
1317
1318 //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
1319 //! p is a hint pointing to where the insert should start to search.
1320 //!
1321 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1322 //! to the key of x.
1323 //!
1324 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
1325 //! is inserted right before p.
1326 iterator insert(const_iterator position, BOOST_RV_REF(movable_value_type) x)
1327 { return m_tree.insert_equal(position, boost::move(x)); }
1328
1329 //! <b>Requires</b>: first, last are not iterators into *this.
1330 //!
1331 //! <b>Effects</b>: inserts each element from the range [first,last) .
1332 //!
1333 //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
1334 template <class InputIterator>
1335 void insert(InputIterator first, InputIterator last)
1336 { m_tree.insert_equal(first, last); }
1337
1338 //! <b>Effects</b>: Erases the element pointed to by position.
1339 //!
1340 //! <b>Returns</b>: Returns an iterator pointing to the element immediately
1341 //! following q prior to the element being erased. If no such element exists,
1342 //! returns end().
1343 //!
1344 //! <b>Complexity</b>: Amortized constant time
1345 iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT
1346 { return m_tree.erase(position); }
1347
1348 //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
1349 //!
1350 //! <b>Returns</b>: Returns the number of erased elements.
1351 //!
1352 //! <b>Complexity</b>: log(size()) + count(k)
1353 size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT
1354 { return m_tree.erase(x); }
1355
1356 //! <b>Effects</b>: Erases all the elements in the range [first, last).
1357 //!
1358 //! <b>Returns</b>: Returns last.
1359 //!
1360 //! <b>Complexity</b>: log(size())+N where N is the distance from first to last.
1361 iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
1362 { return m_tree.erase(first, last); }
1363
1364 //! <b>Effects</b>: Swaps the contents of *this and x.
1365 //!
1366 //! <b>Throws</b>: Nothing.
1367 //!
1368 //! <b>Complexity</b>: Constant.
1369 void swap(multimap& x)
1370 { m_tree.swap(x.m_tree); }
1371
1372 //! <b>Effects</b>: erase(a.begin(),a.end()).
1373 //!
1374 //! <b>Postcondition</b>: size() == 0.
1375 //!
1376 //! <b>Complexity</b>: linear in size().
1377 void clear() BOOST_CONTAINER_NOEXCEPT
1378 { m_tree.clear(); }
1379
1380 //////////////////////////////////////////////
1381 //
1382 // observers
1383 //
1384 //////////////////////////////////////////////
1385
1386 //! <b>Effects</b>: Returns the comparison object out
1387 //! of which a was constructed.
1388 //!
1389 //! <b>Complexity</b>: Constant.
1390 key_compare key_comp() const
1391 { return m_tree.key_comp(); }
1392
1393 //! <b>Effects</b>: Returns an object of value_compare constructed out
1394 //! of the comparison object.
1395 //!
1396 //! <b>Complexity</b>: Constant.
1397 value_compare value_comp() const
1398 { return value_compare(m_tree.key_comp()); }
1399
1400 //////////////////////////////////////////////
1401 //
1402 // map operations
1403 //
1404 //////////////////////////////////////////////
1405
1406 //! <b>Returns</b>: An iterator pointing to an element with the key
1407 //! equivalent to x, or end() if such an element is not found.
1408 //!
1409 //! <b>Complexity</b>: Logarithmic.
1410 iterator find(const key_type& x)
1411 { return m_tree.find(x); }
1412
1413 //! <b>Returns</b>: Allocator const iterator pointing to an element with the key
1414 //! equivalent to x, or end() if such an element is not found.
1415 //!
1416 //! <b>Complexity</b>: Logarithmic.
1417 const_iterator find(const key_type& x) const
1418 { return m_tree.find(x); }
1419
1420 //! <b>Returns</b>: The number of elements with key equivalent to x.
1421 //!
1422 //! <b>Complexity</b>: log(size())+count(k)
1423 size_type count(const key_type& x) const
1424 { return m_tree.count(x); }
1425
1426 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1427 //! than k, or a.end() if such an element is not found.
1428 //!
1429 //! <b>Complexity</b>: Logarithmic
1430 iterator lower_bound(const key_type& x)
1431 {return m_tree.lower_bound(x); }
1432
1433 //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not
1434 //! less than k, or a.end() if such an element is not found.
1435 //!
1436 //! <b>Complexity</b>: Logarithmic
1437 const_iterator lower_bound(const key_type& x) const
1438 { return m_tree.lower_bound(x); }
1439
1440 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1441 //! than x, or end() if such an element is not found.
1442 //!
1443 //! <b>Complexity</b>: Logarithmic
1444 iterator upper_bound(const key_type& x)
1445 { return m_tree.upper_bound(x); }
1446
1447 //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not
1448 //! less than x, or end() if such an element is not found.
1449 //!
1450 //! <b>Complexity</b>: Logarithmic
1451 const_iterator upper_bound(const key_type& x) const
1452 { return m_tree.upper_bound(x); }
1453
1454 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1455 //!
1456 //! <b>Complexity</b>: Logarithmic
1457 std::pair<iterator,iterator> equal_range(const key_type& x)
1458 { return m_tree.equal_range(x); }
1459
1460 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1461 //!
1462 //! <b>Complexity</b>: Logarithmic
1463 std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
1464 { return m_tree.equal_range(x); }
1465
1466 /// @cond
1467 template <class K1, class T1, class C1, class A1>
1468 friend bool operator== (const multimap<K1, T1, C1, A1>& x,
1469 const multimap<K1, T1, C1, A1>& y);
1470
1471 template <class K1, class T1, class C1, class A1>
1472 friend bool operator< (const multimap<K1, T1, C1, A1>& x,
1473 const multimap<K1, T1, C1, A1>& y);
1474 /// @endcond
1475 };
1476
1477 template <class Key, class T, class Compare, class Allocator>
1478 inline bool operator==(const multimap<Key,T,Compare,Allocator>& x,
1479 const multimap<Key,T,Compare,Allocator>& y)
1480 { return x.m_tree == y.m_tree; }
1481
1482 template <class Key, class T, class Compare, class Allocator>
1483 inline bool operator<(const multimap<Key,T,Compare,Allocator>& x,
1484 const multimap<Key,T,Compare,Allocator>& y)
1485 { return x.m_tree < y.m_tree; }
1486
1487 template <class Key, class T, class Compare, class Allocator>
1488 inline bool operator!=(const multimap<Key,T,Compare,Allocator>& x,
1489 const multimap<Key,T,Compare,Allocator>& y)
1490 { return !(x == y); }
1491
1492 template <class Key, class T, class Compare, class Allocator>
1493 inline bool operator>(const multimap<Key,T,Compare,Allocator>& x,
1494 const multimap<Key,T,Compare,Allocator>& y)
1495 { return y < x; }
1496
1497 template <class Key, class T, class Compare, class Allocator>
1498 inline bool operator<=(const multimap<Key,T,Compare,Allocator>& x,
1499 const multimap<Key,T,Compare,Allocator>& y)
1500 { return !(y < x); }
1501
1502 template <class Key, class T, class Compare, class Allocator>
1503 inline bool operator>=(const multimap<Key,T,Compare,Allocator>& x,
1504 const multimap<Key,T,Compare,Allocator>& y)
1505 { return !(x < y); }
1506
1507 template <class Key, class T, class Compare, class Allocator>
1508 inline void swap(multimap<Key,T,Compare,Allocator>& x, multimap<Key,T,Compare,Allocator>& y)
1509 { x.swap(y); }
1510
1511 /// @cond
1512
1513 } //namespace container {
1514
1515 //!has_trivial_destructor_after_move<> == true_type
1516 //!specialization for optimizations
1517 template <class K, class T, class C, class Allocator>
1518 struct has_trivial_destructor_after_move<boost::container::multimap<K, T, C, Allocator> >
1519 {
1520 static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
1521 };
1522
1523 namespace container {
1524
1525 /// @endcond
1526
1527 }}
1528
1529 #include <boost/container/detail/config_end.hpp>
1530
1531 #endif /* BOOST_CONTAINER_MAP_HPP */
1532