fix doc example typo
[boost.git] / boost / interprocess / containers / container / flat_map.hpp
blobb3b9b793f22cdbafb08eac78cd57e8abfd7b4e6d
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 #ifndef BOOST_CONTAINERS_FLAT_MAP_HPP
12 #define BOOST_CONTAINERS_FLAT_MAP_HPP
14 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif
18 #include <boost/interprocess/containers/container/detail/config_begin.hpp>
19 #include <boost/interprocess/containers/container/detail/workaround.hpp>
21 #include <boost/interprocess/containers/container/containers_fwd.hpp>
22 #include <utility>
23 #include <functional>
24 #include <memory>
25 #include <stdexcept>
26 #include <boost/interprocess/containers/container/detail/flat_tree.hpp>
27 #include <boost/interprocess/containers/container/detail/utilities.hpp>
28 #include <boost/type_traits/has_trivial_destructor.hpp>
29 #include <boost/interprocess/containers/container/detail/mpl.hpp>
30 #include <boost/interprocess/detail/move.hpp>
32 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
33 namespace boost {
34 namespace interprocess {
35 #else
36 namespace boost {
37 namespace interprocess_container {
38 #endif
40 /// @cond
41 // Forward declarations of operators == and <, needed for friend declarations.
42 template <class Key, class T, class Pred, class Alloc>
43 class flat_map;
45 template <class Key, class T, class Pred, class Alloc>
46 inline bool operator==(const flat_map<Key,T,Pred,Alloc>& x,
47 const flat_map<Key,T,Pred,Alloc>& y);
49 template <class Key, class T, class Pred, class Alloc>
50 inline bool operator<(const flat_map<Key,T,Pred,Alloc>& x,
51 const flat_map<Key,T,Pred,Alloc>& y);
52 /// @endcond
54 //! A flat_map is a kind of associative container that supports unique keys (contains at
55 //! most one of each key value) and provides for fast retrieval of values of another
56 //! type T based on the keys. The flat_map class supports random-access iterators.
57 //!
58 //! A flat_map satisfies all of the requirements of a container and of a reversible
59 //! container and of an associative container. A flat_map also provides
60 //! most operations described for unique keys. For a
61 //! flat_map<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
62 //! (unlike std::map<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
63 //!
64 //! Pred is the ordering function for Keys (e.g. <i>std::less<Key></i>).
65 //!
66 //! Alloc is the allocator to allocate the value_types
67 //! (e.g. <i>allocator< std::pair<Key, T> ></i>).
68 //!
69 //! flat_map is similar to std::map but it's implemented like an ordered vector.
70 //! This means that inserting a new element into a flat_map invalidates
71 //! previous iterators and references
72 //!
73 //! Erasing an element of a flat_map invalidates iterators and references
74 //! pointing to elements that come after (their keys are bigger) the erased element.
75 template <class Key, class T, class Pred, class Alloc>
76 class flat_map
78 /// @cond
79 private:
80 //This is the tree that we should store if pair was movable
81 typedef containers_detail::flat_tree<Key,
82 std::pair<Key, T>,
83 containers_detail::select1st< std::pair<Key, T> >,
84 Pred,
85 Alloc> tree_t;
87 //This is the real tree stored here. It's based on a movable pair
88 typedef containers_detail::flat_tree<Key,
89 containers_detail::pair<Key, T>,
90 containers_detail::select1st<containers_detail::pair<Key, T> >,
91 Pred,
92 typename Alloc::template
93 rebind<containers_detail::pair<Key, T> >::other> impl_tree_t;
94 impl_tree_t m_flat_tree; // flat tree representing flat_map
96 typedef typename impl_tree_t::value_type impl_value_type;
97 typedef typename impl_tree_t::pointer impl_pointer;
98 typedef typename impl_tree_t::const_pointer impl_const_pointer;
99 typedef typename impl_tree_t::reference impl_reference;
100 typedef typename impl_tree_t::const_reference impl_const_reference;
101 typedef typename impl_tree_t::value_compare impl_value_compare;
102 typedef typename impl_tree_t::iterator impl_iterator;
103 typedef typename impl_tree_t::const_iterator impl_const_iterator;
104 typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator;
105 typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator;
106 typedef typename impl_tree_t::allocator_type impl_allocator_type;
108 template<class D, class S>
109 static D &force(const S &s)
110 { return *const_cast<D*>(reinterpret_cast<const D*>(&s)); }
112 template<class D, class S>
113 static D force_copy(S s)
115 value_type *vp = reinterpret_cast<value_type *>(&*s);
116 return D(vp);
119 /// @endcond
121 public:
122 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(flat_map)
124 // typedefs:
125 typedef typename tree_t::key_type key_type;
126 typedef typename tree_t::value_type value_type;
127 typedef typename tree_t::pointer pointer;
128 typedef typename tree_t::const_pointer const_pointer;
129 typedef typename tree_t::reference reference;
130 typedef typename tree_t::const_reference const_reference;
131 typedef typename tree_t::value_compare value_compare;
132 typedef T mapped_type;
133 typedef typename tree_t::key_compare key_compare;
134 typedef typename tree_t::iterator iterator;
135 typedef typename tree_t::const_iterator const_iterator;
136 typedef typename tree_t::reverse_iterator reverse_iterator;
137 typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
138 typedef typename tree_t::size_type size_type;
139 typedef typename tree_t::difference_type difference_type;
140 typedef typename tree_t::allocator_type allocator_type;
141 typedef typename tree_t::stored_allocator_type stored_allocator_type;
143 //! <b>Effects</b>: Constructs an empty flat_map using the specified
144 //! comparison object and allocator.
145 //!
146 //! <b>Complexity</b>: Constant.
147 explicit flat_map(const Pred& comp = Pred(), const allocator_type& a = allocator_type())
148 : m_flat_tree(comp, force<impl_allocator_type>(a)) {}
150 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
151 //! allocator, and inserts elements from the range [first ,last ).
152 //!
153 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
154 //! comp and otherwise N logN, where N is last - first.
155 template <class InputIterator>
156 flat_map(InputIterator first, InputIterator last, const Pred& comp = Pred(),
157 const allocator_type& a = allocator_type())
158 : m_flat_tree(comp, force<impl_allocator_type>(a))
159 { m_flat_tree.insert_unique(first, last); }
161 //! <b>Effects</b>: Copy constructs a flat_map.
162 //!
163 //! <b>Complexity</b>: Linear in x.size().
164 flat_map(const flat_map<Key,T,Pred,Alloc>& x)
165 : m_flat_tree(x.m_flat_tree) {}
167 //! <b>Effects</b>: Move constructs a flat_map.
168 //! Constructs *this using x's resources.
169 //!
170 //! <b>Complexity</b>: Construct.
171 //!
172 //! <b>Postcondition</b>: x is emptied.
173 flat_map(BOOST_INTERPROCESS_RV_REF(flat_map) x)
174 : m_flat_tree(boost::interprocess::move(x.m_flat_tree))
177 //! <b>Effects</b>: Makes *this a copy of x.
178 //!
179 //! <b>Complexity</b>: Linear in x.size().
180 flat_map<Key,T,Pred,Alloc>& operator=(const flat_map<Key, T, Pred, Alloc>& x)
181 { m_flat_tree = x.m_flat_tree; return *this; }
183 //! <b>Effects</b>: Move constructs a flat_map.
184 //! Constructs *this using x's resources.
185 //!
186 //! <b>Complexity</b>: Construct.
187 //!
188 //! <b>Postcondition</b>: x is emptied.
189 flat_map<Key,T,Pred,Alloc>& operator=(BOOST_INTERPROCESS_RV_REF(flat_map) mx)
190 { m_flat_tree = boost::interprocess::move(mx.m_flat_tree); return *this; }
192 //! <b>Effects</b>: Returns the comparison object out
193 //! of which a was constructed.
194 //!
195 //! <b>Complexity</b>: Constant.
196 key_compare key_comp() const
197 { return force<key_compare>(m_flat_tree.key_comp()); }
199 //! <b>Effects</b>: Returns an object of value_compare constructed out
200 //! of the comparison object.
201 //!
202 //! <b>Complexity</b>: Constant.
203 value_compare value_comp() const
204 { return value_compare(force<key_compare>(m_flat_tree.key_comp())); }
206 //! <b>Effects</b>: Returns a copy of the Allocator that
207 //! was passed to the object's constructor.
208 //!
209 //! <b>Complexity</b>: Constant.
210 allocator_type get_allocator() const
211 { return force<allocator_type>(m_flat_tree.get_allocator()); }
213 const stored_allocator_type &get_stored_allocator() const
214 { return force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
216 stored_allocator_type &get_stored_allocator()
217 { return force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
219 //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
220 //!
221 //! <b>Throws</b>: Nothing.
222 //!
223 //! <b>Complexity</b>: Constant.
224 iterator begin()
225 { return force_copy<iterator>(m_flat_tree.begin()); }
227 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
228 //!
229 //! <b>Throws</b>: Nothing.
230 //!
231 //! <b>Complexity</b>: Constant.
232 const_iterator begin() const
233 { return force<const_iterator>(m_flat_tree.begin()); }
235 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
236 //!
237 //! <b>Throws</b>: Nothing.
238 //!
239 //! <b>Complexity</b>: Constant.
240 const_iterator cbegin() const
241 { return force<const_iterator>(m_flat_tree.cbegin()); }
243 //! <b>Effects</b>: Returns an iterator to the end of the container.
244 //!
245 //! <b>Throws</b>: Nothing.
246 //!
247 //! <b>Complexity</b>: Constant.
248 iterator end()
249 { return force_copy<iterator>(m_flat_tree.end()); }
251 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
252 //!
253 //! <b>Throws</b>: Nothing.
254 //!
255 //! <b>Complexity</b>: Constant.
256 const_iterator end() const
257 { return force<const_iterator>(m_flat_tree.end()); }
259 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
260 //!
261 //! <b>Throws</b>: Nothing.
262 //!
263 //! <b>Complexity</b>: Constant.
264 const_iterator cend() const
265 { return force<const_iterator>(m_flat_tree.cend()); }
267 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
268 //! of the reversed container.
269 //!
270 //! <b>Throws</b>: Nothing.
271 //!
272 //! <b>Complexity</b>: Constant.
273 reverse_iterator rbegin()
274 { return force<reverse_iterator>(m_flat_tree.rbegin()); }
276 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
277 //! of the reversed container.
278 //!
279 //! <b>Throws</b>: Nothing.
280 //!
281 //! <b>Complexity</b>: Constant.
282 const_reverse_iterator rbegin() const
283 { return force<const_reverse_iterator>(m_flat_tree.rbegin()); }
285 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
286 //! of the reversed container.
287 //!
288 //! <b>Throws</b>: Nothing.
289 //!
290 //! <b>Complexity</b>: Constant.
291 const_reverse_iterator crbegin() const
292 { return force<const_reverse_iterator>(m_flat_tree.crbegin()); }
294 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
295 //! of the reversed container.
296 //!
297 //! <b>Throws</b>: Nothing.
298 //!
299 //! <b>Complexity</b>: Constant.
300 reverse_iterator rend()
301 { return force<reverse_iterator>(m_flat_tree.rend()); }
303 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
304 //! of the reversed container.
305 //!
306 //! <b>Throws</b>: Nothing.
307 //!
308 //! <b>Complexity</b>: Constant.
309 const_reverse_iterator rend() const
310 { return force<const_reverse_iterator>(m_flat_tree.rend()); }
312 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
313 //! of the reversed container.
314 //!
315 //! <b>Throws</b>: Nothing.
316 //!
317 //! <b>Complexity</b>: Constant.
318 const_reverse_iterator crend() const
319 { return force<const_reverse_iterator>(m_flat_tree.crend()); }
321 //! <b>Effects</b>: Returns true if the container contains no elements.
322 //!
323 //! <b>Throws</b>: Nothing.
324 //!
325 //! <b>Complexity</b>: Constant.
326 bool empty() const
327 { return m_flat_tree.empty(); }
329 //! <b>Effects</b>: Returns the number of the elements contained in the container.
330 //!
331 //! <b>Throws</b>: Nothing.
332 //!
333 //! <b>Complexity</b>: Constant.
334 size_type size() const
335 { return m_flat_tree.size(); }
337 //! <b>Effects</b>: Returns the largest possible size of the container.
338 //!
339 //! <b>Throws</b>: Nothing.
340 //!
341 //! <b>Complexity</b>: Constant.
342 size_type max_size() const
343 { return m_flat_tree.max_size(); }
345 //! Effects: If there is no key equivalent to x in the flat_map, inserts
346 //! value_type(x, T()) into the flat_map.
347 //!
348 //! Returns: A reference to the mapped_type corresponding to x in *this.
349 //!
350 //! Complexity: Logarithmic.
351 T &operator[](const key_type& k)
353 iterator i = lower_bound(k);
354 // i->first is greater than or equivalent to k.
355 if (i == end() || key_comp()(k, (*i).first))
356 i = insert(i, value_type(k, T()));
357 return (*i).second;
360 //! Effects: If there is no key equivalent to x in the flat_map, inserts
361 //! value_type(move(x), T()) into the flat_map (the key is move-constructed)
362 //!
363 //! Returns: A reference to the mapped_type corresponding to x in *this.
364 //!
365 //! Complexity: Logarithmic.
366 T &operator[](BOOST_INTERPROCESS_RV_REF(key_type) mk)
368 key_type &k = mk;
369 iterator i = lower_bound(k);
370 // i->first is greater than or equivalent to k.
371 if (i == end() || key_comp()(k, (*i).first))
372 i = insert(i, value_type(boost::interprocess::move(k), boost::interprocess::move(T())));
373 return (*i).second;
376 //! Returns: A reference to the element whose key is equivalent to x.
377 //! Throws: An exception object of type out_of_range if no such element is present.
378 //! Complexity: logarithmic.
379 T& at(const key_type& k)
381 iterator i = this->find(k);
382 if(i == this->end()){
383 throw std::out_of_range("key not found");
385 return i->second;
388 //! Returns: A reference to the element whose key is equivalent to x.
389 //! Throws: An exception object of type out_of_range if no such element is present.
390 //! Complexity: logarithmic.
391 const T& at(const key_type& k) const
393 const_iterator i = this->find(k);
394 if(i == this->end()){
395 throw std::out_of_range("key not found");
397 return i->second;
400 //! <b>Effects</b>: Swaps the contents of *this and x.
401 //! If this->allocator_type() != x.allocator_type() allocators are also swapped.
403 //! <b>Throws</b>: Nothing.
405 //! <b>Complexity</b>: Constant.
406 void swap(flat_map& x)
407 { m_flat_tree.swap(x.m_flat_tree); }
409 //! <b>Effects</b>: Inserts x if and only if there is no element in the container
410 //! with key equivalent to the key of x.
412 //! <b>Returns</b>: The bool component of the returned pair is true if and only
413 //! if the insertion takes place, and the iterator component of the pair
414 //! points to the element with key equivalent to the key of x.
416 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
417 //! to the elements with bigger keys than x.
419 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
420 std::pair<iterator,bool> insert(const value_type& x)
421 { return force<std::pair<iterator,bool> >(
422 m_flat_tree.insert_unique(force<impl_value_type>(x))); }
424 //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
425 //! only if there is no element in the container with key equivalent to the key of x.
427 //! <b>Returns</b>: The bool component of the returned pair is true if and only
428 //! if the insertion takes place, and the iterator component of the pair
429 //! points to the element with key equivalent to the key of x.
431 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
432 //! to the elements with bigger keys than x.
434 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
435 std::pair<iterator,bool> insert(BOOST_INTERPROCESS_RV_REF(value_type) x)
436 { return force<std::pair<iterator,bool> >(
437 m_flat_tree.insert_unique(boost::interprocess::move(force<impl_value_type>(x)))); }
439 //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
440 //! only if there is no element in the container with key equivalent to the key of x.
442 //! <b>Returns</b>: The bool component of the returned pair is true if and only
443 //! if the insertion takes place, and the iterator component of the pair
444 //! points to the element with key equivalent to the key of x.
446 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
447 //! to the elements with bigger keys than x.
449 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
450 std::pair<iterator,bool> insert(BOOST_INTERPROCESS_RV_REF(impl_value_type) x)
452 return force<std::pair<iterator,bool> >
453 (m_flat_tree.insert_unique(boost::interprocess::move(x)));
456 //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
457 //! no element in the container with key equivalent to the key of x.
458 //! p is a hint pointing to where the insert should start to search.
460 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
461 //! to the key of x.
463 //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
464 //! right before p) plus insertion linear to the elements with bigger keys than x.
466 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
467 iterator insert(const_iterator position, const value_type& x)
468 { return force_copy<iterator>(
469 m_flat_tree.insert_unique(force<impl_const_iterator>(position), force<impl_value_type>(x))); }
471 //! <b>Effects</b>: Inserts an element move constructed from x in the container.
472 //! p is a hint pointing to where the insert should start to search.
474 //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
476 //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
477 //! right before p) plus insertion linear to the elements with bigger keys than x.
479 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
480 iterator insert(const_iterator position, BOOST_INTERPROCESS_RV_REF(value_type) x)
481 { return force_copy<iterator>(
482 m_flat_tree.insert_unique(force<impl_const_iterator>(position), boost::interprocess::move(force<impl_value_type>(x)))); }
484 //! <b>Effects</b>: Inserts an element move constructed from x in the container.
485 //! p is a hint pointing to where the insert should start to search.
487 //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
489 //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
490 //! right before p) plus insertion linear to the elements with bigger keys than x.
492 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
493 iterator insert(const_iterator position, BOOST_INTERPROCESS_RV_REF(impl_value_type) x)
495 return force_copy<iterator>(
496 m_flat_tree.insert_unique(force<impl_const_iterator>(position), boost::interprocess::move(x)));
499 //! <b>Requires</b>: i, j are not iterators into *this.
501 //! <b>Effects</b>: inserts each element from the range [i,j) if and only
502 //! if there is no element with key equivalent to the key of that element.
504 //! <b>Complexity</b>: N log(size()+N) (N is the distance from i to j)
505 //! search time plus N*size() insertion time.
507 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
508 template <class InputIterator>
509 void insert(InputIterator first, InputIterator last)
510 { m_flat_tree.insert_unique(first, last); }
512 #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
514 //! <b>Effects</b>: Inserts an object of type T constructed with
515 //! std::forward<Args>(args)... if and only if there is no element in the container
516 //! with key equivalent to the key of x.
518 //! <b>Returns</b>: The bool component of the returned pair is true if and only
519 //! if the insertion takes place, and the iterator component of the pair
520 //! points to the element with key equivalent to the key of x.
522 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
523 //! to the elements with bigger keys than x.
525 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
526 template <class... Args>
527 iterator emplace(Args&&... args)
528 { return force_copy<iterator>(m_flat_tree.emplace_unique(boost::interprocess::forward<Args>(args)...)); }
530 //! <b>Effects</b>: Inserts an object of type T constructed with
531 //! std::forward<Args>(args)... in the container if and only if there is
532 //! no element in the container with key equivalent to the key of x.
533 //! p is a hint pointing to where the insert should start to search.
535 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
536 //! to the key of x.
538 //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
539 //! right before p) plus insertion linear to the elements with bigger keys than x.
541 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
542 template <class... Args>
543 iterator emplace_hint(const_iterator hint, Args&&... args)
544 { return force_copy<iterator>(m_flat_tree.emplace_hint_unique(force<impl_const_iterator>(hint), boost::interprocess::forward<Args>(args)...)); }
546 #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
548 iterator emplace()
549 { return force_copy<iterator>(m_flat_tree.emplace_unique()); }
551 iterator emplace_hint(const_iterator hint)
552 { return force_copy<iterator>(m_flat_tree.emplace_hint_unique(force<impl_const_iterator>(hint))); }
554 #define BOOST_PP_LOCAL_MACRO(n) \
555 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
556 iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
558 return force_copy<iterator>(m_flat_tree.emplace_unique \
559 (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
562 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
563 iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
565 return force_copy<iterator>(m_flat_tree.emplace_hint_unique \
566 (force<impl_const_iterator>(hint), \
567 BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
570 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
571 #include BOOST_PP_LOCAL_ITERATE()
573 #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
575 //! <b>Effects</b>: Erases the element pointed to by position.
577 //! <b>Returns</b>: Returns an iterator pointing to the element immediately
578 //! following q prior to the element being erased. If no such element exists,
579 //! returns end().
581 //! <b>Complexity</b>: Linear to the elements with keys bigger than position
583 //! <b>Note</b>: Invalidates elements with keys
584 //! not less than the erased element.
585 iterator erase(const_iterator position)
586 { return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(position))); }
588 //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
590 //! <b>Returns</b>: Returns the number of erased elements.
592 //! <b>Complexity</b>: Logarithmic search time plus erasure time
593 //! linear to the elements with bigger keys.
594 size_type erase(const key_type& x)
595 { return m_flat_tree.erase(x); }
597 //! <b>Effects</b>: Erases all the elements in the range [first, last).
599 //! <b>Returns</b>: Returns last.
601 //! <b>Complexity</b>: size()*N where N is the distance from first to last.
603 //! <b>Complexity</b>: Logarithmic search time plus erasure time
604 //! linear to the elements with bigger keys.
605 iterator erase(const_iterator first, const_iterator last)
606 { return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(first), force<impl_const_iterator>(last))); }
608 //! <b>Effects</b>: erase(a.begin(),a.end()).
610 //! <b>Postcondition</b>: size() == 0.
612 //! <b>Complexity</b>: linear in size().
613 void clear()
614 { m_flat_tree.clear(); }
616 //! <b>Effects</b>: Tries to deallocate the excess of memory created
617 // with previous allocations. The size of the vector is unchanged
619 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
621 //! <b>Complexity</b>: Linear to size().
622 void shrink_to_fit()
623 { m_flat_tree.shrink_to_fit(); }
625 //! <b>Returns</b>: An iterator pointing to an element with the key
626 //! equivalent to x, or end() if such an element is not found.
628 //! <b>Complexity</b>: Logarithmic.
629 iterator find(const key_type& x)
630 { return force_copy<iterator>(m_flat_tree.find(x)); }
632 //! <b>Returns</b>: A const_iterator pointing to an element with the key
633 //! equivalent to x, or end() if such an element is not found.
635 //! <b>Complexity</b>: Logarithmic.s
636 const_iterator find(const key_type& x) const
637 { return force<const_iterator>(m_flat_tree.find(x)); }
639 //! <b>Returns</b>: The number of elements with key equivalent to x.
641 //! <b>Complexity</b>: log(size())+count(k)
642 size_type count(const key_type& x) const
643 { return m_flat_tree.find(x) == m_flat_tree.end() ? 0 : 1; }
645 //! <b>Returns</b>: An iterator pointing to the first element with key not less
646 //! than k, or a.end() if such an element is not found.
648 //! <b>Complexity</b>: Logarithmic
649 iterator lower_bound(const key_type& x)
650 { return force_copy<iterator>(m_flat_tree.lower_bound(x)); }
652 //! <b>Returns</b>: A const iterator pointing to the first element with key not
653 //! less than k, or a.end() if such an element is not found.
655 //! <b>Complexity</b>: Logarithmic
656 const_iterator lower_bound(const key_type& x) const
657 { return force<const_iterator>(m_flat_tree.lower_bound(x)); }
659 //! <b>Returns</b>: An iterator pointing to the first element with key not less
660 //! than x, or end() if such an element is not found.
662 //! <b>Complexity</b>: Logarithmic
663 iterator upper_bound(const key_type& x)
664 { return force_copy<iterator>(m_flat_tree.upper_bound(x)); }
666 //! <b>Returns</b>: A const iterator pointing to the first element with key not
667 //! less than x, or end() if such an element is not found.
669 //! <b>Complexity</b>: Logarithmic
670 const_iterator upper_bound(const key_type& x) const
671 { return force<const_iterator>(m_flat_tree.upper_bound(x)); }
673 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
675 //! <b>Complexity</b>: Logarithmic
676 std::pair<iterator,iterator> equal_range(const key_type& x)
677 { return force<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
679 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
681 //! <b>Complexity</b>: Logarithmic
682 std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
683 { return force<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
685 //! <b>Effects</b>: Number of elements for which memory has been allocated.
686 //! capacity() is always greater than or equal to size().
687 //!
688 //! <b>Throws</b>: Nothing.
689 //!
690 //! <b>Complexity</b>: Constant.
691 size_type capacity() const
692 { return m_flat_tree.capacity(); }
694 //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
695 //! effect. Otherwise, it is a request for allocation of additional memory.
696 //! If the request is successful, then capacity() is greater than or equal to
697 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
698 //!
699 //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
701 //! <b>Note</b>: If capacity() is less than "count", iterators and references to
702 //! to values might be invalidated.
703 void reserve(size_type count)
704 { m_flat_tree.reserve(count); }
706 /// @cond
707 template <class K1, class T1, class C1, class A1>
708 friend bool operator== (const flat_map<K1, T1, C1, A1>&,
709 const flat_map<K1, T1, C1, A1>&);
710 template <class K1, class T1, class C1, class A1>
711 friend bool operator< (const flat_map<K1, T1, C1, A1>&,
712 const flat_map<K1, T1, C1, A1>&);
713 /// @endcond
716 template <class Key, class T, class Pred, class Alloc>
717 inline bool operator==(const flat_map<Key,T,Pred,Alloc>& x,
718 const flat_map<Key,T,Pred,Alloc>& y)
719 { return x.m_flat_tree == y.m_flat_tree; }
721 template <class Key, class T, class Pred, class Alloc>
722 inline bool operator<(const flat_map<Key,T,Pred,Alloc>& x,
723 const flat_map<Key,T,Pred,Alloc>& y)
724 { return x.m_flat_tree < y.m_flat_tree; }
726 template <class Key, class T, class Pred, class Alloc>
727 inline bool operator!=(const flat_map<Key,T,Pred,Alloc>& x,
728 const flat_map<Key,T,Pred,Alloc>& y)
729 { return !(x == y); }
731 template <class Key, class T, class Pred, class Alloc>
732 inline bool operator>(const flat_map<Key,T,Pred,Alloc>& x,
733 const flat_map<Key,T,Pred,Alloc>& y)
734 { return y < x; }
736 template <class Key, class T, class Pred, class Alloc>
737 inline bool operator<=(const flat_map<Key,T,Pred,Alloc>& x,
738 const flat_map<Key,T,Pred,Alloc>& y)
739 { return !(y < x); }
741 template <class Key, class T, class Pred, class Alloc>
742 inline bool operator>=(const flat_map<Key,T,Pred,Alloc>& x,
743 const flat_map<Key,T,Pred,Alloc>& y)
744 { return !(x < y); }
746 template <class Key, class T, class Pred, class Alloc>
747 inline void swap(flat_map<Key,T,Pred,Alloc>& x,
748 flat_map<Key,T,Pred,Alloc>& y)
749 { x.swap(y); }
751 /// @cond
753 } //namespace interprocess_container {
755 namespace interprocess {
757 //!has_trivial_destructor_after_move<> == true_type
758 //!specialization for optimizations
759 template <class K, class T, class C, class A>
760 struct has_trivial_destructor_after_move<boost::interprocess_container::flat_map<K, T, C, A> >
762 static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
765 } //namespace interprocess {
767 namespace interprocess_container {
769 // Forward declaration of operators < and ==, needed for friend declaration.
770 template <class Key, class T,
771 class Pred,
772 class Alloc>
773 class flat_multimap;
775 template <class Key, class T, class Pred, class Alloc>
776 inline bool operator==(const flat_multimap<Key,T,Pred,Alloc>& x,
777 const flat_multimap<Key,T,Pred,Alloc>& y);
779 template <class Key, class T, class Pred, class Alloc>
780 inline bool operator<(const flat_multimap<Key,T,Pred,Alloc>& x,
781 const flat_multimap<Key,T,Pred,Alloc>& y);
782 /// @endcond
784 //! A flat_multimap is a kind of associative container that supports equivalent keys
785 //! (possibly containing multiple copies of the same key value) and provides for
786 //! fast retrieval of values of another type T based on the keys. The flat_multimap
787 //! class supports random-access iterators.
788 //!
789 //! A flat_multimap satisfies all of the requirements of a container and of a reversible
790 //! container and of an associative container. For a
791 //! flat_multimap<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
792 //! (unlike std::multimap<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
794 //! Pred is the ordering function for Keys (e.g. <i>std::less<Key></i>).
796 //! Alloc is the allocator to allocate the value_types
797 //! (e.g. <i>allocator< std::pair<Key, T> ></i>).
798 template <class Key, class T, class Pred, class Alloc>
799 class flat_multimap
801 /// @cond
802 private:
803 typedef containers_detail::flat_tree<Key,
804 std::pair<Key, T>,
805 containers_detail::select1st< std::pair<Key, T> >,
806 Pred,
807 Alloc> tree_t;
808 //This is the real tree stored here. It's based on a movable pair
809 typedef containers_detail::flat_tree<Key,
810 containers_detail::pair<Key, T>,
811 containers_detail::select1st<containers_detail::pair<Key, T> >,
812 Pred,
813 typename Alloc::template
814 rebind<containers_detail::pair<Key, T> >::other> impl_tree_t;
815 impl_tree_t m_flat_tree; // flat tree representing flat_map
817 typedef typename impl_tree_t::value_type impl_value_type;
818 typedef typename impl_tree_t::pointer impl_pointer;
819 typedef typename impl_tree_t::const_pointer impl_const_pointer;
820 typedef typename impl_tree_t::reference impl_reference;
821 typedef typename impl_tree_t::const_reference impl_const_reference;
822 typedef typename impl_tree_t::value_compare impl_value_compare;
823 typedef typename impl_tree_t::iterator impl_iterator;
824 typedef typename impl_tree_t::const_iterator impl_const_iterator;
825 typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator;
826 typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator;
827 typedef typename impl_tree_t::allocator_type impl_allocator_type;
829 template<class D, class S>
830 static D &force(const S &s)
831 { return *const_cast<D*>((reinterpret_cast<const D*>(&s))); }
833 template<class D, class S>
834 static D force_copy(S s)
836 value_type *vp = reinterpret_cast<value_type *>(&*s);
837 return D(vp);
839 /// @endcond
841 public:
842 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(flat_multimap)
844 // typedefs:
845 typedef typename tree_t::key_type key_type;
846 typedef typename tree_t::value_type value_type;
847 typedef typename tree_t::pointer pointer;
848 typedef typename tree_t::const_pointer const_pointer;
849 typedef typename tree_t::reference reference;
850 typedef typename tree_t::const_reference const_reference;
851 typedef typename tree_t::value_compare value_compare;
852 typedef T mapped_type;
853 typedef typename tree_t::key_compare key_compare;
854 typedef typename tree_t::iterator iterator;
855 typedef typename tree_t::const_iterator const_iterator;
856 typedef typename tree_t::reverse_iterator reverse_iterator;
857 typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
858 typedef typename tree_t::size_type size_type;
859 typedef typename tree_t::difference_type difference_type;
860 typedef typename tree_t::allocator_type allocator_type;
861 typedef typename tree_t::stored_allocator_type stored_allocator_type;
863 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
864 //! object and allocator.
865 //!
866 //! <b>Complexity</b>: Constant.
867 explicit flat_multimap(const Pred& comp = Pred(),
868 const allocator_type& a = allocator_type())
869 : m_flat_tree(comp, force<impl_allocator_type>(a)) { }
871 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
872 //! and allocator, and inserts elements from the range [first ,last ).
873 //!
874 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
875 //! comp and otherwise N logN, where N is last - first.
876 template <class InputIterator>
877 flat_multimap(InputIterator first, InputIterator last,
878 const Pred& comp = Pred(),
879 const allocator_type& a = allocator_type())
880 : m_flat_tree(comp, force<impl_allocator_type>(a))
881 { m_flat_tree.insert_equal(first, last); }
883 //! <b>Effects</b>: Copy constructs a flat_multimap.
884 //!
885 //! <b>Complexity</b>: Linear in x.size().
886 flat_multimap(const flat_multimap<Key,T,Pred,Alloc>& x)
887 : m_flat_tree(x.m_flat_tree) { }
889 //! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources.
890 //!
891 //! <b>Complexity</b>: Construct.
892 //!
893 //! <b>Postcondition</b>: x is emptied.
894 flat_multimap(BOOST_INTERPROCESS_RV_REF(flat_multimap) x)
895 : m_flat_tree(boost::interprocess::move(x.m_flat_tree))
898 //! <b>Effects</b>: Makes *this a copy of x.
899 //!
900 //! <b>Complexity</b>: Linear in x.size().
901 flat_multimap<Key,T,Pred,Alloc>& operator=(const flat_multimap<Key,T,Pred,Alloc>& x)
902 { m_flat_tree = x.m_flat_tree; return *this; }
904 //! <b>Effects</b>: this->swap(x.get()).
905 //!
906 //! <b>Complexity</b>: Constant.
907 flat_multimap<Key,T,Pred,Alloc>& operator=(BOOST_INTERPROCESS_RV_REF(flat_multimap) mx)
908 { m_flat_tree = boost::interprocess::move(mx.m_flat_tree); return *this; }
910 //! <b>Effects</b>: Returns the comparison object out
911 //! of which a was constructed.
912 //!
913 //! <b>Complexity</b>: Constant.
914 key_compare key_comp() const
915 { return force<key_compare>(m_flat_tree.key_comp()); }
917 //! <b>Effects</b>: Returns an object of value_compare constructed out
918 //! of the comparison object.
919 //!
920 //! <b>Complexity</b>: Constant.
921 value_compare value_comp() const
922 { return value_compare(force<key_compare>(m_flat_tree.key_comp())); }
924 //! <b>Effects</b>: Returns a copy of the Allocator that
925 //! was passed to the object's constructor.
926 //!
927 //! <b>Complexity</b>: Constant.
928 allocator_type get_allocator() const
929 { return force<allocator_type>(m_flat_tree.get_allocator()); }
931 const stored_allocator_type &get_stored_allocator() const
932 { return force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
934 stored_allocator_type &get_stored_allocator()
935 { return force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
937 //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
938 //!
939 //! <b>Throws</b>: Nothing.
940 //!
941 //! <b>Complexity</b>: Constant.
942 iterator begin()
943 { return force_copy<iterator>(m_flat_tree.begin()); }
945 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
946 //!
947 //! <b>Throws</b>: Nothing.
948 //!
949 //! <b>Complexity</b>: Constant.
950 const_iterator begin() const
951 { return force<const_iterator>(m_flat_tree.begin()); }
953 //! <b>Effects</b>: Returns an iterator to the end of the container.
954 //!
955 //! <b>Throws</b>: Nothing.
956 //!
957 //! <b>Complexity</b>: Constant.
958 iterator end()
959 { return force_copy<iterator>(m_flat_tree.end()); }
961 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
962 //!
963 //! <b>Throws</b>: Nothing.
964 //!
965 //! <b>Complexity</b>: Constant.
966 const_iterator end() const
967 { return force<const_iterator>(m_flat_tree.end()); }
969 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
970 //! of the reversed container.
971 //!
972 //! <b>Throws</b>: Nothing.
973 //!
974 //! <b>Complexity</b>: Constant.
975 reverse_iterator rbegin()
976 { return force<reverse_iterator>(m_flat_tree.rbegin()); }
978 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
979 //! of the reversed container.
980 //!
981 //! <b>Throws</b>: Nothing.
982 //!
983 //! <b>Complexity</b>: Constant.
984 const_reverse_iterator rbegin() const
985 { return force<const_reverse_iterator>(m_flat_tree.rbegin()); }
987 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
988 //! of the reversed container.
989 //!
990 //! <b>Throws</b>: Nothing.
991 //!
992 //! <b>Complexity</b>: Constant.
993 reverse_iterator rend()
994 { return force<reverse_iterator>(m_flat_tree.rend()); }
996 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
997 //! of the reversed container.
998 //!
999 //! <b>Throws</b>: Nothing.
1000 //!
1001 //! <b>Complexity</b>: Constant.
1002 const_reverse_iterator rend() const
1003 { return force<const_reverse_iterator>(m_flat_tree.rend()); }
1005 //! <b>Effects</b>: Returns true if the container contains no elements.
1006 //!
1007 //! <b>Throws</b>: Nothing.
1008 //!
1009 //! <b>Complexity</b>: Constant.
1010 bool empty() const
1011 { return m_flat_tree.empty(); }
1013 //! <b>Effects</b>: Returns the number of the elements contained in the container.
1014 //!
1015 //! <b>Throws</b>: Nothing.
1016 //!
1017 //! <b>Complexity</b>: Constant.
1018 size_type size() const
1019 { return m_flat_tree.size(); }
1021 //! <b>Effects</b>: Returns the largest possible size of the container.
1022 //!
1023 //! <b>Throws</b>: Nothing.
1024 //!
1025 //! <b>Complexity</b>: Constant.
1026 size_type max_size() const
1027 { return m_flat_tree.max_size(); }
1029 //! <b>Effects</b>: Swaps the contents of *this and x.
1030 //! If this->allocator_type() != x.allocator_type() allocators are also swapped.
1032 //! <b>Throws</b>: Nothing.
1034 //! <b>Complexity</b>: Constant.
1035 void swap(flat_multimap& x)
1036 { m_flat_tree.swap(x.m_flat_tree); }
1038 //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
1039 //! newly inserted element.
1041 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1042 //! to the elements with bigger keys than x.
1044 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1045 iterator insert(const value_type& x)
1046 { return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_value_type>(x))); }
1048 //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
1049 //! the iterator pointing to the newly inserted element.
1051 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1052 //! to the elements with bigger keys than x.
1054 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1055 iterator insert(BOOST_INTERPROCESS_RV_REF(value_type) x)
1056 { return force_copy<iterator>(m_flat_tree.insert_equal(boost::interprocess::move(x))); }
1058 //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
1059 //! the iterator pointing to the newly inserted element.
1061 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1062 //! to the elements with bigger keys than x.
1064 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1065 iterator insert(BOOST_INTERPROCESS_RV_REF(impl_value_type) x)
1066 { return force_copy<iterator>(m_flat_tree.insert_equal(boost::interprocess::move(x))); }
1068 //! <b>Effects</b>: Inserts a copy of x in the container.
1069 //! p is a hint pointing to where the insert should start to search.
1071 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1072 //! to the key of x.
1074 //! <b>Complexity</b>: Logarithmic search time (constant time if the value
1075 //! is to be inserted before p) plus linear insertion
1076 //! to the elements with bigger keys than x.
1078 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1079 iterator insert(const_iterator position, const value_type& x)
1080 { return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_const_iterator>(position), force<impl_value_type>(x))); }
1082 //! <b>Effects</b>: Inserts a value move constructed from x in the container.
1083 //! p is a hint pointing to where the insert should start to search.
1085 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1086 //! to the key of x.
1088 //! <b>Complexity</b>: Logarithmic search time (constant time if the value
1089 //! is to be inserted before p) plus linear insertion
1090 //! to the elements with bigger keys than x.
1092 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1093 iterator insert(const_iterator position, BOOST_INTERPROCESS_RV_REF(value_type) x)
1095 return force_copy<iterator>
1096 (m_flat_tree.insert_equal(force<impl_const_iterator>(position)
1097 , boost::interprocess::move(x)));
1100 //! <b>Effects</b>: Inserts a value move constructed from x in the container.
1101 //! p is a hint pointing to where the insert should start to search.
1103 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1104 //! to the key of x.
1106 //! <b>Complexity</b>: Logarithmic search time (constant time if the value
1107 //! is to be inserted before p) plus linear insertion
1108 //! to the elements with bigger keys than x.
1110 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1111 iterator insert(const_iterator position, BOOST_INTERPROCESS_RV_REF(impl_value_type) x)
1113 return force_copy<iterator>(
1114 m_flat_tree.insert_equal(force<impl_const_iterator>(position), boost::interprocess::move(x)));
1117 //! <b>Requires</b>: i, j are not iterators into *this.
1119 //! <b>Effects</b>: inserts each element from the range [i,j) .
1121 //! <b>Complexity</b>: N log(size()+N) (N is the distance from i to j)
1122 //! search time plus N*size() insertion time.
1124 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1125 template <class InputIterator>
1126 void insert(InputIterator first, InputIterator last)
1127 { m_flat_tree.insert_equal(first, last); }
1129 #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
1131 //! <b>Effects</b>: Inserts an object of type T constructed with
1132 //! std::forward<Args>(args)... and returns the iterator pointing to the
1133 //! newly inserted element.
1135 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1136 //! to the elements with bigger keys than x.
1138 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1139 template <class... Args>
1140 iterator emplace(Args&&... args)
1141 { return force_copy<iterator>(m_flat_tree.emplace_equal(boost::interprocess::forward<Args>(args)...)); }
1143 //! <b>Effects</b>: Inserts an object of type T constructed with
1144 //! std::forward<Args>(args)... in the container.
1145 //! p is a hint pointing to where the insert should start to search.
1147 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1148 //! to the key of x.
1150 //! <b>Complexity</b>: Logarithmic search time (constant time if the value
1151 //! is to be inserted before p) plus linear insertion
1152 //! to the elements with bigger keys than x.
1154 //! <b>Note</b>: If an element it's inserted it might invalidate elements.
1155 template <class... Args>
1156 iterator emplace_hint(const_iterator hint, Args&&... args)
1158 return force_copy<iterator>(m_flat_tree.emplace_hint_equal
1159 (force<impl_const_iterator>(hint), boost::interprocess::forward<Args>(args)...));
1162 #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
1164 iterator emplace()
1165 { return force_copy<iterator>(m_flat_tree.emplace_equal()); }
1167 iterator emplace_hint(const_iterator hint)
1168 { return force_copy<iterator>(m_flat_tree.emplace_hint_equal(force<impl_const_iterator>(hint))); }
1170 #define BOOST_PP_LOCAL_MACRO(n) \
1171 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
1172 iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
1174 return force_copy<iterator>(m_flat_tree.emplace_equal \
1175 (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
1178 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
1179 iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
1181 return force_copy<iterator>(m_flat_tree.emplace_hint_equal \
1182 (force<impl_const_iterator>(hint), \
1183 BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
1186 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
1187 #include BOOST_PP_LOCAL_ITERATE()
1189 #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
1191 //! <b>Effects</b>: Erases the element pointed to by position.
1193 //! <b>Returns</b>: Returns an iterator pointing to the element immediately
1194 //! following q prior to the element being erased. If no such element exists,
1195 //! returns end().
1197 //! <b>Complexity</b>: Linear to the elements with keys bigger than position
1199 //! <b>Note</b>: Invalidates elements with keys
1200 //! not less than the erased element.
1201 iterator erase(const_iterator position)
1202 { return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(position))); }
1204 //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
1206 //! <b>Returns</b>: Returns the number of erased elements.
1208 //! <b>Complexity</b>: Logarithmic search time plus erasure time
1209 //! linear to the elements with bigger keys.
1210 size_type erase(const key_type& x)
1211 { return m_flat_tree.erase(x); }
1213 //! <b>Effects</b>: Erases all the elements in the range [first, last).
1215 //! <b>Returns</b>: Returns last.
1217 //! <b>Complexity</b>: size()*N where N is the distance from first to last.
1219 //! <b>Complexity</b>: Logarithmic search time plus erasure time
1220 //! linear to the elements with bigger keys.
1221 iterator erase(const_iterator first, const_iterator last)
1222 { return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(first), force<impl_const_iterator>(last))); }
1224 //! <b>Effects</b>: erase(a.begin(),a.end()).
1226 //! <b>Postcondition</b>: size() == 0.
1228 //! <b>Complexity</b>: linear in size().
1229 void clear()
1230 { m_flat_tree.clear(); }
1232 //! <b>Effects</b>: Tries to deallocate the excess of memory created
1233 // with previous allocations. The size of the vector is unchanged
1235 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
1237 //! <b>Complexity</b>: Linear to size().
1238 void shrink_to_fit()
1239 { m_flat_tree.shrink_to_fit(); }
1241 //! <b>Returns</b>: An iterator pointing to an element with the key
1242 //! equivalent to x, or end() if such an element is not found.
1244 //! <b>Complexity</b>: Logarithmic.
1245 iterator find(const key_type& x)
1246 { return force_copy<iterator>(m_flat_tree.find(x)); }
1248 //! <b>Returns</b>: An const_iterator pointing to an element with the key
1249 //! equivalent to x, or end() if such an element is not found.
1251 //! <b>Complexity</b>: Logarithmic.
1252 const_iterator find(const key_type& x) const
1253 { return force<const_iterator>(m_flat_tree.find(x)); }
1255 //! <b>Returns</b>: The number of elements with key equivalent to x.
1257 //! <b>Complexity</b>: log(size())+count(k)
1258 size_type count(const key_type& x) const
1259 { return m_flat_tree.count(x); }
1261 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1262 //! than k, or a.end() if such an element is not found.
1264 //! <b>Complexity</b>: Logarithmic
1265 iterator lower_bound(const key_type& x)
1266 {return force_copy<iterator>(m_flat_tree.lower_bound(x)); }
1268 //! <b>Returns</b>: A const iterator pointing to the first element with key
1269 //! not less than k, or a.end() if such an element is not found.
1271 //! <b>Complexity</b>: Logarithmic
1272 const_iterator lower_bound(const key_type& x) const
1273 { return force<const_iterator>(m_flat_tree.lower_bound(x)); }
1275 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1276 //! than x, or end() if such an element is not found.
1278 //! <b>Complexity</b>: Logarithmic
1279 iterator upper_bound(const key_type& x)
1280 {return force_copy<iterator>(m_flat_tree.upper_bound(x)); }
1282 //! <b>Returns</b>: A const iterator pointing to the first element with key
1283 //! not less than x, or end() if such an element is not found.
1285 //! <b>Complexity</b>: Logarithmic
1286 const_iterator upper_bound(const key_type& x) const
1287 { return force<const_iterator>(m_flat_tree.upper_bound(x)); }
1289 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1291 //! <b>Complexity</b>: Logarithmic
1292 std::pair<iterator,iterator> equal_range(const key_type& x)
1293 { return force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
1295 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1297 //! <b>Complexity</b>: Logarithmic
1298 std::pair<const_iterator,const_iterator>
1299 equal_range(const key_type& x) const
1300 { return force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
1302 //! <b>Effects</b>: Number of elements for which memory has been allocated.
1303 //! capacity() is always greater than or equal to size().
1304 //!
1305 //! <b>Throws</b>: Nothing.
1306 //!
1307 //! <b>Complexity</b>: Constant.
1308 size_type capacity() const
1309 { return m_flat_tree.capacity(); }
1311 //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
1312 //! effect. Otherwise, it is a request for allocation of additional memory.
1313 //! If the request is successful, then capacity() is greater than or equal to
1314 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
1315 //!
1316 //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
1318 //! <b>Note</b>: If capacity() is less than "count", iterators and references to
1319 //! to values might be invalidated.
1320 void reserve(size_type count)
1321 { m_flat_tree.reserve(count); }
1323 /// @cond
1324 template <class K1, class T1, class C1, class A1>
1325 friend bool operator== (const flat_multimap<K1, T1, C1, A1>& x,
1326 const flat_multimap<K1, T1, C1, A1>& y);
1328 template <class K1, class T1, class C1, class A1>
1329 friend bool operator< (const flat_multimap<K1, T1, C1, A1>& x,
1330 const flat_multimap<K1, T1, C1, A1>& y);
1331 /// @endcond
1334 template <class Key, class T, class Pred, class Alloc>
1335 inline bool operator==(const flat_multimap<Key,T,Pred,Alloc>& x,
1336 const flat_multimap<Key,T,Pred,Alloc>& y)
1337 { return x.m_flat_tree == y.m_flat_tree; }
1339 template <class Key, class T, class Pred, class Alloc>
1340 inline bool operator<(const flat_multimap<Key,T,Pred,Alloc>& x,
1341 const flat_multimap<Key,T,Pred,Alloc>& y)
1342 { return x.m_flat_tree < y.m_flat_tree; }
1344 template <class Key, class T, class Pred, class Alloc>
1345 inline bool operator!=(const flat_multimap<Key,T,Pred,Alloc>& x,
1346 const flat_multimap<Key,T,Pred,Alloc>& y)
1347 { return !(x == y); }
1349 template <class Key, class T, class Pred, class Alloc>
1350 inline bool operator>(const flat_multimap<Key,T,Pred,Alloc>& x,
1351 const flat_multimap<Key,T,Pred,Alloc>& y)
1352 { return y < x; }
1354 template <class Key, class T, class Pred, class Alloc>
1355 inline bool operator<=(const flat_multimap<Key,T,Pred,Alloc>& x,
1356 const flat_multimap<Key,T,Pred,Alloc>& y)
1357 { return !(y < x); }
1359 template <class Key, class T, class Pred, class Alloc>
1360 inline bool operator>=(const flat_multimap<Key,T,Pred,Alloc>& x,
1361 const flat_multimap<Key,T,Pred,Alloc>& y)
1362 { return !(x < y); }
1364 template <class Key, class T, class Pred, class Alloc>
1365 inline void swap(flat_multimap<Key,T,Pred,Alloc>& x, flat_multimap<Key,T,Pred,Alloc>& y)
1366 { x.swap(y); }
1370 /// @cond
1372 namespace boost {
1373 namespace interprocess {
1375 //!has_trivial_destructor_after_move<> == true_type
1376 //!specialization for optimizations
1377 template <class K, class T, class C, class A>
1378 struct has_trivial_destructor_after_move< boost::interprocess_container::flat_multimap<K, T, C, A> >
1380 static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
1383 } //namespace interprocess {
1384 } //namespace boost {
1386 /// @endcond
1388 #include <boost/interprocess/containers/container/detail/config_end.hpp>
1390 #endif /* BOOST_CONTAINERS_FLAT_MAP_HPP */