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