blob: 967994662895c74b21148f9f27b925e9ee39c00b [file] [log] [blame]
Brian Silvermanfad8f552018-08-04 23:36:19 -07001//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2005-2013. 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#ifndef BOOST_CONTAINER_FLAT_MAP_HPP
11#define BOOST_CONTAINER_FLAT_MAP_HPP
12
13#ifndef BOOST_CONFIG_HPP
14# include <boost/config.hpp>
15#endif
16
17#if defined(BOOST_HAS_PRAGMA_ONCE)
18# pragma once
19#endif
20
21#include <boost/container/detail/config_begin.hpp>
22#include <boost/container/detail/workaround.hpp>
23// container
24#include <boost/container/allocator_traits.hpp>
25#include <boost/container/container_fwd.hpp>
26#include <boost/container/new_allocator.hpp> //new_allocator
27#include <boost/container/throw_exception.hpp>
28// container/detail
29#include <boost/container/detail/flat_tree.hpp>
30#include <boost/container/detail/type_traits.hpp>
31#include <boost/container/detail/mpl.hpp>
32#include <boost/container/detail/algorithm.hpp> //equal()
33#include <boost/container/detail/container_or_allocator_rebind.hpp>
34// move
35#include <boost/move/utility_core.hpp>
36#include <boost/move/traits.hpp>
37// move/detail
38#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
39#include <boost/move/detail/fwd_macros.hpp>
40#endif
41#include <boost/move/detail/move_helpers.hpp>
42// intrusive
43#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
44#include <boost/intrusive/detail/minimal_less_equal_header.hpp>//less, equal
45//others
46#include <boost/core/no_exceptions_support.hpp>
47
48#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
49#include <initializer_list>
50#endif
51
52namespace boost {
53namespace container {
54
55#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
56
57template <class Key, class T, class Compare, class AllocatorOrContainer>
58class flat_multimap;
59
60namespace dtl{
61
62template<class D, class S>
63BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
64{ return *reinterpret_cast<D*>(&s); }
65
66template<class D, class S>
67BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
68{
69 const D *const vp = reinterpret_cast<const D *>(&s);
70 D ret_val(*vp);
71 return ret_val;
72}
73
74} //namespace dtl{
75
76#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
77
78//! A flat_map is a kind of associative container that supports unique keys (contains at
79//! most one of each key value) and provides for fast retrieval of values of another
80//! type T based on the keys.
81//!
82//! A flat_map satisfies all of the requirements of a container, a reversible
83//! container and an associative container. A flat_map also provides
84//! most operations described for unique keys. For a
85//! flat_map<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
86//! (unlike std::map<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
87//!
88//! flat_map is similar to std::map but it's implemented by as an ordered sequence container.
89//! The underlying sequence container is by default <i>vector</i> but it can also work
90//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
91//!
92//! Using vector-like sequence containers means that inserting a new element into a flat_map might invalidate
93//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
94//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
95//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
96//!
97//! This container provides random-access iterators.
98//!
99//! \tparam Key is the key_type of the map
100//! \tparam Value is the <code>mapped_type</code>
101//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
102//! \tparam AllocatorOrContainer is either:
103//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
104//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
105//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
106//! sequence container with random-access iterators..
107#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
108template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
109#else
110template <class Key, class T, class Compare, class AllocatorOrContainer>
111#endif
112class flat_map
113{
114 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
115 private:
116 BOOST_COPYABLE_AND_MOVABLE(flat_map)
117 //This is the tree that we should store if pair was movable
118 typedef dtl::flat_tree<
119 std::pair<Key, T>,
120 dtl::select1st<Key>,
121 Compare,
122 AllocatorOrContainer> tree_t;
123
124 //This is the real tree stored here. It's based on a movable pair
125 typedef dtl::flat_tree<
126 dtl::pair<Key, T>,
127 dtl::select1st<Key>,
128 Compare,
129 typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
130 > impl_tree_t;
131 impl_tree_t m_flat_tree; // flat tree representing flat_map
132
133 typedef typename impl_tree_t::value_type impl_value_type;
134 typedef typename impl_tree_t::const_iterator impl_const_iterator;
135 typedef typename impl_tree_t::iterator impl_iterator;
136 typedef typename impl_tree_t::allocator_type impl_allocator_type;
137 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
138 typedef std::initializer_list<impl_value_type> impl_initializer_list;
139 #endif
140
141 typedef dtl::flat_tree_value_compare
142 < Compare
143 , dtl::select1st<Key>
144 , std::pair<Key, T> > value_compare_t;
145 typedef typename tree_t::iterator iterator_t;
146 typedef typename tree_t::const_iterator const_iterator_t;
147 typedef typename tree_t::reverse_iterator reverse_iterator_t;
148 typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
149
150 public:
151 typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
152 typedef typename impl_tree_t::sequence_type impl_sequence_type;
153
154 BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
155 { return m_flat_tree; }
156
157 BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const
158 { return m_flat_tree; }
159
160 private:
161 typedef typename tree_t::get_stored_allocator_const_return_t get_stored_allocator_const_return_t;
162 typedef typename tree_t::get_stored_allocator_noconst_return_t get_stored_allocator_noconst_return_t;
163 typedef typename impl_tree_t::get_stored_allocator_const_return_t impl_get_stored_allocator_const_return_t;
164 typedef typename impl_tree_t::get_stored_allocator_noconst_return_t impl_get_stored_allocator_noconst_return_t;
165
166 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
167
168 public:
169
170 //////////////////////////////////////////////
171 //
172 // types
173 //
174 //////////////////////////////////////////////
175 typedef Key key_type;
176 typedef T mapped_type;
177 typedef Compare key_compare;
178 typedef std::pair<Key, T> value_type;
179 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
180 typedef typename sequence_type::allocator_type allocator_type;
181 typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
182 typedef typename sequence_type::pointer pointer;
183 typedef typename sequence_type::const_pointer const_pointer;
184 typedef typename sequence_type::reference reference;
185 typedef typename sequence_type::const_reference const_reference;
186 typedef typename sequence_type::size_type size_type;
187 typedef typename sequence_type::difference_type difference_type;
188 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
189 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
190
191 typedef typename sequence_type::iterator iterator;
192 typedef typename sequence_type::const_iterator const_iterator;
193 typedef typename sequence_type::reverse_iterator reverse_iterator;
194 typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
195 typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
196
197 //AllocatorOrContainer::value_type must be std::pair<Key, T>
198 BOOST_STATIC_ASSERT((dtl::is_same<std::pair<Key, T>, typename allocator_type::value_type>::value));
199
200 //////////////////////////////////////////////
201 //
202 // construct/copy/destroy
203 //
204 //////////////////////////////////////////////
205
206 //! <b>Effects</b>: Default constructs an empty flat_map.
207 //!
208 //! <b>Complexity</b>: Constant.
209 BOOST_CONTAINER_FORCEINLINE flat_map() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
210 dtl::is_nothrow_default_constructible<Compare>::value)
211 : m_flat_tree()
212 {}
213
214 //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
215 //!
216 //! <b>Complexity</b>: Constant.
217 BOOST_CONTAINER_FORCEINLINE explicit flat_map(const allocator_type& a)
218 : m_flat_tree(dtl::force<const impl_allocator_type>(a))
219 {}
220
221 //! <b>Effects</b>: Constructs an empty flat_map using the specified
222 //! comparison object.
223 //!
224 //! <b>Complexity</b>: Constant.
225 BOOST_CONTAINER_FORCEINLINE explicit flat_map(const Compare& comp)
226 : m_flat_tree(comp)
227 {}
228
229 //! <b>Effects</b>: Constructs an empty flat_map using the specified
230 //! comparison object and allocator.
231 //!
232 //! <b>Complexity</b>: Constant.
233 BOOST_CONTAINER_FORCEINLINE flat_map(const Compare& comp, const allocator_type& a)
234 : m_flat_tree(comp, dtl::force<const impl_allocator_type>(a))
235 {}
236
237 //! <b>Effects</b>: Constructs an empty flat_map and
238 //! and inserts elements from the range [first ,last ).
239 //!
240 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
241 //! the predicate and otherwise N logN, where N is last - first.
242 template <class InputIterator>
243 BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last)
244 : m_flat_tree(true, first, last)
245 {}
246
247 //! <b>Effects</b>: Constructs an empty flat_map using the specified
248 //! allocator, and inserts elements from the range [first ,last ).
249 //!
250 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
251 //! the predicate and otherwise N logN, where N is last - first.
252 template <class InputIterator>
253 BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const allocator_type& a)
254 : m_flat_tree(true, first, last, dtl::force<const impl_allocator_type>(a))
255 {}
256
257 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
258 //! and inserts elements from the range [first ,last ).
259 //!
260 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
261 //! the predicate and otherwise N logN, where N is last - first.
262 template <class InputIterator>
263 BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp)
264 : m_flat_tree(true, first, last, comp)
265 {}
266
267 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
268 //! allocator, and inserts elements from the range [first ,last ).
269 //!
270 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
271 //! the predicate and otherwise N logN, where N is last - first.
272 template <class InputIterator>
273 BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
274 : m_flat_tree(true, first, last, comp, dtl::force<const impl_allocator_type>(a))
275 {}
276
277 //! <b>Effects</b>: Constructs an empty flat_map
278 //! and inserts elements from the ordered range [first ,last). This function
279 //! is more efficient than the normal range creation for ordered ranges.
280 //!
281 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
282 //!
283 //! <b>Complexity</b>: Linear in N.
284 //!
285 //! <b>Note</b>: Non-standard extension.
286 template <class InputIterator>
287 BOOST_CONTAINER_FORCEINLINE
288 flat_map(ordered_unique_range_t, InputIterator first, InputIterator last)
289 : m_flat_tree(ordered_range, first, last)
290 {}
291
292 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
293 //! inserts elements from the ordered range [first ,last). This function
294 //! is more efficient than the normal range creation for ordered ranges.
295 //!
296 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
297 //!
298 //! <b>Complexity</b>: Linear in N.
299 //!
300 //! <b>Note</b>: Non-standard extension.
301 template <class InputIterator>
302 BOOST_CONTAINER_FORCEINLINE
303 flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
304 : m_flat_tree(ordered_range, first, last, comp)
305 {}
306
307 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
308 //! allocator, and inserts elements from the ordered range [first ,last). This function
309 //! is more efficient than the normal range creation for ordered ranges.
310 //!
311 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
312 //!
313 //! <b>Complexity</b>: Linear in N.
314 //!
315 //! <b>Note</b>: Non-standard extension.
316 template <class InputIterator>
317 BOOST_CONTAINER_FORCEINLINE
318 flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
319 : m_flat_tree(ordered_range, first, last, comp, dtl::force<const impl_allocator_type>(a))
320 {}
321
322#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
323 //! <b>Effects</b>: Constructs an empty flat_map and
324 //! inserts elements from the range [il.begin() ,il.end()).
325 //!
326 //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
327 //! the predicate and otherwise N logN, where N is last - first.
328 BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il)
329 : m_flat_tree( true
330 , dtl::force<impl_initializer_list>(il).begin()
331 , dtl::force<impl_initializer_list>(il).end())
332 {}
333
334 //! <b>Effects</b>: Constructs an empty flat_map using the specified
335 //! allocator, and inserts elements from the range [il.begin() ,il.end()).
336 //!
337 //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
338 //! the predicate and otherwise N logN, where N is last - first.
339 BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const allocator_type& a)
340 : m_flat_tree( true
341 , dtl::force<impl_initializer_list>(il).begin()
342 , dtl::force<impl_initializer_list>(il).end()
343 , dtl::force<const impl_allocator_type>(a))
344 {}
345
346 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
347 //! inserts elements from the range [il.begin() ,il.end()).
348 //!
349 //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
350 //! the predicate and otherwise N logN, where N is last - first.
351 BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp)
352 : m_flat_tree(true
353 , dtl::force<impl_initializer_list>(il).begin()
354 , dtl::force<impl_initializer_list>(il).end()
355 , comp)
356 {}
357
358 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
359 //! allocator, and inserts elements from the range [il.begin() ,il.end()).
360 //!
361 //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
362 //! the predicate and otherwise N logN, where N is last - first.
363 BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
364 : m_flat_tree(true
365 , dtl::force<impl_initializer_list>(il).begin()
366 , dtl::force<impl_initializer_list>(il).end()
367 , comp
368 , dtl::force<const impl_allocator_type>(a))
369 {}
370
371 //! <b>Effects</b>: Constructs an empty flat_map using and
372 //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
373 //! is more efficient than the normal range creation for ordered ranges.
374 //!
375 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
376 //! unique values.
377 //!
378 //! <b>Complexity</b>: Linear in N.
379 //!
380 //! <b>Note</b>: Non-standard extension.
381 BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il)
382 : m_flat_tree(ordered_unique_range
383 , dtl::force<impl_initializer_list>(il).begin()
384 , dtl::force<impl_initializer_list>(il).end())
385 {}
386
387 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
388 //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
389 //! is more efficient than the normal range creation for ordered ranges.
390 //!
391 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
392 //! unique values.
393 //!
394 //! <b>Complexity</b>: Linear in N.
395 //!
396 //! <b>Note</b>: Non-standard extension.
397 BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
398 : m_flat_tree(ordered_unique_range
399 , dtl::force<impl_initializer_list>(il).begin()
400 , dtl::force<impl_initializer_list>(il).end()
401 , comp)
402 {}
403
404 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
405 //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
406 //! is more efficient than the normal range creation for ordered ranges.
407 //!
408 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
409 //! unique values.
410 //!
411 //! <b>Complexity</b>: Linear in N.
412 //!
413 //! <b>Note</b>: Non-standard extension.
414 BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
415 : m_flat_tree( ordered_unique_range
416 , dtl::force<impl_initializer_list>(il).begin()
417 , dtl::force<impl_initializer_list>(il).end()
418 , comp
419 , dtl::force<const impl_allocator_type>(a))
420 {}
421#endif
422
423 //! <b>Effects</b>: Copy constructs a flat_map.
424 //!
425 //! <b>Complexity</b>: Linear in x.size().
426 BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x)
427 : m_flat_tree(x.m_flat_tree)
428 {}
429
430 //! <b>Effects</b>: Move constructs a flat_map.
431 //! Constructs *this using x's resources.
432 //!
433 //! <b>Complexity</b>: Constant.
434 //!
435 //! <b>Postcondition</b>: x is emptied.
436 BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x)
437 BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
438 : m_flat_tree(boost::move(x.m_flat_tree))
439 {}
440
441 //! <b>Effects</b>: Copy constructs a flat_map using the specified allocator.
442 //!
443 //! <b>Complexity</b>: Linear in x.size().
444 BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x, const allocator_type &a)
445 : m_flat_tree(x.m_flat_tree, dtl::force<const impl_allocator_type>(a))
446 {}
447
448 //! <b>Effects</b>: Move constructs a flat_map using the specified allocator.
449 //! Constructs *this using x's resources.
450 //!
451 //! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise.
452 BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
453 : m_flat_tree(boost::move(x.m_flat_tree), dtl::force<const impl_allocator_type>(a))
454 {}
455
456 //! <b>Effects</b>: Makes *this a copy of x.
457 //!
458 //! <b>Complexity</b>: Linear in x.size().
459 BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x)
460 { m_flat_tree = x.m_flat_tree; return *this; }
461
462 //! <b>Effects</b>: Move constructs a flat_map.
463 //! Constructs *this using x's resources.
464 //!
465 //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
466 //! is false and (allocation throws or value_type's move constructor throws)
467 //!
468 //! <b>Complexity</b>: Constant if allocator_traits_type::
469 //! propagate_on_container_move_assignment is true or
470 //! this->get>allocator() == x.get_allocator(). Linear otherwise.
471 BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_RV_REF(flat_map) x)
472 BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
473 allocator_traits_type::is_always_equal::value) &&
474 boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
475 { m_flat_tree = boost::move(x.m_flat_tree); return *this; }
476
477#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
478 //! <b>Effects</b>: Assign elements from il to *this
479 flat_map& operator=(std::initializer_list<value_type> il)
480 {
481 this->clear();
482 this->insert(il.begin(), il.end());
483 return *this;
484 }
485#endif
486
487 //! <b>Effects</b>: Returns a copy of the allocator that
488 //! was passed to the object's constructor.
489 //!
490 //! <b>Complexity</b>: Constant.
491 BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
492 { return dtl::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
493
494 //! <b>Effects</b>: Returns a reference to the internal allocator.
495 //!
496 //! <b>Throws</b>: Nothing
497 //!
498 //! <b>Complexity</b>: Constant.
499 //!
500 //! <b>Note</b>: Non-standard extension.
501 BOOST_CONTAINER_FORCEINLINE get_stored_allocator_noconst_return_t get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
502 {
503 impl_get_stored_allocator_noconst_return_t r = m_flat_tree.get_stored_allocator();
504 return dtl::force<stored_allocator_type>(r);
505 }
506
507 //! <b>Effects</b>: Returns a reference to the internal allocator.
508 //!
509 //! <b>Throws</b>: Nothing
510 //!
511 //! <b>Complexity</b>: Constant.
512 //!
513 //! <b>Note</b>: Non-standard extension.
514 BOOST_CONTAINER_FORCEINLINE get_stored_allocator_const_return_t get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
515 {
516 impl_get_stored_allocator_const_return_t r = m_flat_tree.get_stored_allocator();
517 return dtl::force<const stored_allocator_type>(r);
518 }
519
520 //////////////////////////////////////////////
521 //
522 // iterators
523 //
524 //////////////////////////////////////////////
525
526 //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
527 //!
528 //! <b>Throws</b>: Nothing.
529 //!
530 //! <b>Complexity</b>: Constant.
531 BOOST_CONTAINER_FORCEINLINE iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
532 { return dtl::force_copy<iterator>(m_flat_tree.begin()); }
533
534 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
535 //!
536 //! <b>Throws</b>: Nothing.
537 //!
538 //! <b>Complexity</b>: Constant.
539 BOOST_CONTAINER_FORCEINLINE const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
540 { return dtl::force_copy<const_iterator>(m_flat_tree.begin()); }
541
542 //! <b>Effects</b>: Returns an iterator to the end of the container.
543 //!
544 //! <b>Throws</b>: Nothing.
545 //!
546 //! <b>Complexity</b>: Constant.
547 BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
548 { return dtl::force_copy<iterator>(m_flat_tree.end()); }
549
550 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
551 //!
552 //! <b>Throws</b>: Nothing.
553 //!
554 //! <b>Complexity</b>: Constant.
555 BOOST_CONTAINER_FORCEINLINE const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
556 { return dtl::force_copy<const_iterator>(m_flat_tree.end()); }
557
558 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
559 //! of the reversed container.
560 //!
561 //! <b>Throws</b>: Nothing.
562 //!
563 //! <b>Complexity</b>: Constant.
564 BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
565 { return dtl::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
566
567 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
568 //! of the reversed container.
569 //!
570 //! <b>Throws</b>: Nothing.
571 //!
572 //! <b>Complexity</b>: Constant.
573 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
574 { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
575
576 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
577 //! of the reversed container.
578 //!
579 //! <b>Throws</b>: Nothing.
580 //!
581 //! <b>Complexity</b>: Constant.
582 BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
583 { return dtl::force_copy<reverse_iterator>(m_flat_tree.rend()); }
584
585 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
586 //! of the reversed container.
587 //!
588 //! <b>Throws</b>: Nothing.
589 //!
590 //! <b>Complexity</b>: Constant.
591 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
592 { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
593
594 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
595 //!
596 //! <b>Throws</b>: Nothing.
597 //!
598 //! <b>Complexity</b>: Constant.
599 BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
600 { return dtl::force_copy<const_iterator>(m_flat_tree.cbegin()); }
601
602 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
603 //!
604 //! <b>Throws</b>: Nothing.
605 //!
606 //! <b>Complexity</b>: Constant.
607 BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
608 { return dtl::force_copy<const_iterator>(m_flat_tree.cend()); }
609
610 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
611 //! of the reversed container.
612 //!
613 //! <b>Throws</b>: Nothing.
614 //!
615 //! <b>Complexity</b>: Constant.
616 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
617 { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
618
619 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
620 //! of the reversed container.
621 //!
622 //! <b>Throws</b>: Nothing.
623 //!
624 //! <b>Complexity</b>: Constant.
625 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
626 { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
627
628 //////////////////////////////////////////////
629 //
630 // capacity
631 //
632 //////////////////////////////////////////////
633
634 //! <b>Effects</b>: Returns true if the container contains no elements.
635 //!
636 //! <b>Throws</b>: Nothing.
637 //!
638 //! <b>Complexity</b>: Constant.
639 BOOST_CONTAINER_FORCEINLINE bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
640 { return m_flat_tree.empty(); }
641
642 //! <b>Effects</b>: Returns the number of the elements contained in the container.
643 //!
644 //! <b>Throws</b>: Nothing.
645 //!
646 //! <b>Complexity</b>: Constant.
647 BOOST_CONTAINER_FORCEINLINE size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
648 { return m_flat_tree.size(); }
649
650 //! <b>Effects</b>: Returns the largest possible size of the container.
651 //!
652 //! <b>Throws</b>: Nothing.
653 //!
654 //! <b>Complexity</b>: Constant.
655 BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
656 { return m_flat_tree.max_size(); }
657
658 //! <b>Effects</b>: Number of elements for which memory has been allocated.
659 //! capacity() is always greater than or equal to size().
660 //!
661 //! <b>Throws</b>: Nothing.
662 //!
663 //! <b>Complexity</b>: Constant.
664 BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
665 { return m_flat_tree.capacity(); }
666
667 //! <b>Effects</b>: If n is less than or equal to capacity(), or the
668 //! underlying container has no `reserve` member, this call has no
669 //! effect. Otherwise, it is a request for allocation of additional memory.
670 //! If the request is successful, then capacity() is greater than or equal to
671 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
672 //!
673 //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
674 //!
675 //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
676 //! to values might be invalidated.
677 BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
678 { m_flat_tree.reserve(cnt); }
679
680 //! <b>Effects</b>: Tries to deallocate the excess of memory created
681 // with previous allocations. The size of the vector is unchanged
682 //!
683 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
684 //!
685 //! <b>Complexity</b>: Linear to size().
686 BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
687 { m_flat_tree.shrink_to_fit(); }
688
689 //////////////////////////////////////////////
690 //
691 // element access
692 //
693 //////////////////////////////////////////////
694
695 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
696 //! Effects: If there is no key equivalent to x in the flat_map, inserts
697 //! value_type(x, T()) into the flat_map.
698 //!
699 //! Returns: A reference to the mapped_type corresponding to x in *this.
700 //!
701 //! Complexity: Logarithmic.
702 mapped_type &operator[](const key_type& k);
703
704 //! Effects: If there is no key equivalent to x in the flat_map, inserts
705 //! value_type(move(x), T()) into the flat_map (the key is move-constructed)
706 //!
707 //! Returns: A reference to the mapped_type corresponding to x in *this.
708 //!
709 //! Complexity: Logarithmic.
710 mapped_type &operator[](key_type &&k) ;
711 #elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
712 //in compilers like GCC 3.4, we can't catch temporaries
713 BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
714 BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
715 #else
716 BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
717 #endif
718
719 //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
720 //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
721 //! as if by insert, constructing it from value_type(k, forward<M>(obj)).
722 //!
723 //! No iterators or references are invalidated. If the insertion is successful, pointers and references
724 //! to the element obtained while it is held in the node handle are invalidated, and pointers and
725 //! references obtained to that element before it was extracted become valid.
726 //!
727 //! Returns: The bool component is true if the insertion took place and false if the assignment
728 //! took place. The iterator component is pointing at the element that was inserted or updated.
729 //!
730 //! Complexity: Logarithmic in the size of the container.
731 template <class M>
732 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
733 {
734 return dtl::force_copy< std::pair<iterator, bool> >
735 (this->m_flat_tree.insert_or_assign
736 ( impl_const_iterator(), k, ::boost::forward<M>(obj))
737 );
738 }
739
740 //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
741 //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
742 //! as if by insert, constructing it from value_type(k, move(obj)).
743 //!
744 //! No iterators or references are invalidated. If the insertion is successful, pointers and references
745 //! to the element obtained while it is held in the node handle are invalidated, and pointers and
746 //! references obtained to that element before it was extracted become valid.
747 //!
748 //! Returns: The bool component is true if the insertion took place and false if the assignment
749 //! took place. The iterator component is pointing at the element that was inserted or updated.
750 //!
751 //! Complexity: Logarithmic in the size of the container.
752 template <class M>
753 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
754 {
755 return dtl::force_copy< std::pair<iterator, bool> >
756 (this->m_flat_tree.insert_or_assign
757 ( impl_const_iterator(), ::boost::move(k), ::boost::forward<M>(obj))
758 );
759 }
760
761 //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
762 //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
763 //! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
764 //! to the container as close as possible to the position just before hint.
765 //!
766 //! No iterators or references are invalidated. If the insertion is successful, pointers and references
767 //! to the element obtained while it is held in the node handle are invalidated, and pointers and
768 //! references obtained to that element before it was extracted become valid.
769 //!
770 //! Returns: The bool component is true if the insertion took place and false if the assignment
771 //! took place. The iterator component is pointing at the element that was inserted or updated.
772 //!
773 //! Complexity: Logarithmic in the size of the container in general, but amortized constant if
774 //! the new element is inserted just before hint.
775 template <class M>
776 BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
777 {
778 return dtl::force_copy< std::pair<iterator, bool> >
779 (this->m_flat_tree.insert_or_assign
780 ( dtl::force_copy<impl_const_iterator>(hint)
781 , k, ::boost::forward<M>(obj))
782 );
783 }
784
785 //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
786 //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
787 //! as if by insert, constructing it from value_type(k, move(obj)) and the new element
788 //! to the container as close as possible to the position just before hint.
789 //!
790 //! No iterators or references are invalidated. If the insertion is successful, pointers and references
791 //! to the element obtained while it is held in the node handle are invalidated, and pointers and
792 //! references obtained to that element before it was extracted become valid.
793 //!
794 //! Returns: The bool component is true if the insertion took place and false if the assignment
795 //! took place. The iterator component is pointing at the element that was inserted or updated.
796 //!
797 //! Complexity: Logarithmic in the size of the container in general, but amortized constant if
798 //! the new element is inserted just before hint.
799 template <class M>
800 BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
801 {
802 return dtl::force_copy< std::pair<iterator, bool> >
803 (this->m_flat_tree.insert_or_assign
804 ( dtl::force_copy<impl_const_iterator>(hint)
805 , ::boost::move(k), ::boost::forward<M>(obj))
806 );
807 }
808
809 //! @copydoc ::boost::container::flat_set::nth(size_type)
810 BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
811 { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
812
813 //! @copydoc ::boost::container::flat_set::nth(size_type) const
814 BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
815 { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
816
817 //! @copydoc ::boost::container::flat_set::index_of(iterator)
818 BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
819 { return m_flat_tree.index_of(dtl::force_copy<impl_iterator>(p)); }
820
821 //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
822 BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
823 { return m_flat_tree.index_of(dtl::force_copy<impl_const_iterator>(p)); }
824
825 //! Returns: A reference to the element whose key is equivalent to x.
826 //!
827 //! Throws: An exception object of type out_of_range if no such element is present.
828 //!
829 //! Complexity: logarithmic.
830 T& at(const key_type& k)
831 {
832 iterator i = this->find(k);
833 if(i == this->end()){
834 throw_out_of_range("flat_map::at key not found");
835 }
836 return i->second;
837 }
838
839 //! Returns: A reference to the element whose key is equivalent to x.
840 //!
841 //! Throws: An exception object of type out_of_range if no such element is present.
842 //!
843 //! Complexity: logarithmic.
844 const T& at(const key_type& k) const
845 {
846 const_iterator i = this->find(k);
847 if(i == this->end()){
848 throw_out_of_range("flat_map::at key not found");
849 }
850 return i->second;
851 }
852
853 //////////////////////////////////////////////
854 //
855 // modifiers
856 //
857 //////////////////////////////////////////////
858
859 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
860
861 //! <b>Effects</b>: Inserts an object x of type T constructed with
862 //! std::forward<Args>(args)... if and only if there is no element in the container
863 //! with key equivalent to the key of x.
864 //!
865 //! <b>Returns</b>: The bool component of the returned pair is true if and only
866 //! if the insertion takes place, and the iterator component of the pair
867 //! points to the element with key equivalent to the key of x.
868 //!
869 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
870 //! to the elements with bigger keys than x.
871 //!
872 //! <b>Note</b>: If an element is inserted it might invalidate elements.
873 template <class... Args>
874 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
875 { return dtl::force_copy< std::pair<iterator, bool> >(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); }
876
877 //! <b>Effects</b>: Inserts an object of type T constructed with
878 //! std::forward<Args>(args)... in the container if and only if there is
879 //! no element in the container with key equivalent to the key of x.
880 //! p is a hint pointing to where the insert should start to search.
881 //!
882 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
883 //! to the key of x.
884 //!
885 //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
886 //! right before p) plus insertion linear to the elements with bigger keys than x.
887 //!
888 //! <b>Note</b>: If an element is inserted it might invalidate elements.
889 template <class... Args>
890 BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
891 {
892 return dtl::force_copy<iterator>
893 (m_flat_tree.emplace_hint_unique( dtl::force_copy<impl_const_iterator>(hint)
894 , boost::forward<Args>(args)...));
895 }
896
897 //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
898 //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
899 //!
900 //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
901 //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
902 //! forward_as_tuple(forward<Args>(args)...).
903 //!
904 //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
905 //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
906 //!
907 //! <b>Complexity</b>: Logarithmic.
908 template <class... Args>
909 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
910 {
911 return dtl::force_copy< std::pair<iterator, bool> >(
912 m_flat_tree.try_emplace(impl_const_iterator(), k, boost::forward<Args>(args)...));
913 }
914
915 //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
916 //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
917 //!
918 //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
919 //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
920 //! forward_as_tuple(forward<Args>(args)...).
921 //!
922 //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
923 //!
924 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
925 //! is inserted right before p.
926 template <class... Args>
927 BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k, BOOST_FWD_REF(Args)... args)
928 {
929 return dtl::force_copy<iterator>(m_flat_tree.try_emplace
930 (dtl::force_copy<impl_const_iterator>(hint), k, boost::forward<Args>(args)...).first);
931 }
932
933 //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
934 //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
935 //!
936 //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
937 //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
938 //! forward_as_tuple(forward<Args>(args)...).
939 //!
940 //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
941 //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
942 //!
943 //! <b>Complexity</b>: Logarithmic.
944 template <class... Args>
945 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
946 {
947 return dtl::force_copy< std::pair<iterator, bool> >
948 (m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k), boost::forward<Args>(args)...));
949 }
950
951 //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
952 //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
953 //!
954 //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
955 //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
956 //! forward_as_tuple(forward<Args>(args)...).
957 //!
958 //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
959 //!
960 //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
961 //! is inserted right before p.
962 template <class... Args>
963 BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
964 {
965 return dtl::force_copy<iterator>
966 (m_flat_tree.try_emplace(dtl::force_copy
967 <impl_const_iterator>(hint), boost::move(k), boost::forward<Args>(args)...).first);
968 }
969
970 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
971
972 #define BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE(N) \
973 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
974 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
975 {\
976 return dtl::force_copy< std::pair<iterator, bool> >\
977 (m_flat_tree.emplace_unique(BOOST_MOVE_FWD##N));\
978 }\
979 \
980 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
981 BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
982 {\
983 return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_unique\
984 (dtl::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
985 }\
986 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
987 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
988 {\
989 return dtl::force_copy< std::pair<iterator, bool> >\
990 (m_flat_tree.try_emplace(impl_const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
991 }\
992 \
993 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
994 BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
995 { return dtl::force_copy<iterator>(m_flat_tree.try_emplace\
996 (dtl::force_copy<impl_const_iterator>(hint), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
997 \
998 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
999 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1000 {\
1001 return dtl::force_copy< std::pair<iterator, bool> >\
1002 (m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
1003 }\
1004 \
1005 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1006 BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1007 { return dtl::force_copy<iterator>(m_flat_tree.try_emplace\
1008 (dtl::force_copy<impl_const_iterator>(hint), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
1009 //
1010 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE)
1011 #undef BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE
1012
1013 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1014
1015 //! <b>Effects</b>: Inserts x if and only if there is no element in the container
1016 //! with key equivalent to the key of x.
1017 //!
1018 //! <b>Returns</b>: The bool component of the returned pair is true if and only
1019 //! if the insertion takes place, and the iterator component of the pair
1020 //! points to the element with key equivalent to the key of x.
1021 //!
1022 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1023 //! to the elements with bigger keys than x.
1024 //!
1025 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1026 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const value_type& x)
1027 { return dtl::force_copy<std::pair<iterator,bool> >(
1028 m_flat_tree.insert_unique(dtl::force<const impl_value_type>(x))); }
1029
1030 //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
1031 //! only if there is no element in the container with key equivalent to the key of x.
1032 //!
1033 //! <b>Returns</b>: The bool component of the returned pair is true if and only
1034 //! if the insertion takes place, and the iterator component of the pair
1035 //! points to the element with key equivalent to the key of x.
1036 //!
1037 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1038 //! to the elements with bigger keys than x.
1039 //!
1040 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1041 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
1042 { return dtl::force_copy<std::pair<iterator,bool> >(
1043 m_flat_tree.insert_unique(boost::move(dtl::force<impl_value_type>(x)))); }
1044
1045 //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
1046 //! only if there is no element in the container with key equivalent to the key of x.
1047 //!
1048 //! <b>Returns</b>: The bool component of the returned pair is true if and only
1049 //! if the insertion takes place, and the iterator component of the pair
1050 //! points to the element with key equivalent to the key of x.
1051 //!
1052 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1053 //! to the elements with bigger keys than x.
1054 //!
1055 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1056 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
1057 {
1058 return dtl::force_copy<std::pair<iterator,bool> >
1059 (m_flat_tree.insert_unique(boost::move(x)));
1060 }
1061
1062 //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
1063 //! no element in the container with key equivalent to the key of x.
1064 //! p is a hint pointing to where the insert should start to search.
1065 //!
1066 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1067 //! to the key of x.
1068 //!
1069 //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
1070 //! right before p) plus insertion linear to the elements with bigger keys than x.
1071 //!
1072 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1073 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
1074 {
1075 return dtl::force_copy<iterator>(
1076 m_flat_tree.insert_unique( dtl::force_copy<impl_const_iterator>(p)
1077 , dtl::force<const impl_value_type>(x)));
1078 }
1079
1080 //! <b>Effects</b>: Inserts an element move constructed from x in the container.
1081 //! p is a hint pointing to where the insert should start to search.
1082 //!
1083 //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
1084 //!
1085 //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
1086 //! right before p) plus insertion linear to the elements with bigger keys than x.
1087 //!
1088 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1089 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
1090 {
1091 return dtl::force_copy<iterator>
1092 (m_flat_tree.insert_unique( dtl::force_copy<impl_const_iterator>(p)
1093 , boost::move(dtl::force<impl_value_type>(x))));
1094 }
1095
1096 //! <b>Effects</b>: Inserts an element move constructed from x in the container.
1097 //! p is a hint pointing to where the insert should start to search.
1098 //!
1099 //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
1100 //!
1101 //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
1102 //! right before p) plus insertion linear to the elements with bigger keys than x.
1103 //!
1104 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1105 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
1106 {
1107 return dtl::force_copy<iterator>(
1108 m_flat_tree.insert_unique(dtl::force_copy<impl_const_iterator>(p), boost::move(x)));
1109 }
1110
1111 //! <b>Requires</b>: first, last are not iterators into *this.
1112 //!
1113 //! <b>Effects</b>: inserts each element from the range [first,last) if and only
1114 //! if there is no element with key equivalent to the key of that element.
1115 //!
1116 //! <b>Complexity</b>: N log(size()+N).
1117 //!
1118 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1119 template <class InputIterator>
1120 BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
1121 { m_flat_tree.insert_unique(first, last); }
1122
1123 //! <b>Requires</b>: first, last are not iterators into *this.
1124 //!
1125 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
1126 //! unique values.
1127 //!
1128 //! <b>Effects</b>: inserts each element from the range [first,last) if and only
1129 //! if there is no element with key equivalent to the key of that element. This
1130 //! function is more efficient than the normal range creation for ordered ranges.
1131 //!
1132 //! <b>Complexity</b>: Linear.
1133 //!
1134 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1135 //!
1136 //! <b>Note</b>: Non-standard extension.
1137 template <class InputIterator>
1138 BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
1139 { m_flat_tree.insert_unique(ordered_unique_range, first, last); }
1140
1141#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1142 //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
1143 //! if there is no element with key equivalent to the key of that element.
1144 //!
1145 //! <b>Complexity</b>: N log(N).
1146 //!
1147 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1148 BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
1149 {
1150 m_flat_tree.insert_unique( dtl::force<impl_initializer_list>(il).begin()
1151 , dtl::force<impl_initializer_list>(il).end());
1152 }
1153
1154 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
1155 //! unique values.
1156 //!
1157 //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
1158 //! if there is no element with key equivalent to the key of that element. This
1159 //! function is more efficient than the normal range creation for ordered ranges.
1160 //!
1161 //! <b>Complexity</b>: Linear.
1162 //!
1163 //! <b>Note</b>: If an element is inserted it might invalidate elements.
1164 //!
1165 //! <b>Note</b>: Non-standard extension.
1166 BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
1167 {
1168 m_flat_tree.insert_unique(ordered_unique_range
1169 , dtl::force<impl_initializer_list>(il).begin()
1170 , dtl::force<impl_initializer_list>(il).end());
1171 }
1172#endif
1173
1174 //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
1175 //!
1176 //! <b>Effects</b>: Attempts to extract each element in source and insert it into a using
1177 //! the comparison object of *this. If there is an element in a with key equivalent to the
1178 //! key of an element from source, then that element is not extracted from source.
1179 //!
1180 //! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
1181 //! to those same elements but as members of *this. Iterators referring to the transferred
1182 //! elements will continue to refer to their elements, but they now behave as iterators into *this,
1183 //! not into source.
1184 //!
1185 //! <b>Throws</b>: Nothing unless the comparison object throws.
1186 //!
1187 //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
1188 template<class C2>
1189 BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
1190 { m_flat_tree.merge_unique(source.tree()); }
1191
1192 //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
1193 template<class C2>
1194 BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
1195 { return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
1196
1197 //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
1198 template<class C2>
1199 BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
1200 { m_flat_tree.merge_unique(source.tree()); }
1201
1202 //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
1203 template<class C2>
1204 BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
1205 { return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
1206
1207 //! <b>Effects</b>: Erases the element pointed to by p.
1208 //!
1209 //! <b>Returns</b>: Returns an iterator pointing to the element immediately
1210 //! following q prior to the element being erased. If no such element exists,
1211 //! returns end().
1212 //!
1213 //! <b>Complexity</b>: Linear to the elements with keys bigger than p
1214 //!
1215 //! <b>Note</b>: Invalidates elements with keys
1216 //! not less than the erased element.
1217 BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p)
1218 {
1219 return dtl::force_copy<iterator>
1220 (m_flat_tree.erase(dtl::force_copy<impl_const_iterator>(p)));
1221 }
1222
1223 //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
1224 //!
1225 //! <b>Returns</b>: Returns the number of erased elements.
1226 //!
1227 //! <b>Complexity</b>: Logarithmic search time plus erasure time
1228 //! linear to the elements with bigger keys.
1229 BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x)
1230 { return m_flat_tree.erase(x); }
1231
1232 //! <b>Effects</b>: Erases all the elements in the range [first, last).
1233 //!
1234 //! <b>Returns</b>: Returns last.
1235 //!
1236 //! <b>Complexity</b>: size()*N where N is the distance from first to last.
1237 //!
1238 //! <b>Complexity</b>: Logarithmic search time plus erasure time
1239 //! linear to the elements with bigger keys.
1240 BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
1241 {
1242 return dtl::force_copy<iterator>(
1243 m_flat_tree.erase( dtl::force_copy<impl_const_iterator>(first)
1244 , dtl::force_copy<impl_const_iterator>(last)));
1245 }
1246
1247 //! <b>Effects</b>: Swaps the contents of *this and x.
1248 //!
1249 //! <b>Throws</b>: Nothing.
1250 //!
1251 //! <b>Complexity</b>: Constant.
1252 BOOST_CONTAINER_FORCEINLINE void swap(flat_map& x)
1253 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
1254 && boost::container::dtl::is_nothrow_swappable<Compare>::value )
1255 { m_flat_tree.swap(x.m_flat_tree); }
1256
1257 //! <b>Effects</b>: erase(a.begin(),a.end()).
1258 //!
1259 //! <b>Postcondition</b>: size() == 0.
1260 //!
1261 //! <b>Complexity</b>: linear in size().
1262 BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
1263 { m_flat_tree.clear(); }
1264
1265 //////////////////////////////////////////////
1266 //
1267 // observers
1268 //
1269 //////////////////////////////////////////////
1270
1271 //! <b>Effects</b>: Returns the comparison object out
1272 //! of which a was constructed.
1273 //!
1274 //! <b>Complexity</b>: Constant.
1275 BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const
1276 { return dtl::force_copy<key_compare>(m_flat_tree.key_comp()); }
1277
1278 //! <b>Effects</b>: Returns an object of value_compare constructed out
1279 //! of the comparison object.
1280 //!
1281 //! <b>Complexity</b>: Constant.
1282 BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
1283 { return value_compare(dtl::force_copy<key_compare>(m_flat_tree.key_comp())); }
1284
1285 //////////////////////////////////////////////
1286 //
1287 // map operations
1288 //
1289 //////////////////////////////////////////////
1290
1291 //! <b>Returns</b>: An iterator pointing to an element with the key
1292 //! equivalent to x, or end() if such an element is not found.
1293 //!
1294 //! <b>Complexity</b>: Logarithmic.
1295 BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& x)
1296 { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
1297
1298 //! <b>Returns</b>: A const_iterator pointing to an element with the key
1299 //! equivalent to x, or end() if such an element is not found.
1300 //!
1301 //! <b>Complexity</b>: Logarithmic.
1302 BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const
1303 { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
1304
1305 //! <b>Requires</b>: This overload is available only if
1306 //! key_compare::is_transparent exists.
1307 //!
1308 //! <b>Returns</b>: An iterator pointing to an element with the key
1309 //! equivalent to x, or end() if such an element is not found.
1310 //!
1311 //! <b>Complexity</b>: Logarithmic.
1312 template<class K>
1313 BOOST_CONTAINER_FORCEINLINE iterator find(const K& x)
1314 { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
1315
1316 //! <b>Requires</b>: This overload is available only if
1317 //! key_compare::is_transparent exists.
1318 //!
1319 //! <b>Returns</b>: A const_iterator pointing to an element with the key
1320 //! equivalent to x, or end() if such an element is not found.
1321 //!
1322 //! <b>Complexity</b>: Logarithmic.
1323 template<class K>
1324 BOOST_CONTAINER_FORCEINLINE const_iterator find(const K& x) const
1325 { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
1326
1327 //! <b>Returns</b>: The number of elements with key equivalent to x.
1328 //!
1329 //! <b>Complexity</b>: log(size())+count(k)
1330 BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
1331 { return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
1332
1333 //! <b>Requires</b>: This overload is available only if
1334 //! key_compare::is_transparent exists.
1335 //!
1336 //! <b>Returns</b>: The number of elements with key equivalent to x.
1337 //!
1338 //! <b>Complexity</b>: log(size())+count(k)
1339 template<class K>
1340 BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
1341 { return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
1342
1343 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1344 //! than k, or a.end() if such an element is not found.
1345 //!
1346 //! <b>Complexity</b>: Logarithmic.
1347 BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x)
1348 { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
1349
1350 //! <b>Returns</b>: A const iterator pointing to the first element with key not
1351 //! less than k, or a.end() if such an element is not found.
1352 //!
1353 //! <b>Complexity</b>: Logarithmic.
1354 BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const
1355 { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
1356
1357 //! <b>Requires</b>: This overload is available only if
1358 //! key_compare::is_transparent exists.
1359 //!
1360 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1361 //! than k, or a.end() if such an element is not found.
1362 //!
1363 //! <b>Complexity</b>: Logarithmic.
1364 template<class K>
1365 BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const K& x)
1366 { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
1367
1368 //! <b>Requires</b>: This overload is available only if
1369 //! key_compare::is_transparent exists.
1370 //!
1371 //! <b>Returns</b>: A const iterator pointing to the first element with key not
1372 //! less than k, or a.end() if such an element is not found.
1373 //!
1374 //! <b>Complexity</b>: Logarithmic.
1375 template<class K>
1376 BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const K& x) const
1377 { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
1378
1379 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1380 //! than x, or end() if such an element is not found.
1381 //!
1382 //! <b>Complexity</b>: Logarithmic.
1383 BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& x)
1384 { return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
1385
1386 //! <b>Returns</b>: A const iterator pointing to the first element with key not
1387 //! less than x, or end() if such an element is not found.
1388 //!
1389 //! <b>Complexity</b>: Logarithmic.
1390 BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const
1391 { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
1392
1393 //! <b>Requires</b>: This overload is available only if
1394 //! key_compare::is_transparent exists.
1395 //!
1396 //! <b>Returns</b>: An iterator pointing to the first element with key not less
1397 //! than x, or end() if such an element is not found.
1398 //!
1399 //! <b>Complexity</b>: Logarithmic.
1400 template<class K>
1401 BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const K& x)
1402 { return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
1403
1404 //! <b>Requires</b>: This overload is available only if
1405 //! key_compare::is_transparent exists.
1406 //!
1407 //! <b>Returns</b>: A const iterator pointing to the first element with key not
1408 //! less than x, or end() if such an element is not found.
1409 //!
1410 //! <b>Complexity</b>: Logarithmic.
1411 template<class K>
1412 BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const K& x) const
1413 { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
1414
1415 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1416 //!
1417 //! <b>Complexity</b>: Logarithmic.
1418 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
1419 { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
1420
1421 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1422 //!
1423 //! <b>Complexity</b>: Logarithmic.
1424 BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
1425 { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
1426
1427 //! <b>Requires</b>: This overload is available only if
1428 //! key_compare::is_transparent exists.
1429 //!
1430 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1431 //!
1432 //! <b>Complexity</b>: Logarithmic.
1433 template<class K>
1434 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
1435 { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
1436
1437 //! <b>Requires</b>: This overload is available only if
1438 //! key_compare::is_transparent exists.
1439 //!
1440 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1441 //!
1442 //! <b>Complexity</b>: Logarithmic.
1443 template<class K>
1444 BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
1445 { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
1446
1447 //! <b>Effects</b>: Extracts the internal sequence container.
1448 //!
1449 //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
1450 //!
1451 //! <b>Postcondition</b>: this->empty()
1452 //!
1453 //! <b>Throws</b>: If secuence_type's move constructor throws
1454 BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
1455 {
1456 return boost::move(dtl::force<sequence_type>(m_flat_tree.get_sequence_ref()));
1457 }
1458
1459 //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
1460 //! one passed externally using the move assignment. Erases non-unique elements.
1461 //!
1462 //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
1463 //!
1464 //! <b>Throws</b>: If the comparison or the move constructor throws
1465 BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
1466 { this->m_flat_tree.adopt_sequence_unique(boost::move(dtl::force<impl_sequence_type>(seq))); }
1467
1468 //! <b>Requires</b>: seq shall be ordered according to this->compare()
1469 //! and shall contain unique elements.
1470 //!
1471 //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
1472 //! one passed externally using the move assignment.
1473 //!
1474 //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
1475 //!
1476 //! <b>Throws</b>: If the move assignment throws
1477 BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
1478 { this->m_flat_tree.adopt_sequence_unique(ordered_unique_range_t(), boost::move(dtl::force<impl_sequence_type>(seq))); }
1479
1480 //! <b>Effects</b>: Returns true if x and y are equal
1481 //!
1482 //! <b>Complexity</b>: Linear to the number of elements in the container.
1483 BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_map& x, const flat_map& y)
1484 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
1485
1486 //! <b>Effects</b>: Returns true if x and y are unequal
1487 //!
1488 //! <b>Complexity</b>: Linear to the number of elements in the container.
1489 BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_map& x, const flat_map& y)
1490 { return !(x == y); }
1491
1492 //! <b>Effects</b>: Returns true if x is less than y
1493 //!
1494 //! <b>Complexity</b>: Linear to the number of elements in the container.
1495 BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_map& x, const flat_map& y)
1496 { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
1497
1498 //! <b>Effects</b>: Returns true if x is greater than y
1499 //!
1500 //! <b>Complexity</b>: Linear to the number of elements in the container.
1501 BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_map& x, const flat_map& y)
1502 { return y < x; }
1503
1504 //! <b>Effects</b>: Returns true if x is equal or less than y
1505 //!
1506 //! <b>Complexity</b>: Linear to the number of elements in the container.
1507 BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_map& x, const flat_map& y)
1508 { return !(y < x); }
1509
1510 //! <b>Effects</b>: Returns true if x is equal or greater than y
1511 //!
1512 //! <b>Complexity</b>: Linear to the number of elements in the container.
1513 BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_map& x, const flat_map& y)
1514 { return !(x < y); }
1515
1516 //! <b>Effects</b>: x.swap(y)
1517 //!
1518 //! <b>Complexity</b>: Constant.
1519 BOOST_CONTAINER_FORCEINLINE friend void swap(flat_map& x, flat_map& y)
1520 { x.swap(y); }
1521
1522 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1523 private:
1524 mapped_type &priv_subscript(const key_type& k)
1525 {
1526 iterator i = lower_bound(k);
1527 // i->first is greater than or equivalent to k.
1528 if (i == end() || key_comp()(k, (*i).first)){
1529 dtl::value_init<mapped_type> m;
1530 i = insert(i, impl_value_type(k, ::boost::move(m.m_t)));
1531 }
1532 return (*i).second;
1533 }
1534 mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk)
1535 {
1536 key_type &k = mk;
1537 iterator i = lower_bound(k);
1538 // i->first is greater than or equivalent to k.
1539 if (i == end() || key_comp()(k, (*i).first)){
1540 dtl::value_init<mapped_type> m;
1541 i = insert(i, impl_value_type(boost::move(k), ::boost::move(m.m_t)));
1542 }
1543 return (*i).second;
1544 }
1545 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1546};
1547
1548#if __cplusplus >= 201703L
1549
1550template <typename InputIterator>
1551flat_map(InputIterator, InputIterator) ->
1552 flat_map< typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
1553 , typename iterator_traits<InputIterator>::value_type::second_type>;
1554
1555template <typename InputIterator, typename Allocator>
1556flat_map(InputIterator, InputIterator, Allocator const&) ->
1557 flat_map< typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
1558 , typename iterator_traits<InputIterator>::value_type::second_type
1559 , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
1560 , Allocator>;
1561
1562template <typename InputIterator, typename Compare>
1563flat_map(InputIterator, InputIterator, Compare const&) ->
1564 flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
1565 , typename iterator_traits<InputIterator>::value_type::second_type
1566 , Compare>;
1567
1568template <typename InputIterator, typename Compare, typename Allocator>
1569flat_map(InputIterator, InputIterator, Compare const&, Allocator const&) ->
1570 flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
1571 , typename iterator_traits<InputIterator>::value_type::second_type
1572 , Compare
1573 , Allocator>;
1574
1575template <typename InputIterator>
1576flat_map(ordered_unique_range_t, InputIterator, InputIterator) ->
1577 flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
1578 , typename iterator_traits<InputIterator>::value_type::second_type>;
1579
1580template <typename InputIterator, typename Allocator>
1581flat_map(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) ->
1582 flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
1583 , typename iterator_traits<InputIterator>::value_type::second_type
1584 , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
1585 , Allocator>;
1586
1587template <typename InputIterator, typename Compare>
1588flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) ->
1589 flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
1590 , typename iterator_traits<InputIterator>::value_type::second_type
1591 , Compare>;
1592
1593template <typename InputIterator, typename Compare, typename Allocator>
1594flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
1595 flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
1596 , typename iterator_traits<InputIterator>::value_type::second_type
1597 , Compare
1598 , Allocator>;
1599
1600#endif
1601
1602#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1603
1604} //namespace container {
1605
1606//!has_trivial_destructor_after_move<> == true_type
1607//!specialization for optimizations
1608template <class Key, class T, class Compare, class AllocatorOrContainer>
1609struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, AllocatorOrContainer> >
1610{
1611 typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
1612 static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
1613 ::boost::has_trivial_destructor_after_move<pointer>::value &&
1614 ::boost::has_trivial_destructor_after_move<Compare>::value;
1615};
1616
1617namespace container {
1618
1619#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1620
1621//! A flat_multimap is a kind of associative container that supports equivalent keys
1622//! (possibly containing multiple copies of the same key value) and provides for
1623//! fast retrieval of values of another type T based on the keys.
1624//!
1625//! A flat_multimap satisfies all of the requirements of a container and of a reversible
1626//! container and of an associative container. For a
1627//! flat_multimap<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
1628//! (unlike std::multimap<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
1629//!
1630//! flat_multimap is similar to std::multimap but it's implemented by as an ordered sequence container.
1631//! The underlying sequence container is by default <i>vector</i> but it can also work
1632//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
1633//!
1634//! Using vector-like sequence containers means that inserting a new element into a flat_multimap might invalidate
1635//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
1636//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
1637//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
1638//!
1639//! This container provides random-access iterators.
1640//!
1641//! \tparam Key is the key_type of the map
1642//! \tparam Value is the <code>mapped_type</code>
1643//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
1644//! \tparam AllocatorOrContainer is either:
1645//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
1646//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
1647//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
1648//! sequence container with random-access iterators.
1649#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
1650template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
1651#else
1652template <class Key, class T, class Compare, class AllocatorOrContainer>
1653#endif
1654class flat_multimap
1655{
1656 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1657 private:
1658 BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
1659 typedef dtl::flat_tree<
1660 std::pair<Key, T>,
1661 dtl::select1st<Key>,
1662 Compare,
1663 AllocatorOrContainer> tree_t;
1664 //This is the real tree stored here. It's based on a movable pair
1665 typedef dtl::flat_tree<
1666 dtl::pair<Key, T>,
1667 dtl::select1st<Key>,
1668 Compare,
1669 typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
1670 > impl_tree_t;
1671 impl_tree_t m_flat_tree; // flat tree representing flat_map
1672
1673 typedef typename impl_tree_t::value_type impl_value_type;
1674 typedef typename impl_tree_t::const_iterator impl_const_iterator;
1675 typedef typename impl_tree_t::iterator impl_iterator;
1676 typedef typename impl_tree_t::allocator_type impl_allocator_type;
1677 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1678 typedef std::initializer_list<impl_value_type> impl_initializer_list;
1679 #endif
1680
1681 typedef dtl::flat_tree_value_compare
1682 < Compare
1683 , dtl::select1st<Key>
1684 , std::pair<Key, T> > value_compare_t;
1685 typedef typename tree_t::iterator iterator_t;
1686 typedef typename tree_t::const_iterator const_iterator_t;
1687 typedef typename tree_t::reverse_iterator reverse_iterator_t;
1688 typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
1689
1690 public:
1691 typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
1692 typedef typename impl_tree_t::sequence_type impl_sequence_type;
1693
1694 BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
1695 { return m_flat_tree; }
1696
1697 BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const
1698 { return m_flat_tree; }
1699
1700 private:
1701 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1702
1703 public:
1704
1705 //////////////////////////////////////////////
1706 //
1707 // types
1708 //
1709 //////////////////////////////////////////////
1710 typedef Key key_type;
1711 typedef T mapped_type;
1712 typedef Compare key_compare;
1713 typedef std::pair<Key, T> value_type;
1714 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
1715 typedef typename sequence_type::allocator_type allocator_type;
1716 typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
1717 typedef typename sequence_type::pointer pointer;
1718 typedef typename sequence_type::const_pointer const_pointer;
1719 typedef typename sequence_type::reference reference;
1720 typedef typename sequence_type::const_reference const_reference;
1721 typedef typename sequence_type::size_type size_type;
1722 typedef typename sequence_type::difference_type difference_type;
1723 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
1724 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
1725
1726 typedef typename sequence_type::iterator iterator;
1727 typedef typename sequence_type::const_iterator const_iterator;
1728 typedef typename sequence_type::reverse_iterator reverse_iterator;
1729 typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
1730 typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
1731
1732 //AllocatorOrContainer::value_type must be std::pair<Key, T>
1733 BOOST_STATIC_ASSERT((dtl::is_same<std::pair<Key, T>, typename AllocatorOrContainer::value_type>::value));
1734
1735 //////////////////////////////////////////////
1736 //
1737 // construct/copy/destroy
1738 //
1739 //////////////////////////////////////////////
1740
1741 //! <b>Effects</b>: Default constructs an empty flat_map.
1742 //!
1743 //! <b>Complexity</b>: Constant.
1744 BOOST_CONTAINER_FORCEINLINE flat_multimap()
1745 BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
1746 dtl::is_nothrow_default_constructible<Compare>::value)
1747 : m_flat_tree()
1748 {}
1749
1750 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
1751 //!
1752 //! <b>Complexity</b>: Constant.
1753 BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const allocator_type& a)
1754 : m_flat_tree(dtl::force<const impl_allocator_type>(a))
1755 {}
1756
1757 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
1758 //! object .
1759 //!
1760 //! <b>Complexity</b>: Constant.
1761 BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const Compare& comp)
1762 : m_flat_tree(comp)
1763 {}
1764
1765 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
1766 //! object and allocator.
1767 //!
1768 //! <b>Complexity</b>: Constant.
1769 BOOST_CONTAINER_FORCEINLINE
1770 flat_multimap(const Compare& comp, const allocator_type& a)
1771 : m_flat_tree(comp, dtl::force<const impl_allocator_type>(a))
1772 {}
1773
1774 //! <b>Effects</b>: Constructs an empty flat_multimap
1775 //! and inserts elements from the range [first ,last ).
1776 //!
1777 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
1778 //! the predicate and otherwise N logN, where N is last - first.
1779 template <class InputIterator>
1780 BOOST_CONTAINER_FORCEINLINE
1781 flat_multimap(InputIterator first, InputIterator last)
1782 : m_flat_tree(false, first, last)
1783 {}
1784
1785 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified
1786 //! allocator, and inserts elements from the range [first ,last ).
1787 //!
1788 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
1789 //! the predicate and otherwise N logN, where N is last - first.
1790 template <class InputIterator>
1791 BOOST_CONTAINER_FORCEINLINE
1792 flat_multimap(InputIterator first, InputIterator last, const allocator_type& a)
1793 : m_flat_tree(false, first, last, dtl::force<const impl_allocator_type>(a))
1794 {}
1795
1796 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
1797 //! and inserts elements from the range [first ,last ).
1798 //!
1799 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
1800 //! the predicate and otherwise N logN, where N is last - first.
1801 template <class InputIterator>
1802 BOOST_CONTAINER_FORCEINLINE
1803 flat_multimap(InputIterator first, InputIterator last, const Compare& comp)
1804 : m_flat_tree(false, first, last, comp)
1805 {}
1806
1807 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
1808 //! and allocator, and inserts elements from the range [first ,last ).
1809 //!
1810 //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
1811 //! the predicate and otherwise N logN, where N is last - first.
1812 template <class InputIterator>
1813 BOOST_CONTAINER_FORCEINLINE
1814 flat_multimap(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
1815 : m_flat_tree(false, first, last, comp, dtl::force<const impl_allocator_type>(a))
1816 {}
1817
1818 //! <b>Effects</b>: Constructs an empty flat_multimap
1819 //! and inserts elements from the ordered range [first ,last). This function
1820 //! is more efficient than the normal range creation for ordered ranges.
1821 //!
1822 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
1823 //!
1824 //! <b>Complexity</b>: Linear in N.
1825 //!
1826 //! <b>Note</b>: Non-standard extension.
1827 template <class InputIterator>
1828 BOOST_CONTAINER_FORCEINLINE
1829 flat_multimap(ordered_range_t, InputIterator first, InputIterator last)
1830 : m_flat_tree(ordered_range, first, last)
1831 {}
1832
1833 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
1834 //! inserts elements from the ordered range [first ,last). This function
1835 //! is more efficient than the normal range creation for ordered ranges.
1836 //!
1837 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
1838 //!
1839 //! <b>Complexity</b>: Linear in N.
1840 //!
1841 //! <b>Note</b>: Non-standard extension.
1842 template <class InputIterator>
1843 BOOST_CONTAINER_FORCEINLINE
1844 flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
1845 : m_flat_tree(ordered_range, first, last, comp)
1846 {}
1847
1848 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
1849 //! allocator, and inserts elements from the ordered range [first ,last). This function
1850 //! is more efficient than the normal range creation for ordered ranges.
1851 //!
1852 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
1853 //!
1854 //! <b>Complexity</b>: Linear in N.
1855 //!
1856 //! <b>Note</b>: Non-standard extension.
1857 template <class InputIterator>
1858 BOOST_CONTAINER_FORCEINLINE
1859 flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
1860 : m_flat_tree(ordered_range, first, last, comp, a)
1861 {}
1862
1863#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1864 //! <b>Effects</b>: Constructs an empty flat_map and
1865 //! inserts elements from the range [il.begin(), il.end()).
1866 //!
1867 //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
1868 //! the predicate and otherwise N logN, where N is last - first.
1869 BOOST_CONTAINER_FORCEINLINE
1870 flat_multimap(std::initializer_list<value_type> il)
1871 : m_flat_tree( false
1872 , dtl::force<impl_initializer_list>(il).begin()
1873 , dtl::force<impl_initializer_list>(il).end())
1874 {}
1875
1876 //! <b>Effects</b>: Constructs an empty flat_map using the specified
1877 //! allocator, and inserts elements from the range [il.begin(), il.end()).
1878 //!
1879 //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
1880 //! the predicate and otherwise N logN, where N is last - first.
1881 BOOST_CONTAINER_FORCEINLINE
1882 flat_multimap(std::initializer_list<value_type> il, const allocator_type& a)
1883 : m_flat_tree(false
1884 , dtl::force<impl_initializer_list>(il).begin()
1885 , dtl::force<impl_initializer_list>(il).end()
1886 , dtl::force<const impl_allocator_type>(a))
1887 {}
1888
1889 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
1890 //! inserts elements from the range [il.begin(), il.end()).
1891 //!
1892 //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
1893 //! the predicate and otherwise N logN, where N is last - first.
1894 BOOST_CONTAINER_FORCEINLINE
1895 flat_multimap(std::initializer_list<value_type> il, const Compare& comp)
1896 : m_flat_tree(false
1897 , dtl::force<impl_initializer_list>(il).begin()
1898 , dtl::force<impl_initializer_list>(il).end(), comp)
1899 {}
1900
1901 //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
1902 //! allocator, and inserts elements from the range [il.begin(), il.end()).
1903 //!
1904 //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
1905 //! the predicate and otherwise N logN, where N is last - first.
1906 BOOST_CONTAINER_FORCEINLINE
1907 flat_multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
1908 : m_flat_tree( false
1909 , dtl::force<impl_initializer_list>(il).begin()
1910 , dtl::force<impl_initializer_list>(il).end()
1911 , comp, dtl::force<const impl_allocator_type>(a))
1912 {}
1913
1914 //! <b>Effects</b>: Constructs an empty flat_multimap and
1915 //! inserts elements from the ordered range [il.begin(), il.end()). This function
1916 //! is more efficient than the normal range creation for ordered ranges.
1917 //!
1918 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
1919 //!
1920 //! <b>Complexity</b>: Linear in N.
1921 //!
1922 //! <b>Note</b>: Non-standard extension.
1923 BOOST_CONTAINER_FORCEINLINE
1924 flat_multimap(ordered_range_t, std::initializer_list<value_type> il)
1925 : m_flat_tree( ordered_range
1926 , dtl::force<impl_initializer_list>(il).begin()
1927 , dtl::force<impl_initializer_list>(il).end())
1928 {}
1929
1930 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
1931 //! inserts elements from the ordered range [il.begin(), il.end()). This function
1932 //! is more efficient than the normal range creation for ordered ranges.
1933 //!
1934 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
1935 //!
1936 //! <b>Complexity</b>: Linear in N.
1937 //!
1938 //! <b>Note</b>: Non-standard extension.
1939 BOOST_CONTAINER_FORCEINLINE
1940 flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
1941 : m_flat_tree( ordered_range
1942 , dtl::force<impl_initializer_list>(il).begin()
1943 , dtl::force<impl_initializer_list>(il).end(), comp)
1944 {}
1945
1946 //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
1947 //! allocator, and inserts elements from the ordered range [il.begin(), il.end()). This function
1948 //! is more efficient than the normal range creation for ordered ranges.
1949 //!
1950 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
1951 //!
1952 //! <b>Complexity</b>: Linear in N.
1953 //!
1954 //! <b>Note</b>: Non-standard extension.
1955 BOOST_CONTAINER_FORCEINLINE
1956 flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
1957 : m_flat_tree( ordered_range
1958 , dtl::force<impl_initializer_list>(il).begin()
1959 , dtl::force<impl_initializer_list>(il).end()
1960 , comp, dtl::force<const impl_allocator_type>(a))
1961 {}
1962#endif
1963
1964 //! <b>Effects</b>: Copy constructs a flat_multimap.
1965 //!
1966 //! <b>Complexity</b>: Linear in x.size().
1967 BOOST_CONTAINER_FORCEINLINE
1968 flat_multimap(const flat_multimap& x)
1969 : m_flat_tree(x.m_flat_tree)
1970 {}
1971
1972 //! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources.
1973 //!
1974 //! <b>Complexity</b>: Constant.
1975 //!
1976 //! <b>Postcondition</b>: x is emptied.
1977 BOOST_CONTAINER_FORCEINLINE
1978 flat_multimap(BOOST_RV_REF(flat_multimap) x)
1979 BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
1980 : m_flat_tree(boost::move(x.m_flat_tree))
1981 {}
1982
1983 //! <b>Effects</b>: Copy constructs a flat_multimap using the specified allocator.
1984 //!
1985 //! <b>Complexity</b>: Linear in x.size().
1986 BOOST_CONTAINER_FORCEINLINE
1987 flat_multimap(const flat_multimap& x, const allocator_type &a)
1988 : m_flat_tree(x.m_flat_tree, dtl::force<const impl_allocator_type>(a))
1989 {}
1990
1991 //! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator.
1992 //! Constructs *this using x's resources.
1993 //!
1994 //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
1995 BOOST_CONTAINER_FORCEINLINE
1996 flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
1997 : m_flat_tree(boost::move(x.m_flat_tree), dtl::force<const impl_allocator_type>(a))
1998 {}
1999
2000 //! <b>Effects</b>: Makes *this a copy of x.
2001 //!
2002 //! <b>Complexity</b>: Linear in x.size().
2003 BOOST_CONTAINER_FORCEINLINE
2004 flat_multimap& operator=(BOOST_COPY_ASSIGN_REF(flat_multimap) x)
2005 { m_flat_tree = x.m_flat_tree; return *this; }
2006
2007 //! <b>Effects</b>: this->swap(x.get()).
2008 //!
2009 //! <b>Complexity</b>: Constant.
2010 BOOST_CONTAINER_FORCEINLINE
2011 flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x)
2012 BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
2013 allocator_traits_type::is_always_equal::value) &&
2014 boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
2015 { m_flat_tree = boost::move(x.m_flat_tree); return *this; }
2016
2017#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2018 //! <b>Effects</b>: Assign content of il to *this
2019 //!
2020 //! <b>Complexity</b>: Linear in il.size().
2021 BOOST_CONTAINER_FORCEINLINE
2022 flat_multimap& operator=(std::initializer_list<value_type> il)
2023 {
2024 this->clear();
2025 this->insert(il.begin(), il.end());
2026 return *this;
2027 }
2028#endif
2029
2030 //! <b>Effects</b>: Returns a copy of the allocator that
2031 //! was passed to the object's constructor.
2032 //!
2033 //! <b>Complexity</b>: Constant.
2034 BOOST_CONTAINER_FORCEINLINE
2035 allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
2036 { return dtl::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
2037
2038 //! <b>Effects</b>: Returns a reference to the internal allocator.
2039 //!
2040 //! <b>Throws</b>: Nothing
2041 //!
2042 //! <b>Complexity</b>: Constant.
2043 //!
2044 //! <b>Note</b>: Non-standard extension.
2045 BOOST_CONTAINER_FORCEINLINE
2046 stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
2047 { return dtl::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
2048
2049 //! <b>Effects</b>: Returns a reference to the internal allocator.
2050 //!
2051 //! <b>Throws</b>: Nothing
2052 //!
2053 //! <b>Complexity</b>: Constant.
2054 //!
2055 //! <b>Note</b>: Non-standard extension.
2056 BOOST_CONTAINER_FORCEINLINE
2057 const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
2058 { return dtl::force<const stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
2059
2060 //////////////////////////////////////////////
2061 //
2062 // iterators
2063 //
2064 //////////////////////////////////////////////
2065
2066 //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
2067 //!
2068 //! <b>Throws</b>: Nothing.
2069 //!
2070 //! <b>Complexity</b>: Constant.
2071 BOOST_CONTAINER_FORCEINLINE
2072 iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
2073 { return dtl::force_copy<iterator>(m_flat_tree.begin()); }
2074
2075 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
2076 //!
2077 //! <b>Throws</b>: Nothing.
2078 //!
2079 //! <b>Complexity</b>: Constant.
2080 BOOST_CONTAINER_FORCEINLINE
2081 const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
2082 { return dtl::force_copy<const_iterator>(m_flat_tree.begin()); }
2083
2084 //! <b>Effects</b>: Returns an iterator to the end of the container.
2085 //!
2086 //! <b>Throws</b>: Nothing.
2087 //!
2088 //! <b>Complexity</b>: Constant.
2089 BOOST_CONTAINER_FORCEINLINE
2090 iterator end() BOOST_NOEXCEPT_OR_NOTHROW
2091 { return dtl::force_copy<iterator>(m_flat_tree.end()); }
2092
2093 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
2094 //!
2095 //! <b>Throws</b>: Nothing.
2096 //!
2097 //! <b>Complexity</b>: Constant.
2098 BOOST_CONTAINER_FORCEINLINE
2099 const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
2100 { return dtl::force_copy<const_iterator>(m_flat_tree.end()); }
2101
2102 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
2103 //! of the reversed container.
2104 //!
2105 //! <b>Throws</b>: Nothing.
2106 //!
2107 //! <b>Complexity</b>: Constant.
2108 BOOST_CONTAINER_FORCEINLINE
2109 reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
2110 { return dtl::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
2111
2112 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
2113 //! of the reversed container.
2114 //!
2115 //! <b>Throws</b>: Nothing.
2116 //!
2117 //! <b>Complexity</b>: Constant.
2118 BOOST_CONTAINER_FORCEINLINE
2119 const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
2120 { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
2121
2122 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
2123 //! of the reversed container.
2124 //!
2125 //! <b>Throws</b>: Nothing.
2126 //!
2127 //! <b>Complexity</b>: Constant.
2128 BOOST_CONTAINER_FORCEINLINE
2129 reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
2130 { return dtl::force_copy<reverse_iterator>(m_flat_tree.rend()); }
2131
2132 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
2133 //! of the reversed container.
2134 //!
2135 //! <b>Throws</b>: Nothing.
2136 //!
2137 //! <b>Complexity</b>: Constant.
2138 BOOST_CONTAINER_FORCEINLINE
2139 const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
2140 { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
2141
2142 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
2143 //!
2144 //! <b>Throws</b>: Nothing.
2145 //!
2146 //! <b>Complexity</b>: Constant.
2147 BOOST_CONTAINER_FORCEINLINE
2148 const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
2149 { return dtl::force_copy<const_iterator>(m_flat_tree.cbegin()); }
2150
2151 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
2152 //!
2153 //! <b>Throws</b>: Nothing.
2154 //!
2155 //! <b>Complexity</b>: Constant.
2156 BOOST_CONTAINER_FORCEINLINE
2157 const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
2158 { return dtl::force_copy<const_iterator>(m_flat_tree.cend()); }
2159
2160 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
2161 //! of the reversed container.
2162 //!
2163 //! <b>Throws</b>: Nothing.
2164 //!
2165 //! <b>Complexity</b>: Constant.
2166 BOOST_CONTAINER_FORCEINLINE
2167 const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
2168 { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
2169
2170 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
2171 //! of the reversed container.
2172 //!
2173 //! <b>Throws</b>: Nothing.
2174 //!
2175 //! <b>Complexity</b>: Constant.
2176 BOOST_CONTAINER_FORCEINLINE
2177 const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
2178 { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
2179
2180 //////////////////////////////////////////////
2181 //
2182 // capacity
2183 //
2184 //////////////////////////////////////////////
2185
2186 //! <b>Effects</b>: Returns true if the container contains no elements.
2187 //!
2188 //! <b>Throws</b>: Nothing.
2189 //!
2190 //! <b>Complexity</b>: Constant.
2191 BOOST_CONTAINER_FORCEINLINE
2192 bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
2193 { return m_flat_tree.empty(); }
2194
2195 //! <b>Effects</b>: Returns the number of the elements contained in the container.
2196 //!
2197 //! <b>Throws</b>: Nothing.
2198 //!
2199 //! <b>Complexity</b>: Constant.
2200 BOOST_CONTAINER_FORCEINLINE
2201 size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
2202 { return m_flat_tree.size(); }
2203
2204 //! <b>Effects</b>: Returns the largest possible size of the container.
2205 //!
2206 //! <b>Throws</b>: Nothing.
2207 //!
2208 //! <b>Complexity</b>: Constant.
2209 BOOST_CONTAINER_FORCEINLINE
2210 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
2211 { return m_flat_tree.max_size(); }
2212
2213 //! <b>Effects</b>: Number of elements for which memory has been allocated.
2214 //! capacity() is always greater than or equal to size().
2215 //!
2216 //! <b>Throws</b>: Nothing.
2217 //!
2218 //! <b>Complexity</b>: Constant.
2219 BOOST_CONTAINER_FORCEINLINE
2220 size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
2221 { return m_flat_tree.capacity(); }
2222
2223 //! <b>Effects</b>: If n is less than or equal to capacity(), or the
2224 //! underlying container has no `reserve` member, this call has no
2225 //! effect. Otherwise, it is a request for allocation of additional memory.
2226 //! If the request is successful, then capacity() is greater than or equal to
2227 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
2228 //!
2229 //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
2230 //!
2231 //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
2232 //! to values might be invalidated.
2233 BOOST_CONTAINER_FORCEINLINE
2234 void reserve(size_type cnt)
2235 { m_flat_tree.reserve(cnt); }
2236
2237 //! <b>Effects</b>: Tries to deallocate the excess of memory created
2238 // with previous allocations. The size of the vector is unchanged
2239 //!
2240 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
2241 //!
2242 //! <b>Complexity</b>: Linear to size().
2243 BOOST_CONTAINER_FORCEINLINE
2244 void shrink_to_fit()
2245 { m_flat_tree.shrink_to_fit(); }
2246
2247 //! @copydoc ::boost::container::flat_set::nth(size_type)
2248 BOOST_CONTAINER_FORCEINLINE
2249 iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
2250 { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
2251
2252 //! @copydoc ::boost::container::flat_set::nth(size_type) const
2253 BOOST_CONTAINER_FORCEINLINE
2254 const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
2255 { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
2256
2257 //! @copydoc ::boost::container::flat_set::index_of(iterator)
2258 BOOST_CONTAINER_FORCEINLINE
2259 size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
2260 { return m_flat_tree.index_of(dtl::force_copy<impl_iterator>(p)); }
2261
2262 //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
2263 BOOST_CONTAINER_FORCEINLINE
2264 size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
2265 { return m_flat_tree.index_of(dtl::force_copy<impl_const_iterator>(p)); }
2266
2267 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2268
2269 //! <b>Effects</b>: Inserts an object of type T constructed with
2270 //! std::forward<Args>(args)... and returns the iterator pointing to the
2271 //! newly inserted element.
2272 //!
2273 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
2274 //! to the elements with bigger keys than x.
2275 //!
2276 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2277 template <class... Args>
2278 BOOST_CONTAINER_FORCEINLINE
2279 iterator emplace(BOOST_FWD_REF(Args)... args)
2280 { return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
2281
2282 //! <b>Effects</b>: Inserts an object of type T constructed with
2283 //! std::forward<Args>(args)... in the container.
2284 //! p is a hint pointing to where the insert should start to search.
2285 //!
2286 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
2287 //! to the key of x.
2288 //!
2289 //! <b>Complexity</b>: Logarithmic search time (constant time if the value
2290 //! is to be inserted before p) plus linear insertion
2291 //! to the elements with bigger keys than x.
2292 //!
2293 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2294 template <class... Args>
2295 BOOST_CONTAINER_FORCEINLINE
2296 iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
2297 {
2298 return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_equal
2299 (dtl::force_copy<impl_const_iterator>(hint), boost::forward<Args>(args)...));
2300 }
2301
2302 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
2303
2304 #define BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE(N) \
2305 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2306 BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
2307 { return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(BOOST_MOVE_FWD##N)); }\
2308 \
2309 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2310 BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2311 {\
2312 return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_equal\
2313 (dtl::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
2314 }\
2315 //
2316 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE)
2317 #undef BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE
2318
2319 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
2320
2321 //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
2322 //! newly inserted element.
2323 //!
2324 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
2325 //! to the elements with bigger keys than x.
2326 //!
2327 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2328 BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x)
2329 {
2330 return dtl::force_copy<iterator>(
2331 m_flat_tree.insert_equal(dtl::force<const impl_value_type>(x)));
2332 }
2333
2334 //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
2335 //! the iterator pointing to the newly inserted element.
2336 //!
2337 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
2338 //! to the elements with bigger keys than x.
2339 //!
2340 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2341 BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(value_type) x)
2342 { return dtl::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
2343
2344 //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
2345 //! the iterator pointing to the newly inserted element.
2346 //!
2347 //! <b>Complexity</b>: Logarithmic search time plus linear insertion
2348 //! to the elements with bigger keys than x.
2349 //!
2350 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2351 BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(impl_value_type) x)
2352 { return dtl::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
2353
2354 //! <b>Effects</b>: Inserts a copy of x in the container.
2355 //! p is a hint pointing to where the insert should start to search.
2356 //!
2357 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
2358 //! to the key of x.
2359 //!
2360 //! <b>Complexity</b>: Logarithmic search time (constant time if the value
2361 //! is to be inserted before p) plus linear insertion
2362 //! to the elements with bigger keys than x.
2363 //!
2364 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2365 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
2366 {
2367 return dtl::force_copy<iterator>
2368 (m_flat_tree.insert_equal( dtl::force_copy<impl_const_iterator>(p)
2369 , dtl::force<const impl_value_type>(x)));
2370 }
2371
2372 //! <b>Effects</b>: Inserts a value move constructed from x in the container.
2373 //! p is a hint pointing to where the insert should start to search.
2374 //!
2375 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
2376 //! to the key of x.
2377 //!
2378 //! <b>Complexity</b>: Logarithmic search time (constant time if the value
2379 //! is to be inserted before p) plus linear insertion
2380 //! to the elements with bigger keys than x.
2381 //!
2382 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2383 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
2384 {
2385 return dtl::force_copy<iterator>
2386 (m_flat_tree.insert_equal(dtl::force_copy<impl_const_iterator>(p)
2387 , boost::move(x)));
2388 }
2389
2390 //! <b>Effects</b>: Inserts a value move constructed from x in the container.
2391 //! p is a hint pointing to where the insert should start to search.
2392 //!
2393 //! <b>Returns</b>: An iterator pointing to the element with key equivalent
2394 //! to the key of x.
2395 //!
2396 //! <b>Complexity</b>: Logarithmic search time (constant time if the value
2397 //! is to be inserted before p) plus linear insertion
2398 //! to the elements with bigger keys than x.
2399 //!
2400 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2401 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x)
2402 {
2403 return dtl::force_copy<iterator>(
2404 m_flat_tree.insert_equal(dtl::force_copy<impl_const_iterator>(p), boost::move(x)));
2405 }
2406
2407 //! <b>Requires</b>: first, last are not iterators into *this.
2408 //!
2409 //! <b>Effects</b>: inserts each element from the range [first,last) .
2410 //!
2411 //! <b>Complexity</b>: N log(N).
2412 //!
2413 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2414 template <class InputIterator>
2415 BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
2416 { m_flat_tree.insert_equal(first, last); }
2417
2418 //! <b>Requires</b>: first, last are not iterators into *this.
2419 //!
2420 //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
2421 //!
2422 //! <b>Effects</b>: inserts each element from the range [first,last) if and only
2423 //! if there is no element with key equivalent to the key of that element. This
2424 //! function is more efficient than the normal range creation for ordered ranges.
2425 //!
2426 //! <b>Complexity</b>: Linear.
2427 //!
2428 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2429 //!
2430 //! <b>Note</b>: Non-standard extension.
2431 template <class InputIterator>
2432 BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last)
2433 { m_flat_tree.insert_equal(ordered_range, first, last); }
2434
2435#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2436 //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .
2437 //!
2438 //! <b>Complexity</b>: N log(N).
2439 //!
2440 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2441 BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
2442 {
2443 m_flat_tree.insert_equal( dtl::force<impl_initializer_list>(il).begin()
2444 , dtl::force<impl_initializer_list>(il).end());
2445 }
2446
2447 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
2448 //!
2449 //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
2450 //! if there is no element with key equivalent to the key of that element. This
2451 //! function is more efficient than the normal range creation for ordered ranges.
2452 //!
2453 //! <b>Complexity</b>: Linear.
2454 //!
2455 //! <b>Note</b>: If an element is inserted it might invalidate elements.
2456 //!
2457 //! <b>Note</b>: Non-standard extension.
2458 BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
2459 {
2460 m_flat_tree.insert_equal( ordered_range
2461 , dtl::force<impl_initializer_list>(il).begin()
2462 , dtl::force<impl_initializer_list>(il).end());
2463 }
2464#endif
2465
2466 //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
2467 //!
2468 //! <b>Effects</b>: Extracts each element in source and insert it into a using
2469 //! the comparison object of *this.
2470 //!
2471 //! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
2472 //! to those same elements but as members of *this. Iterators referring to the transferred
2473 //! elements will continue to refer to their elements, but they now behave as iterators into *this,
2474 //! not into source.
2475 //!
2476 //! <b>Throws</b>: Nothing unless the comparison object throws.
2477 //!
2478 //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
2479 template<class C2>
2480 BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
2481 { m_flat_tree.merge_equal(source.tree()); }
2482
2483 //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
2484 template<class C2>
2485 BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
2486 { return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
2487
2488 //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
2489 template<class C2>
2490 BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
2491 { m_flat_tree.merge_equal(source.tree()); }
2492
2493 //! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
2494 template<class C2>
2495 BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
2496 { return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
2497
2498 //! <b>Effects</b>: Erases the element pointed to by p.
2499 //!
2500 //! <b>Returns</b>: Returns an iterator pointing to the element immediately
2501 //! following q prior to the element being erased. If no such element exists,
2502 //! returns end().
2503 //!
2504 //! <b>Complexity</b>: Linear to the elements with keys bigger than p
2505 //!
2506 //! <b>Note</b>: Invalidates elements with keys
2507 //! not less than the erased element.
2508 BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p)
2509 {
2510 return dtl::force_copy<iterator>(
2511 m_flat_tree.erase(dtl::force_copy<impl_const_iterator>(p)));
2512 }
2513
2514 //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
2515 //!
2516 //! <b>Returns</b>: Returns the number of erased elements.
2517 //!
2518 //! <b>Complexity</b>: Logarithmic search time plus erasure time
2519 //! linear to the elements with bigger keys.
2520 BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x)
2521 { return m_flat_tree.erase(x); }
2522
2523 //! <b>Effects</b>: Erases all the elements in the range [first, last).
2524 //!
2525 //! <b>Returns</b>: Returns last.
2526 //!
2527 //! <b>Complexity</b>: size()*N where N is the distance from first to last.
2528 //!
2529 //! <b>Complexity</b>: Logarithmic search time plus erasure time
2530 //! linear to the elements with bigger keys.
2531 BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
2532 {
2533 return dtl::force_copy<iterator>
2534 (m_flat_tree.erase( dtl::force_copy<impl_const_iterator>(first)
2535 , dtl::force_copy<impl_const_iterator>(last)));
2536 }
2537
2538 //! <b>Effects</b>: Swaps the contents of *this and x.
2539 //!
2540 //! <b>Throws</b>: Nothing.
2541 //!
2542 //! <b>Complexity</b>: Constant.
2543 BOOST_CONTAINER_FORCEINLINE void swap(flat_multimap& x)
2544 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
2545 && boost::container::dtl::is_nothrow_swappable<Compare>::value )
2546 { m_flat_tree.swap(x.m_flat_tree); }
2547
2548 //! <b>Effects</b>: erase(a.begin(),a.end()).
2549 //!
2550 //! <b>Postcondition</b>: size() == 0.
2551 //!
2552 //! <b>Complexity</b>: linear in size().
2553 BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
2554 { m_flat_tree.clear(); }
2555
2556 //////////////////////////////////////////////
2557 //
2558 // observers
2559 //
2560 //////////////////////////////////////////////
2561
2562 //! <b>Effects</b>: Returns the comparison object out
2563 //! of which a was constructed.
2564 //!
2565 //! <b>Complexity</b>: Constant.
2566 BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const
2567 { return dtl::force_copy<key_compare>(m_flat_tree.key_comp()); }
2568
2569 //! <b>Effects</b>: Returns an object of value_compare constructed out
2570 //! of the comparison object.
2571 //!
2572 //! <b>Complexity</b>: Constant.
2573 BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
2574 { return value_compare(dtl::force_copy<key_compare>(m_flat_tree.key_comp())); }
2575
2576 //////////////////////////////////////////////
2577 //
2578 // map operations
2579 //
2580 //////////////////////////////////////////////
2581
2582 //! <b>Returns</b>: An iterator pointing to an element with the key
2583 //! equivalent to x, or end() if such an element is not found.
2584 //!
2585 //! <b>Complexity</b>: Logarithmic.
2586 BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& x)
2587 { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
2588
2589 //! <b>Returns</b>: An const_iterator pointing to an element with the key
2590 //! equivalent to x, or end() if such an element is not found.
2591 //!
2592 //! <b>Complexity</b>: Logarithmic.
2593 BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const
2594 { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
2595
2596 //! <b>Requires</b>: This overload is available only if
2597 //! key_compare::is_transparent exists.
2598 //!
2599 //! <b>Returns</b>: An iterator pointing to an element with the key
2600 //! equivalent to x, or end() if such an element is not found.
2601 //!
2602 //! <b>Complexity</b>: Logarithmic.
2603 template<class K>
2604 BOOST_CONTAINER_FORCEINLINE iterator find(const K& x)
2605 { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
2606
2607 //! <b>Requires</b>: This overload is available only if
2608 //! key_compare::is_transparent exists.
2609 //!
2610 //! <b>Returns</b>: An const_iterator pointing to an element with the key
2611 //! equivalent to x, or end() if such an element is not found.
2612 //!
2613 //! <b>Complexity</b>: Logarithmic.
2614 template<class K>
2615 BOOST_CONTAINER_FORCEINLINE const_iterator find(const K& x) const
2616 { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
2617
2618 //! <b>Returns</b>: The number of elements with key equivalent to x.
2619 //!
2620 //! <b>Complexity</b>: log(size())+count(k)
2621 BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
2622 { return m_flat_tree.count(x); }
2623
2624 //! <b>Requires</b>: This overload is available only if
2625 //! key_compare::is_transparent exists.
2626 //!
2627 //! <b>Returns</b>: The number of elements with key equivalent to x.
2628 //!
2629 //! <b>Complexity</b>: log(size())+count(k)
2630 template<class K>
2631 BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
2632 { return m_flat_tree.count(x); }
2633
2634 //! <b>Returns</b>: An iterator pointing to the first element with key not less
2635 //! than k, or a.end() if such an element is not found.
2636 //!
2637 //! <b>Complexity</b>: Logarithmic
2638 BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x)
2639 { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
2640
2641 //! <b>Returns</b>: An iterator pointing to the first element with key not less
2642 //! than k, or a.end() if such an element is not found.
2643 //!
2644 //! <b>Complexity</b>: Logarithmic
2645 BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const
2646 { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
2647
2648 //! <b>Requires</b>: This overload is available only if
2649 //! key_compare::is_transparent exists.
2650 //!
2651 //! <b>Returns</b>: An iterator pointing to the first element with key not less
2652 //! than k, or a.end() if such an element is not found.
2653 //!
2654 //! <b>Complexity</b>: Logarithmic
2655 template<class K>
2656 BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const K& x)
2657 { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
2658
2659 //! <b>Requires</b>: This overload is available only if
2660 //! key_compare::is_transparent exists.
2661 //!
2662 //! <b>Returns</b>: An iterator pointing to the first element with key not less
2663 //! than k, or a.end() if such an element is not found.
2664 //!
2665 //! <b>Complexity</b>: Logarithmic
2666 template<class K>
2667 BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const K& x) const
2668 { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
2669
2670 //! <b>Returns</b>: An iterator pointing to the first element with key not less
2671 //! than x, or end() if such an element is not found.
2672 //!
2673 //! <b>Complexity</b>: Logarithmic
2674 BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& x)
2675 {return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
2676
2677 //! <b>Returns</b>: A const iterator pointing to the first element with key
2678 //! not less than x, or end() if such an element is not found.
2679 //!
2680 //! <b>Complexity</b>: Logarithmic
2681 BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const
2682 { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
2683
2684 //! <b>Requires</b>: This overload is available only if
2685 //! key_compare::is_transparent exists.
2686 //!
2687 //! <b>Returns</b>: An iterator pointing to the first element with key not less
2688 //! than x, or end() if such an element is not found.
2689 //!
2690 //! <b>Complexity</b>: Logarithmic
2691 template<class K>
2692 BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const K& x)
2693 {return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
2694
2695 //! <b>Requires</b>: This overload is available only if
2696 //! key_compare::is_transparent exists.
2697 //!
2698 //! <b>Returns</b>: A const iterator pointing to the first element with key
2699 //! not less than x, or end() if such an element is not found.
2700 //!
2701 //! <b>Complexity</b>: Logarithmic
2702 template<class K>
2703 BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const K& x) const
2704 { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
2705
2706 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
2707 //!
2708 //! <b>Complexity</b>: Logarithmic
2709 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
2710 { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
2711
2712 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
2713 //!
2714 //! <b>Complexity</b>: Logarithmic
2715 BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
2716 { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
2717
2718 //! <b>Requires</b>: This overload is available only if
2719 //! key_compare::is_transparent exists.
2720 //!
2721 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
2722 //!
2723 //! <b>Complexity</b>: Logarithmic
2724 template<class K>
2725 BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
2726 { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
2727
2728 //! <b>Requires</b>: This overload is available only if
2729 //! key_compare::is_transparent exists.
2730 //!
2731 //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
2732 //!
2733 //! <b>Complexity</b>: Logarithmic
2734 template<class K>
2735 BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
2736 { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
2737
2738 //! <b>Effects</b>: Extracts the internal sequence container.
2739 //!
2740 //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
2741 //!
2742 //! <b>Postcondition</b>: this->empty()
2743 //!
2744 //! <b>Throws</b>: If secuence_type's move constructor throws
2745 BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
2746 {
2747 return boost::move(dtl::force<sequence_type>(m_flat_tree.get_sequence_ref()));
2748 }
2749
2750 //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
2751 //! one passed externally using the move assignment.
2752 //!
2753 //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
2754 //!
2755 //! <b>Throws</b>: If the comparison or the move constructor throws
2756 BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
2757 { this->m_flat_tree.adopt_sequence_equal(boost::move(dtl::force<impl_sequence_type>(seq))); }
2758
2759 //! <b>Requires</b>: seq shall be ordered according to this->compare().
2760 //!
2761 //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
2762 //! one passed externally using the move assignment.
2763 //!
2764 //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
2765 //!
2766 //! <b>Throws</b>: If the move assignment throws
2767 BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
2768 { this->m_flat_tree.adopt_sequence_equal(ordered_range_t(), boost::move(dtl::force<impl_sequence_type>(seq))); }
2769
2770 //! <b>Effects</b>: Returns true if x and y are equal
2771 //!
2772 //! <b>Complexity</b>: Linear to the number of elements in the container.
2773 BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_multimap& x, const flat_multimap& y)
2774 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
2775
2776 //! <b>Effects</b>: Returns true if x and y are unequal
2777 //!
2778 //! <b>Complexity</b>: Linear to the number of elements in the container.
2779 BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
2780 { return !(x == y); }
2781
2782 //! <b>Effects</b>: Returns true if x is less than y
2783 //!
2784 //! <b>Complexity</b>: Linear to the number of elements in the container.
2785 BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_multimap& x, const flat_multimap& y)
2786 { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
2787
2788 //! <b>Effects</b>: Returns true if x is greater than y
2789 //!
2790 //! <b>Complexity</b>: Linear to the number of elements in the container.
2791 BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_multimap& x, const flat_multimap& y)
2792 { return y < x; }
2793
2794 //! <b>Effects</b>: Returns true if x is equal or less than y
2795 //!
2796 //! <b>Complexity</b>: Linear to the number of elements in the container.
2797 BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_multimap& x, const flat_multimap& y)
2798 { return !(y < x); }
2799
2800 //! <b>Effects</b>: Returns true if x is equal or greater than y
2801 //!
2802 //! <b>Complexity</b>: Linear to the number of elements in the container.
2803 BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_multimap& x, const flat_multimap& y)
2804 { return !(x < y); }
2805
2806 //! <b>Effects</b>: x.swap(y)
2807 //!
2808 //! <b>Complexity</b>: Constant.
2809 BOOST_CONTAINER_FORCEINLINE friend void swap(flat_multimap& x, flat_multimap& y)
2810 { x.swap(y); }
2811};
2812
2813#if __cplusplus >= 201703L
2814
2815template <typename InputIterator>
2816flat_multimap(InputIterator, InputIterator) ->
2817 flat_multimap<typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
2818 , typename iterator_traits<InputIterator>::value_type::second_type>;
2819
2820template <typename InputIterator, typename Allocator>
2821flat_multimap(InputIterator, InputIterator, Allocator const&) ->
2822 flat_multimap<typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
2823 , typename iterator_traits<InputIterator>::value_type::second_type
2824 , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
2825 , Allocator>;
2826
2827template <typename InputIterator, typename Compare>
2828flat_multimap(InputIterator, InputIterator, Compare const&) ->
2829 flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
2830 , typename iterator_traits<InputIterator>::value_type::second_type
2831 , Compare>;
2832
2833template <typename InputIterator, typename Compare, typename Allocator>
2834flat_multimap(InputIterator, InputIterator, Compare const&, Allocator const&) ->
2835 flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
2836 , typename iterator_traits<InputIterator>::value_type::second_type
2837 , Compare
2838 , Allocator>;
2839
2840template <typename InputIterator>
2841flat_multimap(ordered_range_t, InputIterator, InputIterator) ->
2842 flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
2843 , typename iterator_traits<InputIterator>::value_type::second_type>;
2844
2845template <typename InputIterator, typename Allocator>
2846flat_multimap(ordered_range_t, InputIterator, InputIterator, Allocator const&) ->
2847 flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
2848 , typename iterator_traits<InputIterator>::value_type::second_type
2849 , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
2850 , Allocator>;
2851
2852template <typename InputIterator, typename Compare>
2853flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&) ->
2854 flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
2855 , typename iterator_traits<InputIterator>::value_type::second_type
2856 , Compare>;
2857
2858template <typename InputIterator, typename Compare, typename Allocator>
2859flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
2860 flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
2861 , typename iterator_traits<InputIterator>::value_type::second_type
2862 , Compare
2863 , Allocator>;
2864
2865#endif
2866
2867}}
2868
2869#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2870
2871namespace boost {
2872
2873//!has_trivial_destructor_after_move<> == true_type
2874//!specialization for optimizations
2875template <class Key, class T, class Compare, class AllocatorOrContainer>
2876struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, AllocatorOrContainer> >
2877{
2878 typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
2879 static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
2880 ::boost::has_trivial_destructor_after_move<pointer>::value &&
2881 ::boost::has_trivial_destructor_after_move<Compare>::value;
2882};
2883
2884} //namespace boost {
2885
2886#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2887
2888#include <boost/container/detail/config_end.hpp>
2889
2890#endif // BOOST_CONTAINER_FLAT_MAP_HPP