Chris@16
|
1 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@101
|
3 // (C) Copyright Ion Gaztanaga 2005-2014. Distributed under the Boost
|
Chris@16
|
4 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 //
|
Chris@16
|
7 // See http://www.boost.org/libs/container for documentation.
|
Chris@16
|
8 //
|
Chris@16
|
9 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
|
Chris@16
|
12 #define BOOST_CONTAINER_CONTAINER_VECTOR_HPP
|
Chris@16
|
13
|
Chris@101
|
14 #ifndef BOOST_CONFIG_HPP
|
Chris@101
|
15 # include <boost/config.hpp>
|
Chris@101
|
16 #endif
|
Chris@101
|
17
|
Chris@101
|
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
|
Chris@16
|
19 # pragma once
|
Chris@16
|
20 #endif
|
Chris@16
|
21
|
Chris@16
|
22 #include <boost/container/detail/config_begin.hpp>
|
Chris@16
|
23 #include <boost/container/detail/workaround.hpp>
|
Chris@101
|
24
|
Chris@101
|
25 // container
|
Chris@16
|
26 #include <boost/container/container_fwd.hpp>
|
Chris@101
|
27 #include <boost/container/allocator_traits.hpp>
|
Chris@101
|
28 #include <boost/container/new_allocator.hpp> //new_allocator
|
Chris@101
|
29 #include <boost/container/throw_exception.hpp>
|
Chris@101
|
30 // container detail
|
Chris@101
|
31 #include <boost/container/detail/advanced_insert_int.hpp>
|
Chris@101
|
32 #include <boost/container/detail/algorithm.hpp> //equal()
|
Chris@101
|
33 #include <boost/container/detail/alloc_helpers.hpp>
|
Chris@101
|
34 #include <boost/container/detail/allocation_type.hpp>
|
Chris@101
|
35 #include <boost/container/detail/copy_move_algo.hpp>
|
Chris@101
|
36 #include <boost/container/detail/destroyers.hpp>
|
Chris@101
|
37 #include <boost/container/detail/iterator.hpp>
|
Chris@101
|
38 #include <boost/container/detail/iterators.hpp>
|
Chris@101
|
39 #include <boost/container/detail/iterator_to_raw_pointer.hpp>
|
Chris@101
|
40 #include <boost/container/detail/mpl.hpp>
|
Chris@101
|
41 #include <boost/container/detail/next_capacity.hpp>
|
Chris@101
|
42 #include <boost/container/detail/to_raw_pointer.hpp>
|
Chris@101
|
43 #include <boost/container/detail/type_traits.hpp>
|
Chris@101
|
44 #include <boost/container/detail/version_type.hpp>
|
Chris@101
|
45 // intrusive
|
Chris@101
|
46 #include <boost/intrusive/pointer_traits.hpp>
|
Chris@101
|
47 // move
|
Chris@101
|
48 #include <boost/move/adl_move_swap.hpp>
|
Chris@101
|
49 #include <boost/move/iterator.hpp>
|
Chris@101
|
50 #include <boost/move/traits.hpp>
|
Chris@101
|
51 #include <boost/move/utility_core.hpp>
|
Chris@101
|
52 // move/detail
|
Chris@101
|
53 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
54 #include <boost/move/detail/fwd_macros.hpp>
|
Chris@101
|
55 #endif
|
Chris@101
|
56 #include <boost/move/detail/move_helpers.hpp>
|
Chris@101
|
57 // other
|
Chris@101
|
58 #include <boost/core/no_exceptions_support.hpp>
|
Chris@101
|
59 #include <boost/assert.hpp>
|
Chris@16
|
60
|
Chris@101
|
61 //std
|
Chris@101
|
62 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
Chris@101
|
63 #include <initializer_list> //for std::initializer_list
|
Chris@101
|
64 #endif
|
Chris@16
|
65
|
Chris@16
|
66 namespace boost {
|
Chris@16
|
67 namespace container {
|
Chris@16
|
68
|
Chris@101
|
69 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
70
|
Chris@16
|
71 //#define BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
|
Chris@16
|
72
|
Chris@16
|
73 namespace container_detail {
|
Chris@16
|
74
|
Chris@16
|
75 #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
|
Chris@16
|
76
|
Chris@16
|
77 template <class Pointer, bool IsConst>
|
Chris@16
|
78 class vec_iterator
|
Chris@16
|
79 {
|
Chris@16
|
80 public:
|
Chris@101
|
81 typedef std::random_access_iterator_tag iterator_category;
|
Chris@16
|
82 typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
|
Chris@16
|
83 typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
|
Chris@16
|
84 typedef typename if_c
|
Chris@16
|
85 < IsConst
|
Chris@16
|
86 , typename boost::intrusive::pointer_traits<Pointer>::template
|
Chris@16
|
87 rebind_pointer<const value_type>::type
|
Chris@16
|
88 , Pointer
|
Chris@16
|
89 >::type pointer;
|
Chris@101
|
90 typedef typename boost::intrusive::pointer_traits<pointer> ptr_traits;
|
Chris@101
|
91 typedef typename ptr_traits::reference reference;
|
Chris@16
|
92
|
Chris@101
|
93 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
94 private:
|
Chris@16
|
95 Pointer m_ptr;
|
Chris@16
|
96
|
Chris@16
|
97 public:
|
Chris@101
|
98 const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
99 { return m_ptr; }
|
Chris@16
|
100
|
Chris@101
|
101 Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
102 { return m_ptr; }
|
Chris@16
|
103
|
Chris@101
|
104 explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
105 : m_ptr(ptr)
|
Chris@16
|
106 {}
|
Chris@101
|
107 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
108
|
Chris@16
|
109 public:
|
Chris@16
|
110
|
Chris@16
|
111 //Constructors
|
Chris@101
|
112 vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
113 : m_ptr() //Value initialization to achieve "null iterators" (N3644)
|
Chris@16
|
114 {}
|
Chris@16
|
115
|
Chris@101
|
116 vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
117 : m_ptr(other.get_ptr())
|
Chris@16
|
118 {}
|
Chris@16
|
119
|
Chris@16
|
120 //Pointer like operators
|
Chris@101
|
121 reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
122 { return *m_ptr; }
|
Chris@16
|
123
|
Chris@101
|
124 pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
125 { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
|
Chris@16
|
126
|
Chris@101
|
127 reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
128 { return m_ptr[off]; }
|
Chris@16
|
129
|
Chris@16
|
130 //Increment / Decrement
|
Chris@101
|
131 vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
132 { ++m_ptr; return *this; }
|
Chris@16
|
133
|
Chris@101
|
134 vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
135 { return vec_iterator(m_ptr++); }
|
Chris@16
|
136
|
Chris@101
|
137 vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
138 { --m_ptr; return *this; }
|
Chris@16
|
139
|
Chris@101
|
140 vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
141 { return vec_iterator(m_ptr--); }
|
Chris@16
|
142
|
Chris@16
|
143 //Arithmetic
|
Chris@101
|
144 vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
145 { m_ptr += off; return *this; }
|
Chris@16
|
146
|
Chris@101
|
147 vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
148 { m_ptr -= off; return *this; }
|
Chris@16
|
149
|
Chris@101
|
150 friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
151 { return vec_iterator(x.m_ptr+off); }
|
Chris@16
|
152
|
Chris@101
|
153 friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
154 { right.m_ptr += off; return right; }
|
Chris@16
|
155
|
Chris@101
|
156 friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
157 { left.m_ptr -= off; return left; }
|
Chris@16
|
158
|
Chris@101
|
159 friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
160 { return left.m_ptr - right.m_ptr; }
|
Chris@16
|
161
|
Chris@16
|
162 //Comparison operators
|
Chris@101
|
163 friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
164 { return l.m_ptr == r.m_ptr; }
|
Chris@16
|
165
|
Chris@101
|
166 friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
167 { return l.m_ptr != r.m_ptr; }
|
Chris@16
|
168
|
Chris@101
|
169 friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
170 { return l.m_ptr < r.m_ptr; }
|
Chris@16
|
171
|
Chris@101
|
172 friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
173 { return l.m_ptr <= r.m_ptr; }
|
Chris@16
|
174
|
Chris@101
|
175 friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
176 { return l.m_ptr > r.m_ptr; }
|
Chris@16
|
177
|
Chris@101
|
178 friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
179 { return l.m_ptr >= r.m_ptr; }
|
Chris@16
|
180 };
|
Chris@16
|
181
|
Chris@16
|
182 } //namespace container_detail {
|
Chris@16
|
183
|
Chris@16
|
184 template<class Pointer, bool IsConst>
|
Chris@101
|
185 const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
186 { return it.get_ptr(); }
|
Chris@16
|
187
|
Chris@16
|
188 template<class Pointer, bool IsConst>
|
Chris@101
|
189 Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
190 { return it.get_ptr(); }
|
Chris@16
|
191
|
Chris@16
|
192 namespace container_detail {
|
Chris@16
|
193
|
Chris@16
|
194 #else //ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
|
Chris@16
|
195
|
Chris@16
|
196 template< class MaybeConstPointer
|
Chris@16
|
197 , bool ElementTypeIsConst
|
Chris@16
|
198 = is_const< typename boost::intrusive::pointer_traits<MaybeConstPointer>::element_type>::value >
|
Chris@16
|
199 struct vector_get_ptr_pointer_to_non_const
|
Chris@16
|
200 {
|
Chris@16
|
201 typedef MaybeConstPointer const_pointer;
|
Chris@16
|
202 typedef boost::intrusive::pointer_traits<const_pointer> pointer_traits_t;
|
Chris@16
|
203 typedef typename pointer_traits_t::element_type element_type;
|
Chris@16
|
204 typedef typename remove_const<element_type>::type non_const_element_type;
|
Chris@16
|
205 typedef typename pointer_traits_t
|
Chris@16
|
206 ::template rebind_pointer<non_const_element_type>::type return_type;
|
Chris@16
|
207
|
Chris@101
|
208 static return_type get_ptr(const const_pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
209 { return boost::intrusive::pointer_traits<return_type>::const_cast_from(ptr); }
|
Chris@16
|
210 };
|
Chris@16
|
211
|
Chris@16
|
212 template<class Pointer>
|
Chris@16
|
213 struct vector_get_ptr_pointer_to_non_const<Pointer, false>
|
Chris@16
|
214 {
|
Chris@16
|
215 typedef const Pointer & return_type;
|
Chris@101
|
216 static return_type get_ptr(const Pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
217 { return ptr; }
|
Chris@16
|
218 };
|
Chris@16
|
219
|
Chris@16
|
220 } //namespace container_detail {
|
Chris@16
|
221
|
Chris@16
|
222 template<class MaybeConstPointer>
|
Chris@16
|
223 typename container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::return_type
|
Chris@101
|
224 vector_iterator_get_ptr(const MaybeConstPointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
225 {
|
Chris@16
|
226 return container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::get_ptr(ptr);
|
Chris@16
|
227 }
|
Chris@16
|
228
|
Chris@16
|
229 namespace container_detail {
|
Chris@16
|
230
|
Chris@16
|
231 #endif //#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
|
Chris@16
|
232
|
Chris@101
|
233 struct uninitialized_size_t {};
|
Chris@101
|
234 static const uninitialized_size_t uninitialized_size = uninitialized_size_t();
|
Chris@101
|
235
|
Chris@101
|
236 template <class T>
|
Chris@101
|
237 struct vector_value_traits_base
|
Chris@101
|
238 {
|
Chris@101
|
239 static const bool trivial_dctr = is_trivially_destructible<T>::value;
|
Chris@101
|
240 static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
|
Chris@101
|
241 static const bool trivial_copy = is_trivially_copy_constructible<T>::value;
|
Chris@101
|
242 static const bool nothrow_copy = is_nothrow_copy_constructible<T>::value || trivial_copy;
|
Chris@101
|
243 static const bool trivial_assign = is_trivially_copy_assignable<T>::value;
|
Chris@101
|
244 static const bool nothrow_assign = is_nothrow_copy_assignable<T>::value || trivial_assign;
|
Chris@101
|
245 };
|
Chris@101
|
246
|
Chris@101
|
247
|
Chris@101
|
248 template <class Allocator>
|
Chris@16
|
249 struct vector_value_traits
|
Chris@101
|
250 : public vector_value_traits_base<typename Allocator::value_type>
|
Chris@16
|
251 {
|
Chris@101
|
252 typedef vector_value_traits_base<typename Allocator::value_type> base_t;
|
Chris@16
|
253 //This is the anti-exception array destructor
|
Chris@16
|
254 //to deallocate values already constructed
|
Chris@16
|
255 typedef typename container_detail::if_c
|
Chris@101
|
256 <base_t::trivial_dctr
|
Chris@16
|
257 ,container_detail::null_scoped_destructor_n<Allocator>
|
Chris@16
|
258 ,container_detail::scoped_destructor_n<Allocator>
|
Chris@16
|
259 >::type ArrayDestructor;
|
Chris@16
|
260 //This is the anti-exception array deallocator
|
Chris@101
|
261 typedef container_detail::scoped_array_deallocator<Allocator> ArrayDeallocator;
|
Chris@16
|
262 };
|
Chris@16
|
263
|
Chris@16
|
264 //!This struct deallocates and allocated memory
|
Chris@16
|
265 template < class Allocator
|
Chris@101
|
266 , class AllocatorVersion = typename container_detail::version<Allocator>::type
|
Chris@16
|
267 >
|
Chris@16
|
268 struct vector_alloc_holder
|
Chris@16
|
269 : public Allocator
|
Chris@16
|
270 {
|
Chris@16
|
271 private:
|
Chris@16
|
272 BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
|
Chris@16
|
273
|
Chris@16
|
274 public:
|
Chris@101
|
275 typedef Allocator allocator_type;
|
Chris@16
|
276 typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
|
Chris@16
|
277 typedef typename allocator_traits_type::pointer pointer;
|
Chris@16
|
278 typedef typename allocator_traits_type::size_type size_type;
|
Chris@16
|
279 typedef typename allocator_traits_type::value_type value_type;
|
Chris@16
|
280
|
Chris@101
|
281 static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator)
|
Chris@101
|
282 {
|
Chris@101
|
283 (void)propagate_allocator; (void)p; (void)to_alloc; (void)from_alloc;
|
Chris@101
|
284 return (!allocator_traits_type::is_partially_propagable::value ||
|
Chris@101
|
285 !allocator_traits_type::storage_is_unpropagable(from_alloc, p)) &&
|
Chris@101
|
286 (propagate_allocator || allocator_traits_type::equal(from_alloc, to_alloc));
|
Chris@101
|
287 }
|
Chris@101
|
288
|
Chris@101
|
289 static bool are_swap_propagable(const allocator_type &l_a, pointer l_p, const allocator_type &r_a, pointer r_p, bool const propagate_allocator)
|
Chris@101
|
290 {
|
Chris@101
|
291 (void)propagate_allocator; (void)l_p; (void)r_p; (void)l_a; (void)r_a;
|
Chris@101
|
292 return (!allocator_traits_type::is_partially_propagable::value ||
|
Chris@101
|
293 (!allocator_traits_type::storage_is_unpropagable(r_a, r_p) &&
|
Chris@101
|
294 !allocator_traits_type::storage_is_unpropagable(l_a, l_p))
|
Chris@101
|
295 ) && (propagate_allocator || allocator_traits_type::equal(l_a, r_a));
|
Chris@101
|
296 }
|
Chris@101
|
297
|
Chris@16
|
298 //Constructor, does not throw
|
Chris@16
|
299 vector_alloc_holder()
|
Chris@101
|
300 BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
|
Chris@16
|
301 : Allocator(), m_start(), m_size(), m_capacity()
|
Chris@16
|
302 {}
|
Chris@16
|
303
|
Chris@16
|
304 //Constructor, does not throw
|
Chris@16
|
305 template<class AllocConvertible>
|
Chris@101
|
306 explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
307 : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
|
Chris@16
|
308 {}
|
Chris@16
|
309
|
Chris@16
|
310 //Constructor, does not throw
|
Chris@16
|
311 template<class AllocConvertible>
|
Chris@101
|
312 vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
|
Chris@16
|
313 : Allocator(boost::forward<AllocConvertible>(a))
|
Chris@16
|
314 , m_start()
|
Chris@16
|
315 , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
|
Chris@16
|
316 , m_capacity()
|
Chris@16
|
317 {
|
Chris@16
|
318 if(initial_size){
|
Chris@101
|
319 pointer reuse = 0;
|
Chris@101
|
320 m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse);
|
Chris@16
|
321 }
|
Chris@16
|
322 }
|
Chris@16
|
323
|
Chris@16
|
324 //Constructor, does not throw
|
Chris@101
|
325 vector_alloc_holder(uninitialized_size_t, size_type initial_size)
|
Chris@16
|
326 : Allocator()
|
Chris@16
|
327 , m_start()
|
Chris@16
|
328 , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
|
Chris@16
|
329 , m_capacity()
|
Chris@16
|
330 {
|
Chris@16
|
331 if(initial_size){
|
Chris@101
|
332 pointer reuse = 0;
|
Chris@101
|
333 m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse);
|
Chris@16
|
334 }
|
Chris@16
|
335 }
|
Chris@16
|
336
|
Chris@101
|
337 vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
338 : Allocator(BOOST_MOVE_BASE(Allocator, holder))
|
Chris@16
|
339 , m_start(holder.m_start)
|
Chris@16
|
340 , m_size(holder.m_size)
|
Chris@16
|
341 , m_capacity(holder.m_capacity)
|
Chris@16
|
342 {
|
Chris@16
|
343 holder.m_start = pointer();
|
Chris@16
|
344 holder.m_size = holder.m_capacity = 0;
|
Chris@16
|
345 }
|
Chris@16
|
346
|
Chris@101
|
347 vector_alloc_holder(pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder)
|
Chris@101
|
348 : Allocator(BOOST_MOVE_BASE(Allocator, holder))
|
Chris@101
|
349 , m_start(p)
|
Chris@101
|
350 , m_size(holder.m_size)
|
Chris@101
|
351 , m_capacity(capacity)
|
Chris@16
|
352 {
|
Chris@101
|
353 allocator_type &this_alloc = this->alloc();
|
Chris@101
|
354 allocator_type &x_alloc = holder.alloc();
|
Chris@101
|
355 if(this->is_propagable_from(x_alloc, holder.start(), this_alloc, true)){
|
Chris@101
|
356 if(this->m_capacity){
|
Chris@101
|
357 this->alloc().deallocate(this->m_start, this->m_capacity);
|
Chris@101
|
358 }
|
Chris@101
|
359 m_start = holder.m_start;
|
Chris@101
|
360 m_capacity = holder.m_capacity;
|
Chris@101
|
361 holder.m_start = pointer();
|
Chris@101
|
362 holder.m_capacity = holder.m_size = 0;
|
Chris@101
|
363 }
|
Chris@101
|
364 else if(this->m_capacity < holder.m_size){
|
Chris@101
|
365 size_type const n = holder.m_size;
|
Chris@101
|
366 pointer reuse = pointer();
|
Chris@101
|
367 m_start = this->allocation_command(allocate_new, n, m_capacity = n, reuse);
|
Chris@101
|
368 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
369 this->num_alloc += n != 0;
|
Chris@101
|
370 #endif
|
Chris@16
|
371 }
|
Chris@16
|
372 }
|
Chris@16
|
373
|
Chris@101
|
374 vector_alloc_holder(pointer p, size_type n)
|
Chris@101
|
375 BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
|
Chris@101
|
376 : Allocator()
|
Chris@101
|
377 , m_start(p)
|
Chris@101
|
378 , m_size()
|
Chris@101
|
379 , m_capacity(n)
|
Chris@101
|
380 {}
|
Chris@16
|
381
|
Chris@101
|
382 template<class AllocFwd>
|
Chris@101
|
383 vector_alloc_holder(pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
|
Chris@101
|
384 : Allocator(::boost::forward<AllocFwd>(a))
|
Chris@101
|
385 , m_start(p)
|
Chris@101
|
386 , m_size()
|
Chris@101
|
387 , m_capacity(n)
|
Chris@101
|
388 {}
|
Chris@101
|
389
|
Chris@101
|
390 ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
391 {
|
Chris@16
|
392 if(this->m_capacity){
|
Chris@16
|
393 this->alloc().deallocate(this->m_start, this->m_capacity);
|
Chris@16
|
394 }
|
Chris@16
|
395 }
|
Chris@16
|
396
|
Chris@101
|
397 pointer allocation_command(boost::container::allocation_type command,
|
Chris@101
|
398 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
|
Chris@16
|
399 {
|
Chris@101
|
400 typedef typename container_detail::version<Allocator>::type alloc_version;
|
Chris@101
|
401 return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse);
|
Chris@101
|
402 }
|
Chris@101
|
403
|
Chris@101
|
404 bool try_expand_fwd(size_type at_least)
|
Chris@101
|
405 {
|
Chris@101
|
406 //There is not enough memory, try to expand the old one
|
Chris@101
|
407 const size_type new_cap = this->capacity() + at_least;
|
Chris@101
|
408 size_type real_cap = new_cap;
|
Chris@101
|
409 pointer reuse = this->start();
|
Chris@101
|
410 bool const success = !!this->allocation_command(expand_fwd, new_cap, real_cap, reuse);
|
Chris@101
|
411 //Check for forward expansion
|
Chris@101
|
412 if(success){
|
Chris@101
|
413 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
414 ++this->num_expand_fwd;
|
Chris@101
|
415 #endif
|
Chris@101
|
416 this->capacity(real_cap);
|
Chris@101
|
417 }
|
Chris@101
|
418 return success;
|
Chris@16
|
419 }
|
Chris@16
|
420
|
Chris@16
|
421 size_type next_capacity(size_type additional_objects) const
|
Chris@16
|
422 {
|
Chris@101
|
423 return next_capacity_calculator
|
Chris@101
|
424 <size_type, NextCapacityDouble //NextCapacity60Percent
|
Chris@101
|
425 >::get( allocator_traits_type::max_size(this->alloc())
|
Chris@101
|
426 , this->m_capacity, additional_objects );
|
Chris@16
|
427 }
|
Chris@16
|
428
|
Chris@16
|
429 pointer m_start;
|
Chris@16
|
430 size_type m_size;
|
Chris@16
|
431 size_type m_capacity;
|
Chris@16
|
432
|
Chris@101
|
433 void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
434 {
|
Chris@101
|
435 boost::adl_move_swap(this->m_start, x.m_start);
|
Chris@101
|
436 boost::adl_move_swap(this->m_size, x.m_size);
|
Chris@101
|
437 boost::adl_move_swap(this->m_capacity, x.m_capacity);
|
Chris@16
|
438 }
|
Chris@16
|
439
|
Chris@101
|
440 void steal_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
441 {
|
Chris@16
|
442 this->m_start = x.m_start;
|
Chris@16
|
443 this->m_size = x.m_size;
|
Chris@16
|
444 this->m_capacity = x.m_capacity;
|
Chris@16
|
445 x.m_start = pointer();
|
Chris@16
|
446 x.m_size = x.m_capacity = 0;
|
Chris@16
|
447 }
|
Chris@16
|
448
|
Chris@101
|
449 Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
450 { return *this; }
|
Chris@16
|
451
|
Chris@101
|
452 const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
453 { return *this; }
|
Chris@16
|
454
|
Chris@101
|
455 const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW { return m_start; }
|
Chris@101
|
456 const size_type &capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_capacity; }
|
Chris@101
|
457 void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW { m_start = p; }
|
Chris@101
|
458 void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW { m_capacity = c; }
|
Chris@101
|
459
|
Chris@101
|
460 private:
|
Chris@101
|
461 void priv_first_allocation(size_type cap)
|
Chris@101
|
462 {
|
Chris@101
|
463 if(cap){
|
Chris@101
|
464 pointer reuse = 0;
|
Chris@101
|
465 m_start = this->allocation_command(allocate_new, cap, cap, reuse);
|
Chris@101
|
466 m_capacity = cap;
|
Chris@101
|
467 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
468 ++this->num_alloc;
|
Chris@101
|
469 #endif
|
Chris@101
|
470 }
|
Chris@101
|
471 }
|
Chris@101
|
472
|
Chris@101
|
473 pointer priv_allocation_command(version_1, boost::container::allocation_type command,
|
Chris@101
|
474 size_type ,
|
Chris@101
|
475 size_type &prefer_in_recvd_out_size,
|
Chris@101
|
476 pointer &reuse)
|
Chris@101
|
477 {
|
Chris@101
|
478 (void)command;
|
Chris@101
|
479 BOOST_ASSERT( (command & allocate_new));
|
Chris@101
|
480 BOOST_ASSERT(!(command & nothrow_allocation));
|
Chris@101
|
481 pointer const p = allocator_traits_type::allocate(this->alloc(), prefer_in_recvd_out_size, reuse);
|
Chris@101
|
482 reuse = pointer();
|
Chris@101
|
483 return p;
|
Chris@101
|
484 }
|
Chris@101
|
485
|
Chris@101
|
486 pointer priv_allocation_command(version_2, boost::container::allocation_type command,
|
Chris@101
|
487 size_type limit_size,
|
Chris@101
|
488 size_type &prefer_in_recvd_out_size,
|
Chris@101
|
489 pointer &reuse)
|
Chris@101
|
490 {
|
Chris@101
|
491 return this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
|
Chris@101
|
492 }
|
Chris@16
|
493 };
|
Chris@16
|
494
|
Chris@16
|
495 //!This struct deallocates and allocated memory
|
Chris@16
|
496 template <class Allocator>
|
Chris@101
|
497 struct vector_alloc_holder<Allocator, version_0>
|
Chris@16
|
498 : public Allocator
|
Chris@16
|
499 {
|
Chris@16
|
500 private:
|
Chris@16
|
501 BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
|
Chris@16
|
502
|
Chris@16
|
503 public:
|
Chris@16
|
504 typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
|
Chris@16
|
505 typedef typename allocator_traits_type::pointer pointer;
|
Chris@16
|
506 typedef typename allocator_traits_type::size_type size_type;
|
Chris@16
|
507 typedef typename allocator_traits_type::value_type value_type;
|
Chris@16
|
508
|
Chris@16
|
509 template <class OtherAllocator, class OtherAllocatorVersion>
|
Chris@16
|
510 friend struct vector_alloc_holder;
|
Chris@16
|
511
|
Chris@16
|
512 //Constructor, does not throw
|
Chris@16
|
513 vector_alloc_holder()
|
Chris@101
|
514 BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
|
Chris@16
|
515 : Allocator(), m_size()
|
Chris@16
|
516 {}
|
Chris@16
|
517
|
Chris@16
|
518 //Constructor, does not throw
|
Chris@16
|
519 template<class AllocConvertible>
|
Chris@101
|
520 explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
521 : Allocator(boost::forward<AllocConvertible>(a)), m_size()
|
Chris@16
|
522 {}
|
Chris@16
|
523
|
Chris@16
|
524 //Constructor, does not throw
|
Chris@16
|
525 template<class AllocConvertible>
|
Chris@101
|
526 vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
|
Chris@16
|
527 : Allocator(boost::forward<AllocConvertible>(a))
|
Chris@16
|
528 , m_size(initial_size) //Size is initialized here...
|
Chris@16
|
529 {
|
Chris@16
|
530 //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
|
Chris@101
|
531 this->priv_first_allocation(initial_size);
|
Chris@16
|
532 }
|
Chris@16
|
533
|
Chris@16
|
534 //Constructor, does not throw
|
Chris@101
|
535 vector_alloc_holder(uninitialized_size_t, size_type initial_size)
|
Chris@16
|
536 : Allocator()
|
Chris@16
|
537 , m_size(initial_size) //Size is initialized here...
|
Chris@16
|
538 {
|
Chris@16
|
539 //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
|
Chris@101
|
540 this->priv_first_allocation(initial_size);
|
Chris@16
|
541 }
|
Chris@16
|
542
|
Chris@16
|
543 vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
|
Chris@101
|
544 : Allocator(BOOST_MOVE_BASE(Allocator, holder))
|
Chris@16
|
545 , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
|
Chris@16
|
546 {
|
Chris@16
|
547 ::boost::container::uninitialized_move_alloc_n
|
Chris@16
|
548 (this->alloc(), container_detail::to_raw_pointer(holder.start()), m_size, container_detail::to_raw_pointer(this->start()));
|
Chris@16
|
549 }
|
Chris@16
|
550
|
Chris@16
|
551 template<class OtherAllocator, class OtherAllocatorVersion>
|
Chris@16
|
552 vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> BOOST_RV_REF_END holder)
|
Chris@16
|
553 : Allocator()
|
Chris@16
|
554 , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
|
Chris@16
|
555 {
|
Chris@16
|
556 //Different allocator type so we must check we have enough storage
|
Chris@16
|
557 const size_type n = holder.m_size;
|
Chris@101
|
558 this->priv_first_allocation(n);
|
Chris@16
|
559 ::boost::container::uninitialized_move_alloc_n
|
Chris@16
|
560 (this->alloc(), container_detail::to_raw_pointer(holder.start()), n, container_detail::to_raw_pointer(this->start()));
|
Chris@16
|
561 }
|
Chris@16
|
562
|
Chris@101
|
563 void priv_first_allocation(size_type cap)
|
Chris@16
|
564 {
|
Chris@16
|
565 if(cap > Allocator::internal_capacity){
|
Chris@16
|
566 throw_bad_alloc();
|
Chris@16
|
567 }
|
Chris@16
|
568 }
|
Chris@16
|
569
|
Chris@101
|
570 void deep_swap(vector_alloc_holder &x)
|
Chris@16
|
571 {
|
Chris@101
|
572 this->priv_deep_swap(x);
|
Chris@16
|
573 }
|
Chris@16
|
574
|
Chris@16
|
575 template<class OtherAllocator, class OtherAllocatorVersion>
|
Chris@101
|
576 void deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
|
Chris@16
|
577 {
|
Chris@16
|
578 if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){
|
Chris@16
|
579 throw_bad_alloc();
|
Chris@16
|
580 }
|
Chris@101
|
581 this->priv_deep_swap(x);
|
Chris@16
|
582 }
|
Chris@16
|
583
|
Chris@101
|
584 void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
585 { //Containers with version 0 allocators can't be moved without moving elements one by one
|
Chris@16
|
586 throw_bad_alloc();
|
Chris@16
|
587 }
|
Chris@16
|
588
|
Chris@101
|
589
|
Chris@101
|
590 void steal_resources(vector_alloc_holder &)
|
Chris@101
|
591 { //Containers with version 0 allocators can't be moved without moving elements one by one
|
Chris@101
|
592 throw_bad_alloc();
|
Chris@101
|
593 }
|
Chris@101
|
594
|
Chris@101
|
595 Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
596 { return *this; }
|
Chris@16
|
597
|
Chris@101
|
598 const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
599 { return *this; }
|
Chris@16
|
600
|
Chris@101
|
601 bool try_expand_fwd(size_type at_least)
|
Chris@101
|
602 { return !at_least; }
|
Chris@101
|
603
|
Chris@101
|
604 pointer start() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_storage(); }
|
Chris@101
|
605 size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_capacity; }
|
Chris@16
|
606 size_type m_size;
|
Chris@16
|
607
|
Chris@16
|
608 private:
|
Chris@16
|
609
|
Chris@16
|
610 template<class OtherAllocator, class OtherAllocatorVersion>
|
Chris@101
|
611 void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
|
Chris@16
|
612 {
|
Chris@101
|
613 const size_type MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity;
|
Chris@16
|
614 value_type *const first_this = container_detail::to_raw_pointer(this->start());
|
Chris@16
|
615 value_type *const first_x = container_detail::to_raw_pointer(x.start());
|
Chris@16
|
616
|
Chris@16
|
617 if(this->m_size < x.m_size){
|
Chris@16
|
618 boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size);
|
Chris@16
|
619 }
|
Chris@16
|
620 else{
|
Chris@16
|
621 boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_x, x.m_size, first_this, this->m_size);
|
Chris@16
|
622 }
|
Chris@101
|
623 boost::adl_move_swap(this->m_size, x.m_size);
|
Chris@16
|
624 }
|
Chris@16
|
625 };
|
Chris@16
|
626
|
Chris@16
|
627 } //namespace container_detail {
|
Chris@16
|
628
|
Chris@101
|
629 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
630
|
Chris@16
|
631 //! A vector is a sequence that supports random access to elements, constant
|
Chris@16
|
632 //! time insertion and removal of elements at the end, and linear time insertion
|
Chris@16
|
633 //! and removal of elements at the beginning or in the middle. The number of
|
Chris@16
|
634 //! elements in a vector may vary dynamically; memory management is automatic.
|
Chris@101
|
635 //!
|
Chris@101
|
636 //! \tparam T The type of object that is stored in the vector
|
Chris@101
|
637 //! \tparam Allocator The allocator used for all internal memory management
|
Chris@101
|
638 template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) >
|
Chris@16
|
639 class vector
|
Chris@16
|
640 {
|
Chris@101
|
641 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@101
|
642
|
Chris@101
|
643 typedef typename container_detail::version<Allocator>::type alloc_version;
|
Chris@101
|
644 typedef boost::container::container_detail::vector_alloc_holder<Allocator> alloc_holder_t;
|
Chris@101
|
645 alloc_holder_t m_holder;
|
Chris@16
|
646 typedef allocator_traits<Allocator> allocator_traits_type;
|
Chris@16
|
647 template <class U, class UAllocator>
|
Chris@16
|
648 friend class vector;
|
Chris@16
|
649
|
Chris@101
|
650 typedef typename allocator_traits_type::pointer pointer_impl;
|
Chris@16
|
651 typedef container_detail::vec_iterator<pointer_impl, false> iterator_impl;
|
Chris@16
|
652 typedef container_detail::vec_iterator<pointer_impl, true > const_iterator_impl;
|
Chris@16
|
653
|
Chris@101
|
654 protected:
|
Chris@101
|
655 static bool is_propagable_from(const Allocator &from_alloc, pointer_impl p, const Allocator &to_alloc, bool const propagate_allocator)
|
Chris@101
|
656 { return alloc_holder_t::is_propagable_from(from_alloc, p, to_alloc, propagate_allocator); }
|
Chris@101
|
657
|
Chris@101
|
658 static bool are_swap_propagable( const Allocator &l_a, pointer_impl l_p
|
Chris@101
|
659 , const Allocator &r_a, pointer_impl r_p, bool const propagate_allocator)
|
Chris@101
|
660 { return alloc_holder_t::are_swap_propagable(l_a, l_p, r_a, r_p, propagate_allocator); }
|
Chris@101
|
661
|
Chris@101
|
662 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
663 public:
|
Chris@16
|
664 //////////////////////////////////////////////
|
Chris@16
|
665 //
|
Chris@16
|
666 // types
|
Chris@16
|
667 //
|
Chris@16
|
668 //////////////////////////////////////////////
|
Chris@16
|
669
|
Chris@16
|
670 typedef T value_type;
|
Chris@16
|
671 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
|
Chris@16
|
672 typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
|
Chris@16
|
673 typedef typename ::boost::container::allocator_traits<Allocator>::reference reference;
|
Chris@16
|
674 typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
|
Chris@16
|
675 typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
|
Chris@16
|
676 typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
|
Chris@16
|
677 typedef Allocator allocator_type;
|
Chris@16
|
678 typedef Allocator stored_allocator_type;
|
Chris@101
|
679 #if defined BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
|
Chris@16
|
680 typedef BOOST_CONTAINER_IMPDEF(pointer) iterator;
|
Chris@16
|
681 typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator;
|
Chris@16
|
682 #else
|
Chris@16
|
683 typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
|
Chris@16
|
684 typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
|
Chris@16
|
685 #endif
|
Chris@101
|
686 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
|
Chris@101
|
687 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
|
Chris@16
|
688
|
Chris@101
|
689 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
690 private:
|
Chris@16
|
691 BOOST_COPYABLE_AND_MOVABLE(vector)
|
Chris@101
|
692 typedef container_detail::vector_value_traits<Allocator> value_traits;
|
Chris@101
|
693 typedef constant_iterator<T, difference_type> cvalue_iterator;
|
Chris@16
|
694
|
Chris@101
|
695 protected:
|
Chris@16
|
696
|
Chris@101
|
697 void steal_resources(vector &x)
|
Chris@101
|
698 { return this->m_holder.steal_resources(x.m_holder); }
|
Chris@101
|
699
|
Chris@101
|
700 struct initial_capacity_t{};
|
Chris@101
|
701 template<class AllocFwd>
|
Chris@101
|
702 vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a)
|
Chris@101
|
703 : m_holder(initial_memory, capacity, ::boost::forward<AllocFwd>(a))
|
Chris@101
|
704 {}
|
Chris@101
|
705
|
Chris@101
|
706 vector(initial_capacity_t, pointer initial_memory, size_type capacity)
|
Chris@101
|
707 : m_holder(initial_memory, capacity)
|
Chris@101
|
708 {}
|
Chris@101
|
709
|
Chris@101
|
710 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
711
|
Chris@16
|
712 public:
|
Chris@16
|
713 //////////////////////////////////////////////
|
Chris@16
|
714 //
|
Chris@16
|
715 // construct/copy/destroy
|
Chris@16
|
716 //
|
Chris@16
|
717 //////////////////////////////////////////////
|
Chris@16
|
718
|
Chris@16
|
719 //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
|
Chris@16
|
720 //!
|
Chris@101
|
721 //! <b>Throws</b>: Nothing.
|
Chris@16
|
722 //!
|
Chris@16
|
723 //! <b>Complexity</b>: Constant.
|
Chris@101
|
724 vector() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
725 : m_holder()
|
Chris@16
|
726 {}
|
Chris@16
|
727
|
Chris@16
|
728 //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
|
Chris@16
|
729 //!
|
Chris@16
|
730 //! <b>Throws</b>: Nothing
|
Chris@16
|
731 //!
|
Chris@16
|
732 //! <b>Complexity</b>: Constant.
|
Chris@101
|
733 explicit vector(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
734 : m_holder(a)
|
Chris@16
|
735 {}
|
Chris@16
|
736
|
Chris@101
|
737 //! <b>Effects</b>: Constructs a vector and inserts n value initialized values.
|
Chris@16
|
738 //!
|
Chris@101
|
739 //! <b>Throws</b>: If allocator_type's allocation
|
Chris@101
|
740 //! throws or T's value initialization throws.
|
Chris@16
|
741 //!
|
Chris@16
|
742 //! <b>Complexity</b>: Linear to n.
|
Chris@16
|
743 explicit vector(size_type n)
|
Chris@101
|
744 : m_holder(container_detail::uninitialized_size, n)
|
Chris@16
|
745 {
|
Chris@101
|
746 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
747 this->num_alloc += n != 0;
|
Chris@101
|
748 #endif
|
Chris@16
|
749 boost::container::uninitialized_value_init_alloc_n
|
Chris@16
|
750 (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@16
|
751 }
|
Chris@16
|
752
|
Chris@16
|
753 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
|
Chris@16
|
754 //! and inserts n default initialized values.
|
Chris@16
|
755 //!
|
Chris@101
|
756 //! <b>Throws</b>: If allocator_type's allocation
|
Chris@101
|
757 //! throws or T's default initialization throws.
|
Chris@16
|
758 //!
|
Chris@16
|
759 //! <b>Complexity</b>: Linear to n.
|
Chris@16
|
760 //!
|
Chris@16
|
761 //! <b>Note</b>: Non-standard extension
|
Chris@101
|
762 vector(size_type n, default_init_t)
|
Chris@101
|
763 : m_holder(container_detail::uninitialized_size, n)
|
Chris@16
|
764 {
|
Chris@101
|
765 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
766 this->num_alloc += n != 0;
|
Chris@101
|
767 #endif
|
Chris@101
|
768 boost::container::uninitialized_default_init_alloc_n
|
Chris@101
|
769 (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@101
|
770 }
|
Chris@101
|
771
|
Chris@101
|
772 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
|
Chris@101
|
773 //! and inserts n value initialized values.
|
Chris@101
|
774 //!
|
Chris@101
|
775 //! <b>Throws</b>: If allocator_type's allocation
|
Chris@101
|
776 //! throws or T's value initialization throws.
|
Chris@101
|
777 //!
|
Chris@101
|
778 //! <b>Complexity</b>: Linear to n.
|
Chris@101
|
779 explicit vector(size_type n, const allocator_type &a)
|
Chris@101
|
780 : m_holder(container_detail::uninitialized_size, a, n)
|
Chris@101
|
781 {
|
Chris@101
|
782 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
783 this->num_alloc += n != 0;
|
Chris@101
|
784 #endif
|
Chris@101
|
785 boost::container::uninitialized_value_init_alloc_n
|
Chris@101
|
786 (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@101
|
787 }
|
Chris@101
|
788
|
Chris@101
|
789 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
|
Chris@101
|
790 //! and inserts n default initialized values.
|
Chris@101
|
791 //!
|
Chris@101
|
792 //! <b>Throws</b>: If allocator_type's allocation
|
Chris@101
|
793 //! throws or T's default initialization throws.
|
Chris@101
|
794 //!
|
Chris@101
|
795 //! <b>Complexity</b>: Linear to n.
|
Chris@101
|
796 //!
|
Chris@101
|
797 //! <b>Note</b>: Non-standard extension
|
Chris@101
|
798 vector(size_type n, default_init_t, const allocator_type &a)
|
Chris@101
|
799 : m_holder(container_detail::uninitialized_size, a, n)
|
Chris@101
|
800 {
|
Chris@101
|
801 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
802 this->num_alloc += n != 0;
|
Chris@101
|
803 #endif
|
Chris@16
|
804 boost::container::uninitialized_default_init_alloc_n
|
Chris@16
|
805 (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@16
|
806 }
|
Chris@16
|
807
|
Chris@16
|
808 //! <b>Effects</b>: Constructs a vector
|
Chris@16
|
809 //! and inserts n copies of value.
|
Chris@16
|
810 //!
|
Chris@101
|
811 //! <b>Throws</b>: If allocator_type's allocation
|
Chris@16
|
812 //! throws or T's copy constructor throws.
|
Chris@16
|
813 //!
|
Chris@16
|
814 //! <b>Complexity</b>: Linear to n.
|
Chris@16
|
815 vector(size_type n, const T& value)
|
Chris@101
|
816 : m_holder(container_detail::uninitialized_size, n)
|
Chris@16
|
817 {
|
Chris@101
|
818 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
819 this->num_alloc += n != 0;
|
Chris@101
|
820 #endif
|
Chris@16
|
821 boost::container::uninitialized_fill_alloc_n
|
Chris@16
|
822 (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@16
|
823 }
|
Chris@16
|
824
|
Chris@16
|
825 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
|
Chris@16
|
826 //! and inserts n copies of value.
|
Chris@16
|
827 //!
|
Chris@16
|
828 //! <b>Throws</b>: If allocation
|
Chris@16
|
829 //! throws or T's copy constructor throws.
|
Chris@16
|
830 //!
|
Chris@16
|
831 //! <b>Complexity</b>: Linear to n.
|
Chris@16
|
832 vector(size_type n, const T& value, const allocator_type& a)
|
Chris@101
|
833 : m_holder(container_detail::uninitialized_size, a, n)
|
Chris@16
|
834 {
|
Chris@101
|
835 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
836 this->num_alloc += n != 0;
|
Chris@101
|
837 #endif
|
Chris@16
|
838 boost::container::uninitialized_fill_alloc_n
|
Chris@16
|
839 (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@16
|
840 }
|
Chris@16
|
841
|
Chris@16
|
842 //! <b>Effects</b>: Constructs a vector
|
Chris@16
|
843 //! and inserts a copy of the range [first, last) in the vector.
|
Chris@16
|
844 //!
|
Chris@101
|
845 //! <b>Throws</b>: If allocator_type's allocation
|
Chris@101
|
846 //! throws or T's constructor taking a dereferenced InIt throws.
|
Chris@16
|
847 //!
|
Chris@16
|
848 //! <b>Complexity</b>: Linear to the range [first, last).
|
Chris@16
|
849 template <class InIt>
|
Chris@16
|
850 vector(InIt first, InIt last)
|
Chris@16
|
851 : m_holder()
|
Chris@101
|
852 { this->assign(first, last); }
|
Chris@16
|
853
|
Chris@16
|
854 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
|
Chris@16
|
855 //! and inserts a copy of the range [first, last) in the vector.
|
Chris@16
|
856 //!
|
Chris@101
|
857 //! <b>Throws</b>: If allocator_type's allocation
|
Chris@101
|
858 //! throws or T's constructor taking a dereferenced InIt throws.
|
Chris@16
|
859 //!
|
Chris@16
|
860 //! <b>Complexity</b>: Linear to the range [first, last).
|
Chris@16
|
861 template <class InIt>
|
Chris@16
|
862 vector(InIt first, InIt last, const allocator_type& a)
|
Chris@16
|
863 : m_holder(a)
|
Chris@101
|
864 { this->assign(first, last); }
|
Chris@16
|
865
|
Chris@16
|
866 //! <b>Effects</b>: Copy constructs a vector.
|
Chris@16
|
867 //!
|
Chris@16
|
868 //! <b>Postcondition</b>: x == *this.
|
Chris@16
|
869 //!
|
Chris@101
|
870 //! <b>Throws</b>: If allocator_type's allocation
|
Chris@16
|
871 //! throws or T's copy constructor throws.
|
Chris@16
|
872 //!
|
Chris@16
|
873 //! <b>Complexity</b>: Linear to the elements x contains.
|
Chris@16
|
874 vector(const vector &x)
|
Chris@101
|
875 : m_holder( container_detail::uninitialized_size
|
Chris@101
|
876 , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc())
|
Chris@101
|
877 , x.size())
|
Chris@16
|
878 {
|
Chris@101
|
879 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
880 this->num_alloc += x.size() != 0;
|
Chris@101
|
881 #endif
|
Chris@16
|
882 ::boost::container::uninitialized_copy_alloc_n
|
Chris@16
|
883 ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
|
Chris@16
|
884 , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@16
|
885 }
|
Chris@16
|
886
|
Chris@101
|
887 //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
|
Chris@16
|
888 //!
|
Chris@16
|
889 //! <b>Throws</b>: Nothing
|
Chris@16
|
890 //!
|
Chris@16
|
891 //! <b>Complexity</b>: Constant.
|
Chris@101
|
892 vector(BOOST_RV_REF(vector) x) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
893 : m_holder(boost::move(x.m_holder))
|
Chris@101
|
894 { BOOST_STATIC_ASSERT((!allocator_traits_type::is_partially_propagable::value)); }
|
Chris@101
|
895
|
Chris@101
|
896 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
Chris@101
|
897 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
|
Chris@101
|
898 //! and inserts a copy of the range [il.begin(), il.last()) in the vector
|
Chris@101
|
899 //!
|
Chris@101
|
900 //! <b>Throws</b>: If T's constructor taking a dereferenced initializer_list iterator throws.
|
Chris@101
|
901 //!
|
Chris@101
|
902 //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
|
Chris@101
|
903 vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
|
Chris@101
|
904 : m_holder(a)
|
Chris@101
|
905 {
|
Chris@101
|
906 this->assign(il.begin(), il.end());
|
Chris@101
|
907 }
|
Chris@101
|
908 #endif
|
Chris@16
|
909
|
Chris@16
|
910 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
Chris@16
|
911
|
Chris@101
|
912 //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
|
Chris@16
|
913 //!
|
Chris@16
|
914 //! <b>Throws</b>: If T's move constructor or allocation throws
|
Chris@16
|
915 //!
|
Chris@16
|
916 //! <b>Complexity</b>: Linear.
|
Chris@16
|
917 //!
|
Chris@101
|
918 //! <b>Note</b>: Non-standard extension to support static_vector
|
Chris@16
|
919 template<class OtherAllocator>
|
Chris@101
|
920 vector(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
|
Chris@101
|
921 , typename container_detail::enable_if_c
|
Chris@101
|
922 < container_detail::is_version<OtherAllocator, 0>::value>::type * = 0
|
Chris@101
|
923 )
|
Chris@101
|
924 : m_holder(boost::move(x.m_holder))
|
Chris@16
|
925 {}
|
Chris@16
|
926
|
Chris@16
|
927 #endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
Chris@16
|
928
|
Chris@16
|
929 //! <b>Effects</b>: Copy constructs a vector using the specified allocator.
|
Chris@16
|
930 //!
|
Chris@16
|
931 //! <b>Postcondition</b>: x == *this.
|
Chris@16
|
932 //!
|
Chris@16
|
933 //! <b>Throws</b>: If allocation
|
Chris@16
|
934 //! throws or T's copy constructor throws.
|
Chris@16
|
935 //!
|
Chris@16
|
936 //! <b>Complexity</b>: Linear to the elements x contains.
|
Chris@16
|
937 vector(const vector &x, const allocator_type &a)
|
Chris@101
|
938 : m_holder(container_detail::uninitialized_size, a, x.size())
|
Chris@16
|
939 {
|
Chris@101
|
940 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
941 this->num_alloc += x.size() != 0;
|
Chris@101
|
942 #endif
|
Chris@16
|
943 ::boost::container::uninitialized_copy_alloc_n_source
|
Chris@16
|
944 ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
|
Chris@16
|
945 , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@16
|
946 }
|
Chris@16
|
947
|
Chris@16
|
948 //! <b>Effects</b>: Move constructor using the specified allocator.
|
Chris@101
|
949 //! Moves x's resources to *this if a == allocator_type().
|
Chris@16
|
950 //! Otherwise copies values from x to *this.
|
Chris@16
|
951 //!
|
Chris@16
|
952 //! <b>Throws</b>: If allocation or T's copy constructor throws.
|
Chris@16
|
953 //!
|
Chris@101
|
954 //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
|
Chris@101
|
955 vector(BOOST_RV_REF(vector) x, const allocator_type &a)
|
Chris@101
|
956 : m_holder( container_detail::uninitialized_size, a
|
Chris@101
|
957 , is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true) ? 0 : x.size()
|
Chris@101
|
958 )
|
Chris@16
|
959 {
|
Chris@101
|
960 if(is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true)){
|
Chris@101
|
961 this->m_holder.steal_resources(x.m_holder);
|
Chris@16
|
962 }
|
Chris@16
|
963 else{
|
Chris@101
|
964 const size_type n = x.size();
|
Chris@101
|
965 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
966 this->num_alloc += n != 0;
|
Chris@101
|
967 #endif
|
Chris@16
|
968 ::boost::container::uninitialized_move_alloc_n_source
|
Chris@101
|
969 ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
|
Chris@16
|
970 , n, container_detail::to_raw_pointer(this->m_holder.start()));
|
Chris@16
|
971 }
|
Chris@16
|
972 }
|
Chris@16
|
973
|
Chris@16
|
974 //! <b>Effects</b>: Destroys the vector. All stored values are destroyed
|
Chris@16
|
975 //! and used memory is deallocated.
|
Chris@16
|
976 //!
|
Chris@16
|
977 //! <b>Throws</b>: Nothing.
|
Chris@16
|
978 //!
|
Chris@16
|
979 //! <b>Complexity</b>: Linear to the number of elements.
|
Chris@101
|
980 ~vector() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
981 {
|
Chris@16
|
982 boost::container::destroy_alloc_n
|
Chris@16
|
983 (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size);
|
Chris@16
|
984 //vector_alloc_holder deallocates the data
|
Chris@101
|
985 }
|
Chris@16
|
986
|
Chris@16
|
987 //! <b>Effects</b>: Makes *this contain the same elements as x.
|
Chris@16
|
988 //!
|
Chris@16
|
989 //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
|
Chris@16
|
990 //! of each of x's elements.
|
Chris@16
|
991 //!
|
Chris@16
|
992 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
|
Chris@16
|
993 //!
|
Chris@16
|
994 //! <b>Complexity</b>: Linear to the number of elements in x.
|
Chris@16
|
995 vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
|
Chris@16
|
996 {
|
Chris@16
|
997 if (&x != this){
|
Chris@101
|
998 this->priv_copy_assign(x);
|
Chris@16
|
999 }
|
Chris@16
|
1000 return *this;
|
Chris@16
|
1001 }
|
Chris@16
|
1002
|
Chris@101
|
1003 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
Chris@101
|
1004 //! <b>Effects</b>: Make *this container contains elements from il.
|
Chris@101
|
1005 //!
|
Chris@101
|
1006 //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
|
Chris@101
|
1007 vector& operator=(std::initializer_list<value_type> il)
|
Chris@101
|
1008 {
|
Chris@101
|
1009 this->assign(il.begin(), il.end());
|
Chris@101
|
1010 return *this;
|
Chris@101
|
1011 }
|
Chris@101
|
1012 #endif
|
Chris@101
|
1013
|
Chris@101
|
1014 //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
|
Chris@16
|
1015 //!
|
Chris@16
|
1016 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
|
Chris@16
|
1017 //! before the function.
|
Chris@16
|
1018 //!
|
Chris@101
|
1019 //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
|
Chris@101
|
1020 //! is false and (allocation throws or value_type's move constructor throws)
|
Chris@16
|
1021 //!
|
Chris@101
|
1022 //! <b>Complexity</b>: Constant if allocator_traits_type::
|
Chris@101
|
1023 //! propagate_on_container_move_assignment is true or
|
Chris@101
|
1024 //! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
Chris@16
|
1025 vector& operator=(BOOST_RV_REF(vector) x)
|
Chris@101
|
1026 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
Chris@101
|
1027 || allocator_traits_type::is_always_equal::value)
|
Chris@16
|
1028 {
|
Chris@101
|
1029 this->priv_move_assign(boost::move(x));
|
Chris@16
|
1030 return *this;
|
Chris@16
|
1031 }
|
Chris@16
|
1032
|
Chris@16
|
1033 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
Chris@16
|
1034
|
Chris@101
|
1035 //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
|
Chris@16
|
1036 //!
|
Chris@16
|
1037 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
|
Chris@16
|
1038 //! before the function.
|
Chris@16
|
1039 //!
|
Chris@16
|
1040 //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
|
Chris@16
|
1041 //!
|
Chris@16
|
1042 //! <b>Complexity</b>: Linear.
|
Chris@101
|
1043 //!
|
Chris@101
|
1044 //! <b>Note</b>: Non-standard extension to support static_vector
|
Chris@101
|
1045 template<class OtherAllocator>
|
Chris@101
|
1046 typename container_detail::enable_if_c
|
Chris@101
|
1047 < container_detail::is_version<OtherAllocator, 0>::value &&
|
Chris@101
|
1048 !container_detail::is_same<OtherAllocator, allocator_type>::value
|
Chris@101
|
1049 , vector& >::type
|
Chris@101
|
1050 operator=(BOOST_RV_REF_BEG vector<value_type, OtherAllocator> BOOST_RV_REF_END x)
|
Chris@16
|
1051 {
|
Chris@101
|
1052 this->priv_move_assign(boost::move(x));
|
Chris@101
|
1053 return *this;
|
Chris@101
|
1054 }
|
Chris@101
|
1055
|
Chris@101
|
1056 //! <b>Effects</b>: Copy assignment. All x's values are copied to *this.
|
Chris@101
|
1057 //!
|
Chris@101
|
1058 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
|
Chris@101
|
1059 //! before the function.
|
Chris@101
|
1060 //!
|
Chris@101
|
1061 //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
|
Chris@101
|
1062 //!
|
Chris@101
|
1063 //! <b>Complexity</b>: Linear.
|
Chris@101
|
1064 //!
|
Chris@101
|
1065 //! <b>Note</b>: Non-standard extension to support static_vector
|
Chris@101
|
1066 template<class OtherAllocator>
|
Chris@101
|
1067 typename container_detail::enable_if_c
|
Chris@101
|
1068 < container_detail::is_version<OtherAllocator, 0>::value &&
|
Chris@101
|
1069 !container_detail::is_same<OtherAllocator, allocator_type>::value
|
Chris@101
|
1070 , vector& >::type
|
Chris@101
|
1071 operator=(const vector<value_type, OtherAllocator> &x)
|
Chris@101
|
1072 {
|
Chris@101
|
1073 this->priv_copy_assign(x);
|
Chris@16
|
1074 return *this;
|
Chris@16
|
1075 }
|
Chris@16
|
1076
|
Chris@16
|
1077 #endif
|
Chris@16
|
1078
|
Chris@16
|
1079 //! <b>Effects</b>: Assigns the the range [first, last) to *this.
|
Chris@16
|
1080 //!
|
Chris@16
|
1081 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
|
Chris@16
|
1082 //! T's constructor/assignment from dereferencing InpIt throws.
|
Chris@16
|
1083 //!
|
Chris@16
|
1084 //! <b>Complexity</b>: Linear to n.
|
Chris@16
|
1085 template <class InIt>
|
Chris@16
|
1086 void assign(InIt first, InIt last
|
Chris@101
|
1087 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
|
Chris@101
|
1088 < !container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value &&
|
Chris@101
|
1089 ( container_detail::is_input_iterator<InIt>::value ||
|
Chris@101
|
1090 container_detail::is_same<alloc_version BOOST_MOVE_I version_0>::value )
|
Chris@101
|
1091 >::type * = 0) )
|
Chris@16
|
1092 {
|
Chris@16
|
1093 //Overwrite all elements we can from [first, last)
|
Chris@16
|
1094 iterator cur = this->begin();
|
Chris@16
|
1095 const iterator end_it = this->end();
|
Chris@16
|
1096 for ( ; first != last && cur != end_it; ++cur, ++first){
|
Chris@16
|
1097 *cur = *first;
|
Chris@16
|
1098 }
|
Chris@16
|
1099
|
Chris@16
|
1100 if (first == last){
|
Chris@16
|
1101 //There are no more elements in the sequence, erase remaining
|
Chris@101
|
1102 T* const end_pos = this->back_raw();
|
Chris@101
|
1103 const size_type n = static_cast<size_type>(end_pos - container_detail::iterator_to_raw_pointer(cur));
|
Chris@16
|
1104 this->priv_destroy_last_n(n);
|
Chris@16
|
1105 }
|
Chris@16
|
1106 else{
|
Chris@16
|
1107 //There are more elements in the range, insert the remaining ones
|
Chris@16
|
1108 this->insert(this->cend(), first, last);
|
Chris@16
|
1109 }
|
Chris@16
|
1110 }
|
Chris@16
|
1111
|
Chris@101
|
1112 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
Chris@101
|
1113 //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
|
Chris@101
|
1114 //!
|
Chris@101
|
1115 //! <b>Throws</b>: If memory allocation throws or
|
Chris@101
|
1116 //! T's constructor from dereferencing iniializer_list iterator throws.
|
Chris@101
|
1117 //!
|
Chris@101
|
1118 void assign(std::initializer_list<T> il)
|
Chris@101
|
1119 {
|
Chris@101
|
1120 this->assign(il.begin(), il.end());
|
Chris@101
|
1121 }
|
Chris@101
|
1122 #endif
|
Chris@101
|
1123
|
Chris@101
|
1124 //! <b>Effects</b>: Assigns the the range [first, last) to *this.
|
Chris@101
|
1125 //!
|
Chris@101
|
1126 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
|
Chris@101
|
1127 //! T's constructor/assignment from dereferencing InpIt throws.
|
Chris@101
|
1128 //!
|
Chris@101
|
1129 //! <b>Complexity</b>: Linear to n.
|
Chris@101
|
1130 template <class FwdIt>
|
Chris@101
|
1131 void assign(FwdIt first, FwdIt last
|
Chris@101
|
1132 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
|
Chris@101
|
1133 < !container_detail::is_convertible<FwdIt BOOST_MOVE_I size_type>::value &&
|
Chris@101
|
1134 ( !container_detail::is_input_iterator<FwdIt>::value &&
|
Chris@101
|
1135 !container_detail::is_same<alloc_version BOOST_MOVE_I version_0>::value )
|
Chris@101
|
1136 >::type * = 0)
|
Chris@101
|
1137 )
|
Chris@101
|
1138 {
|
Chris@101
|
1139 //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
|
Chris@101
|
1140 //so we can't do any backwards allocation
|
Chris@101
|
1141 const size_type input_sz = static_cast<size_type>(boost::container::iterator_distance(first, last));
|
Chris@101
|
1142 const size_type old_capacity = this->capacity();
|
Chris@101
|
1143 if(input_sz > old_capacity){ //If input range is too big, we need to reallocate
|
Chris@101
|
1144 size_type real_cap = 0;
|
Chris@101
|
1145 pointer reuse(this->m_holder.start());
|
Chris@101
|
1146 pointer const ret(this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, real_cap = input_sz, reuse));
|
Chris@101
|
1147 if(!reuse){ //New allocation, just emplace new values
|
Chris@101
|
1148 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
1149 ++this->num_alloc;
|
Chris@101
|
1150 #endif
|
Chris@101
|
1151 pointer const old_p = this->m_holder.start();
|
Chris@101
|
1152 if(old_p){
|
Chris@101
|
1153 this->priv_destroy_all();
|
Chris@101
|
1154 this->m_holder.alloc().deallocate(old_p, old_capacity);
|
Chris@101
|
1155 }
|
Chris@101
|
1156 this->m_holder.start(ret);
|
Chris@101
|
1157 this->m_holder.capacity(real_cap);
|
Chris@101
|
1158 this->m_holder.m_size = 0;
|
Chris@101
|
1159 this->priv_uninitialized_construct_at_end(first, last);
|
Chris@101
|
1160 return;
|
Chris@101
|
1161 }
|
Chris@101
|
1162 else{
|
Chris@101
|
1163 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@101
|
1164 ++this->num_expand_fwd;
|
Chris@101
|
1165 #endif
|
Chris@101
|
1166 this->m_holder.capacity(real_cap);
|
Chris@101
|
1167 //Forward expansion, use assignment + back deletion/construction that comes later
|
Chris@101
|
1168 }
|
Chris@101
|
1169 }
|
Chris@101
|
1170 //Overwrite all elements we can from [first, last)
|
Chris@101
|
1171 iterator cur = this->begin();
|
Chris@101
|
1172 const iterator end_it = this->end();
|
Chris@101
|
1173 for ( ; first != last && cur != end_it; ++cur, ++first){
|
Chris@101
|
1174 *cur = *first;
|
Chris@101
|
1175 }
|
Chris@101
|
1176
|
Chris@101
|
1177 if (first == last){
|
Chris@101
|
1178 //There are no more elements in the sequence, erase remaining
|
Chris@101
|
1179 this->priv_destroy_last_n(this->size() - input_sz);
|
Chris@101
|
1180 }
|
Chris@101
|
1181 else{
|
Chris@101
|
1182 //Uninitialized construct at end the remaining range
|
Chris@101
|
1183 this->priv_uninitialized_construct_at_end(first, last);
|
Chris@101
|
1184 }
|
Chris@101
|
1185 }
|
Chris@101
|
1186
|
Chris@16
|
1187 //! <b>Effects</b>: Assigns the n copies of val to *this.
|
Chris@16
|
1188 //!
|
Chris@16
|
1189 //! <b>Throws</b>: If memory allocation throws or
|
Chris@16
|
1190 //! T's copy/move constructor/assignment throws.
|
Chris@16
|
1191 //!
|
Chris@16
|
1192 //! <b>Complexity</b>: Linear to n.
|
Chris@16
|
1193 void assign(size_type n, const value_type& val)
|
Chris@16
|
1194 { this->assign(cvalue_iterator(val, n), cvalue_iterator()); }
|
Chris@16
|
1195
|
Chris@16
|
1196 //! <b>Effects</b>: Returns a copy of the internal allocator.
|
Chris@16
|
1197 //!
|
Chris@16
|
1198 //! <b>Throws</b>: If allocator's copy constructor throws.
|
Chris@16
|
1199 //!
|
Chris@16
|
1200 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1201 allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1202 { return this->m_holder.alloc(); }
|
Chris@16
|
1203
|
Chris@16
|
1204 //! <b>Effects</b>: Returns a reference to the internal allocator.
|
Chris@16
|
1205 //!
|
Chris@16
|
1206 //! <b>Throws</b>: Nothing
|
Chris@16
|
1207 //!
|
Chris@16
|
1208 //! <b>Complexity</b>: Constant.
|
Chris@16
|
1209 //!
|
Chris@16
|
1210 //! <b>Note</b>: Non-standard extension.
|
Chris@101
|
1211 stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1212 { return this->m_holder.alloc(); }
|
Chris@16
|
1213
|
Chris@16
|
1214 //! <b>Effects</b>: Returns a reference to the internal allocator.
|
Chris@16
|
1215 //!
|
Chris@16
|
1216 //! <b>Throws</b>: Nothing
|
Chris@16
|
1217 //!
|
Chris@16
|
1218 //! <b>Complexity</b>: Constant.
|
Chris@16
|
1219 //!
|
Chris@16
|
1220 //! <b>Note</b>: Non-standard extension.
|
Chris@101
|
1221 const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1222 { return this->m_holder.alloc(); }
|
Chris@16
|
1223
|
Chris@16
|
1224 //////////////////////////////////////////////
|
Chris@16
|
1225 //
|
Chris@16
|
1226 // iterators
|
Chris@16
|
1227 //
|
Chris@16
|
1228 //////////////////////////////////////////////
|
Chris@16
|
1229
|
Chris@16
|
1230 //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
|
Chris@16
|
1231 //!
|
Chris@16
|
1232 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1233 //!
|
Chris@16
|
1234 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1235 iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1236 { return iterator(this->m_holder.start()); }
|
Chris@16
|
1237
|
Chris@16
|
1238 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
|
Chris@16
|
1239 //!
|
Chris@16
|
1240 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1241 //!
|
Chris@16
|
1242 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1243 const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1244 { return const_iterator(this->m_holder.start()); }
|
Chris@16
|
1245
|
Chris@16
|
1246 //! <b>Effects</b>: Returns an iterator to the end of the vector.
|
Chris@16
|
1247 //!
|
Chris@16
|
1248 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1249 //!
|
Chris@16
|
1250 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1251 iterator end() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1252 { return iterator(this->m_holder.start() + this->m_holder.m_size); }
|
Chris@16
|
1253
|
Chris@16
|
1254 //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
|
Chris@16
|
1255 //!
|
Chris@16
|
1256 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1257 //!
|
Chris@16
|
1258 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1259 const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1260 { return this->cend(); }
|
Chris@16
|
1261
|
Chris@16
|
1262 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
|
Chris@16
|
1263 //! of the reversed vector.
|
Chris@16
|
1264 //!
|
Chris@16
|
1265 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1266 //!
|
Chris@16
|
1267 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1268 reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1269 { return reverse_iterator(this->end()); }
|
Chris@16
|
1270
|
Chris@16
|
1271 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
|
Chris@16
|
1272 //! of the reversed vector.
|
Chris@16
|
1273 //!
|
Chris@16
|
1274 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1275 //!
|
Chris@16
|
1276 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1277 const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1278 { return this->crbegin(); }
|
Chris@16
|
1279
|
Chris@16
|
1280 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
|
Chris@16
|
1281 //! of the reversed vector.
|
Chris@16
|
1282 //!
|
Chris@16
|
1283 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1284 //!
|
Chris@16
|
1285 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1286 reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1287 { return reverse_iterator(this->begin()); }
|
Chris@16
|
1288
|
Chris@16
|
1289 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
|
Chris@16
|
1290 //! of the reversed vector.
|
Chris@16
|
1291 //!
|
Chris@16
|
1292 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1293 //!
|
Chris@16
|
1294 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1295 const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1296 { return this->crend(); }
|
Chris@16
|
1297
|
Chris@16
|
1298 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
|
Chris@16
|
1299 //!
|
Chris@16
|
1300 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1301 //!
|
Chris@16
|
1302 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1303 const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1304 { return const_iterator(this->m_holder.start()); }
|
Chris@16
|
1305
|
Chris@16
|
1306 //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
|
Chris@16
|
1307 //!
|
Chris@16
|
1308 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1309 //!
|
Chris@16
|
1310 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1311 const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1312 { return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
|
Chris@16
|
1313
|
Chris@16
|
1314 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
|
Chris@16
|
1315 //! of the reversed vector.
|
Chris@16
|
1316 //!
|
Chris@16
|
1317 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1318 //!
|
Chris@16
|
1319 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1320 const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1321 { return const_reverse_iterator(this->end());}
|
Chris@16
|
1322
|
Chris@16
|
1323 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
|
Chris@16
|
1324 //! of the reversed vector.
|
Chris@16
|
1325 //!
|
Chris@16
|
1326 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1327 //!
|
Chris@16
|
1328 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1329 const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1330 { return const_reverse_iterator(this->begin()); }
|
Chris@16
|
1331
|
Chris@16
|
1332 //////////////////////////////////////////////
|
Chris@16
|
1333 //
|
Chris@16
|
1334 // capacity
|
Chris@16
|
1335 //
|
Chris@16
|
1336 //////////////////////////////////////////////
|
Chris@16
|
1337
|
Chris@16
|
1338 //! <b>Effects</b>: Returns true if the vector contains no elements.
|
Chris@16
|
1339 //!
|
Chris@16
|
1340 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1341 //!
|
Chris@16
|
1342 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1343 bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1344 { return !this->m_holder.m_size; }
|
Chris@16
|
1345
|
Chris@16
|
1346 //! <b>Effects</b>: Returns the number of the elements contained in the vector.
|
Chris@16
|
1347 //!
|
Chris@16
|
1348 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1349 //!
|
Chris@16
|
1350 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1351 size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1352 { return this->m_holder.m_size; }
|
Chris@16
|
1353
|
Chris@16
|
1354 //! <b>Effects</b>: Returns the largest possible size of the vector.
|
Chris@16
|
1355 //!
|
Chris@16
|
1356 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1357 //!
|
Chris@16
|
1358 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1359 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1360 { return allocator_traits_type::max_size(this->m_holder.alloc()); }
|
Chris@16
|
1361
|
Chris@16
|
1362 //! <b>Effects</b>: Inserts or erases elements at the end such that
|
Chris@16
|
1363 //! the size becomes n. New elements are value initialized.
|
Chris@16
|
1364 //!
|
Chris@101
|
1365 //! <b>Throws</b>: If memory allocation throws, or T's copy/move or value initialization throws.
|
Chris@16
|
1366 //!
|
Chris@16
|
1367 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
|
Chris@16
|
1368 void resize(size_type new_size)
|
Chris@101
|
1369 { this->priv_resize(new_size, value_init); }
|
Chris@16
|
1370
|
Chris@16
|
1371 //! <b>Effects</b>: Inserts or erases elements at the end such that
|
Chris@101
|
1372 //! the size becomes n. New elements are default initialized.
|
Chris@16
|
1373 //!
|
Chris@101
|
1374 //! <b>Throws</b>: If memory allocation throws, or T's copy/move or default initialization throws.
|
Chris@16
|
1375 //!
|
Chris@16
|
1376 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
|
Chris@16
|
1377 //!
|
Chris@16
|
1378 //! <b>Note</b>: Non-standard extension
|
Chris@16
|
1379 void resize(size_type new_size, default_init_t)
|
Chris@101
|
1380 { this->priv_resize(new_size, default_init); }
|
Chris@16
|
1381
|
Chris@16
|
1382 //! <b>Effects</b>: Inserts or erases elements at the end such that
|
Chris@16
|
1383 //! the size becomes n. New elements are copy constructed from x.
|
Chris@16
|
1384 //!
|
Chris@101
|
1385 //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
|
Chris@16
|
1386 //!
|
Chris@16
|
1387 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
|
Chris@16
|
1388 void resize(size_type new_size, const T& x)
|
Chris@101
|
1389 { this->priv_resize(new_size, x); }
|
Chris@16
|
1390
|
Chris@16
|
1391 //! <b>Effects</b>: Number of elements for which memory has been allocated.
|
Chris@16
|
1392 //! capacity() is always greater than or equal to size().
|
Chris@16
|
1393 //!
|
Chris@16
|
1394 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1395 //!
|
Chris@16
|
1396 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1397 size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1398 { return this->m_holder.capacity(); }
|
Chris@16
|
1399
|
Chris@16
|
1400 //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
|
Chris@16
|
1401 //! effect. Otherwise, it is a request for allocation of additional memory.
|
Chris@16
|
1402 //! If the request is successful, then capacity() is greater than or equal to
|
Chris@16
|
1403 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
|
Chris@16
|
1404 //!
|
Chris@16
|
1405 //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
|
Chris@16
|
1406 void reserve(size_type new_cap)
|
Chris@16
|
1407 {
|
Chris@16
|
1408 if (this->capacity() < new_cap){
|
Chris@101
|
1409 this->priv_reserve_no_capacity(new_cap, alloc_version());
|
Chris@16
|
1410 }
|
Chris@16
|
1411 }
|
Chris@16
|
1412
|
Chris@16
|
1413 //! <b>Effects</b>: Tries to deallocate the excess of memory created
|
Chris@16
|
1414 //! with previous allocations. The size of the vector is unchanged
|
Chris@16
|
1415 //!
|
Chris@16
|
1416 //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
|
Chris@16
|
1417 //!
|
Chris@16
|
1418 //! <b>Complexity</b>: Linear to size().
|
Chris@16
|
1419 void shrink_to_fit()
|
Chris@16
|
1420 { this->priv_shrink_to_fit(alloc_version()); }
|
Chris@16
|
1421
|
Chris@16
|
1422 //////////////////////////////////////////////
|
Chris@16
|
1423 //
|
Chris@16
|
1424 // element access
|
Chris@16
|
1425 //
|
Chris@16
|
1426 //////////////////////////////////////////////
|
Chris@16
|
1427
|
Chris@16
|
1428 //! <b>Requires</b>: !empty()
|
Chris@16
|
1429 //!
|
Chris@16
|
1430 //! <b>Effects</b>: Returns a reference to the first
|
Chris@16
|
1431 //! element of the container.
|
Chris@16
|
1432 //!
|
Chris@16
|
1433 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1434 //!
|
Chris@16
|
1435 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1436 reference front() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1437 { return *this->m_holder.start(); }
|
Chris@16
|
1438
|
Chris@16
|
1439 //! <b>Requires</b>: !empty()
|
Chris@16
|
1440 //!
|
Chris@16
|
1441 //! <b>Effects</b>: Returns a const reference to the first
|
Chris@16
|
1442 //! element of the container.
|
Chris@16
|
1443 //!
|
Chris@16
|
1444 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1445 //!
|
Chris@16
|
1446 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1447 const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1448 { return *this->m_holder.start(); }
|
Chris@16
|
1449
|
Chris@16
|
1450 //! <b>Requires</b>: !empty()
|
Chris@16
|
1451 //!
|
Chris@16
|
1452 //! <b>Effects</b>: Returns a reference to the last
|
Chris@16
|
1453 //! element of the container.
|
Chris@16
|
1454 //!
|
Chris@16
|
1455 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1456 //!
|
Chris@16
|
1457 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1458 reference back() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
1459 {
|
Chris@101
|
1460 BOOST_ASSERT(this->m_holder.m_size > 0);
|
Chris@101
|
1461 return this->m_holder.start()[this->m_holder.m_size - 1];
|
Chris@101
|
1462 }
|
Chris@16
|
1463
|
Chris@16
|
1464 //! <b>Requires</b>: !empty()
|
Chris@16
|
1465 //!
|
Chris@16
|
1466 //! <b>Effects</b>: Returns a const reference to the last
|
Chris@16
|
1467 //! element of the container.
|
Chris@16
|
1468 //!
|
Chris@16
|
1469 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1470 //!
|
Chris@16
|
1471 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1472 const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
1473 {
|
Chris@101
|
1474 BOOST_ASSERT(this->m_holder.m_size > 0);
|
Chris@101
|
1475 return this->m_holder.start()[this->m_holder.m_size - 1];
|
Chris@101
|
1476 }
|
Chris@16
|
1477
|
Chris@16
|
1478 //! <b>Requires</b>: size() > n.
|
Chris@16
|
1479 //!
|
Chris@16
|
1480 //! <b>Effects</b>: Returns a reference to the nth element
|
Chris@16
|
1481 //! from the beginning of the container.
|
Chris@16
|
1482 //!
|
Chris@16
|
1483 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1484 //!
|
Chris@16
|
1485 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1486 reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
1487 {
|
Chris@101
|
1488 BOOST_ASSERT(this->m_holder.m_size > n);
|
Chris@101
|
1489 return this->m_holder.start()[n];
|
Chris@101
|
1490 }
|
Chris@16
|
1491
|
Chris@16
|
1492 //! <b>Requires</b>: size() > n.
|
Chris@16
|
1493 //!
|
Chris@16
|
1494 //! <b>Effects</b>: Returns a const reference to the nth element
|
Chris@16
|
1495 //! from the beginning of the container.
|
Chris@16
|
1496 //!
|
Chris@16
|
1497 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1498 //!
|
Chris@16
|
1499 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1500 const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
1501 {
|
Chris@101
|
1502 return this->m_holder.start()[n];
|
Chris@101
|
1503 }
|
Chris@101
|
1504
|
Chris@101
|
1505 //! <b>Requires</b>: size() >= n.
|
Chris@101
|
1506 //!
|
Chris@101
|
1507 //! <b>Effects</b>: Returns an iterator to the nth element
|
Chris@101
|
1508 //! from the beginning of the container. Returns end()
|
Chris@101
|
1509 //! if n == size().
|
Chris@101
|
1510 //!
|
Chris@101
|
1511 //! <b>Throws</b>: Nothing.
|
Chris@101
|
1512 //!
|
Chris@101
|
1513 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1514 //!
|
Chris@101
|
1515 //! <b>Note</b>: Non-standard extension
|
Chris@101
|
1516 iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
1517 {
|
Chris@101
|
1518 BOOST_ASSERT(this->m_holder.m_size >= n);
|
Chris@101
|
1519 return iterator(this->m_holder.start()+n);
|
Chris@101
|
1520 }
|
Chris@101
|
1521
|
Chris@101
|
1522 //! <b>Requires</b>: size() >= n.
|
Chris@101
|
1523 //!
|
Chris@101
|
1524 //! <b>Effects</b>: Returns a const_iterator to the nth element
|
Chris@101
|
1525 //! from the beginning of the container. Returns end()
|
Chris@101
|
1526 //! if n == size().
|
Chris@101
|
1527 //!
|
Chris@101
|
1528 //! <b>Throws</b>: Nothing.
|
Chris@101
|
1529 //!
|
Chris@101
|
1530 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1531 //!
|
Chris@101
|
1532 //! <b>Note</b>: Non-standard extension
|
Chris@101
|
1533 const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
1534 {
|
Chris@101
|
1535 BOOST_ASSERT(this->m_holder.m_size >= n);
|
Chris@101
|
1536 return const_iterator(this->m_holder.start()+n);
|
Chris@101
|
1537 }
|
Chris@101
|
1538
|
Chris@101
|
1539 //! <b>Requires</b>: size() >= n.
|
Chris@101
|
1540 //!
|
Chris@101
|
1541 //! <b>Effects</b>: Returns an iterator to the nth element
|
Chris@101
|
1542 //! from the beginning of the container. Returns end()
|
Chris@101
|
1543 //! if n == size().
|
Chris@101
|
1544 //!
|
Chris@101
|
1545 //! <b>Throws</b>: Nothing.
|
Chris@101
|
1546 //!
|
Chris@101
|
1547 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1548 //!
|
Chris@101
|
1549 //! <b>Note</b>: Non-standard extension
|
Chris@101
|
1550 size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
1551 { return this->priv_index_of(vector_iterator_get_ptr(p)); }
|
Chris@101
|
1552
|
Chris@101
|
1553 //! <b>Requires</b>: begin() <= p <= end().
|
Chris@101
|
1554 //!
|
Chris@101
|
1555 //! <b>Effects</b>: Returns the index of the element pointed by p
|
Chris@101
|
1556 //! and size() if p == end().
|
Chris@101
|
1557 //!
|
Chris@101
|
1558 //! <b>Throws</b>: Nothing.
|
Chris@101
|
1559 //!
|
Chris@101
|
1560 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1561 //!
|
Chris@101
|
1562 //! <b>Note</b>: Non-standard extension
|
Chris@101
|
1563 size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
1564 { return this->priv_index_of(vector_iterator_get_ptr(p)); }
|
Chris@16
|
1565
|
Chris@16
|
1566 //! <b>Requires</b>: size() > n.
|
Chris@16
|
1567 //!
|
Chris@16
|
1568 //! <b>Effects</b>: Returns a reference to the nth element
|
Chris@16
|
1569 //! from the beginning of the container.
|
Chris@16
|
1570 //!
|
Chris@16
|
1571 //! <b>Throws</b>: std::range_error if n >= size()
|
Chris@16
|
1572 //!
|
Chris@16
|
1573 //! <b>Complexity</b>: Constant.
|
Chris@16
|
1574 reference at(size_type n)
|
Chris@16
|
1575 { this->priv_check_range(n); return this->m_holder.start()[n]; }
|
Chris@16
|
1576
|
Chris@16
|
1577 //! <b>Requires</b>: size() > n.
|
Chris@16
|
1578 //!
|
Chris@16
|
1579 //! <b>Effects</b>: Returns a const reference to the nth element
|
Chris@16
|
1580 //! from the beginning of the container.
|
Chris@16
|
1581 //!
|
Chris@16
|
1582 //! <b>Throws</b>: std::range_error if n >= size()
|
Chris@16
|
1583 //!
|
Chris@16
|
1584 //! <b>Complexity</b>: Constant.
|
Chris@16
|
1585 const_reference at(size_type n) const
|
Chris@16
|
1586 { this->priv_check_range(n); return this->m_holder.start()[n]; }
|
Chris@16
|
1587
|
Chris@16
|
1588 //////////////////////////////////////////////
|
Chris@16
|
1589 //
|
Chris@16
|
1590 // data access
|
Chris@16
|
1591 //
|
Chris@16
|
1592 //////////////////////////////////////////////
|
Chris@16
|
1593
|
Chris@101
|
1594 //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
|
Chris@16
|
1595 //! For a non-empty vector, data() == &front().
|
Chris@16
|
1596 //!
|
Chris@16
|
1597 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1598 //!
|
Chris@16
|
1599 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1600 T* data() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1601 { return container_detail::to_raw_pointer(this->m_holder.start()); }
|
Chris@16
|
1602
|
Chris@101
|
1603 //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
|
Chris@16
|
1604 //! For a non-empty vector, data() == &front().
|
Chris@16
|
1605 //!
|
Chris@16
|
1606 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1607 //!
|
Chris@16
|
1608 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1609 const T * data() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1610 { return container_detail::to_raw_pointer(this->m_holder.start()); }
|
Chris@16
|
1611
|
Chris@16
|
1612 //////////////////////////////////////////////
|
Chris@16
|
1613 //
|
Chris@16
|
1614 // modifiers
|
Chris@16
|
1615 //
|
Chris@16
|
1616 //////////////////////////////////////////////
|
Chris@16
|
1617
|
Chris@101
|
1618 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
Chris@16
|
1619 //! <b>Effects</b>: Inserts an object of type T constructed with
|
Chris@16
|
1620 //! std::forward<Args>(args)... in the end of the vector.
|
Chris@16
|
1621 //!
|
Chris@16
|
1622 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
|
Chris@101
|
1623 //! T's copy/move constructor throws.
|
Chris@16
|
1624 //!
|
Chris@16
|
1625 //! <b>Complexity</b>: Amortized constant time.
|
Chris@16
|
1626 template<class ...Args>
|
Chris@101
|
1627 void emplace_back(BOOST_FWD_REF(Args)...args)
|
Chris@16
|
1628 {
|
Chris@101
|
1629 if (BOOST_LIKELY(this->room_enough())){
|
Chris@16
|
1630 //There is more memory, just construct a new object at the end
|
Chris@101
|
1631 allocator_traits_type::construct(this->m_holder.alloc(), this->back_raw(), ::boost::forward<Args>(args)...);
|
Chris@16
|
1632 ++this->m_holder.m_size;
|
Chris@16
|
1633 }
|
Chris@16
|
1634 else{
|
Chris@16
|
1635 typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
|
Chris@16
|
1636 this->priv_forward_range_insert_no_capacity
|
Chris@101
|
1637 (this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version());
|
Chris@16
|
1638 }
|
Chris@16
|
1639 }
|
Chris@16
|
1640
|
Chris@101
|
1641 //! <b>Effects</b>: Inserts an object of type T constructed with
|
Chris@101
|
1642 //! std::forward<Args>(args)... in the end of the vector.
|
Chris@101
|
1643 //!
|
Chris@101
|
1644 //! <b>Throws</b>: If the in-place constructor throws.
|
Chris@101
|
1645 //!
|
Chris@101
|
1646 //! <b>Complexity</b>: Constant time.
|
Chris@101
|
1647 //!
|
Chris@101
|
1648 //! <b>Note</b>: Non-standard extension.
|
Chris@101
|
1649 template<class ...Args>
|
Chris@101
|
1650 bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
|
Chris@101
|
1651 {
|
Chris@101
|
1652 const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
|
Chris@101
|
1653 if (BOOST_LIKELY(is_room_enough)){
|
Chris@101
|
1654 //There is more memory, just construct a new object at the end
|
Chris@101
|
1655 allocator_traits_type::construct(this->m_holder.alloc(), this->back_raw(), ::boost::forward<Args>(args)...);
|
Chris@101
|
1656 ++this->m_holder.m_size;
|
Chris@101
|
1657 }
|
Chris@101
|
1658 return is_room_enough;
|
Chris@101
|
1659 }
|
Chris@101
|
1660
|
Chris@16
|
1661 //! <b>Requires</b>: position must be a valid iterator of *this.
|
Chris@16
|
1662 //!
|
Chris@16
|
1663 //! <b>Effects</b>: Inserts an object of type T constructed with
|
Chris@16
|
1664 //! std::forward<Args>(args)... before position
|
Chris@16
|
1665 //!
|
Chris@16
|
1666 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
|
Chris@101
|
1667 //! T's copy/move constructor/assignment throws.
|
Chris@16
|
1668 //!
|
Chris@16
|
1669 //! <b>Complexity</b>: If position is end(), amortized constant time
|
Chris@16
|
1670 //! Linear time otherwise.
|
Chris@16
|
1671 template<class ...Args>
|
Chris@101
|
1672 iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args)
|
Chris@16
|
1673 {
|
Chris@16
|
1674 //Just call more general insert(pos, size, value) and return iterator
|
Chris@16
|
1675 typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
|
Chris@101
|
1676 return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1
|
Chris@101
|
1677 , type(::boost::forward<Args>(args)...));
|
Chris@16
|
1678 }
|
Chris@16
|
1679
|
Chris@101
|
1680 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@16
|
1681
|
Chris@101
|
1682 #define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
|
Chris@101
|
1683 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
Chris@101
|
1684 void emplace_back(BOOST_MOVE_UREF##N)\
|
Chris@101
|
1685 {\
|
Chris@101
|
1686 if (BOOST_LIKELY(this->room_enough())){\
|
Chris@101
|
1687 allocator_traits_type::construct (this->m_holder.alloc()\
|
Chris@101
|
1688 , this->back_raw() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
Chris@101
|
1689 ++this->m_holder.m_size;\
|
Chris@101
|
1690 }\
|
Chris@101
|
1691 else{\
|
Chris@101
|
1692 typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
|
Chris@101
|
1693 this->priv_forward_range_insert_no_capacity\
|
Chris@101
|
1694 ( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\
|
Chris@101
|
1695 }\
|
Chris@101
|
1696 }\
|
Chris@101
|
1697 \
|
Chris@101
|
1698 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
Chris@101
|
1699 bool stable_emplace_back(BOOST_MOVE_UREF##N)\
|
Chris@101
|
1700 {\
|
Chris@101
|
1701 const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
|
Chris@101
|
1702 if (BOOST_LIKELY(is_room_enough)){\
|
Chris@101
|
1703 allocator_traits_type::construct (this->m_holder.alloc()\
|
Chris@101
|
1704 , this->back_raw() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
Chris@101
|
1705 ++this->m_holder.m_size;\
|
Chris@101
|
1706 }\
|
Chris@101
|
1707 return is_room_enough;\
|
Chris@101
|
1708 }\
|
Chris@101
|
1709 \
|
Chris@101
|
1710 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
Chris@101
|
1711 iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
Chris@101
|
1712 {\
|
Chris@101
|
1713 typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
|
Chris@101
|
1714 return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), 1, type(BOOST_MOVE_FWD##N));\
|
Chris@101
|
1715 }\
|
Chris@101
|
1716 //
|
Chris@101
|
1717 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
|
Chris@101
|
1718 #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE
|
Chris@16
|
1719
|
Chris@101
|
1720 #endif
|
Chris@16
|
1721
|
Chris@16
|
1722 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
Chris@16
|
1723 //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
|
Chris@16
|
1724 //!
|
Chris@16
|
1725 //! <b>Throws</b>: If memory allocation throws or
|
Chris@16
|
1726 //! T's copy/move constructor throws.
|
Chris@16
|
1727 //!
|
Chris@16
|
1728 //! <b>Complexity</b>: Amortized constant time.
|
Chris@16
|
1729 void push_back(const T &x);
|
Chris@16
|
1730
|
Chris@16
|
1731 //! <b>Effects</b>: Constructs a new element in the end of the vector
|
Chris@101
|
1732 //! and moves the resources of x to this new element.
|
Chris@16
|
1733 //!
|
Chris@16
|
1734 //! <b>Throws</b>: If memory allocation throws or
|
Chris@101
|
1735 //! T's copy/move constructor throws.
|
Chris@16
|
1736 //!
|
Chris@16
|
1737 //! <b>Complexity</b>: Amortized constant time.
|
Chris@16
|
1738 void push_back(T &&x);
|
Chris@16
|
1739 #else
|
Chris@16
|
1740 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
|
Chris@16
|
1741 #endif
|
Chris@101
|
1742
|
Chris@16
|
1743 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
Chris@16
|
1744 //! <b>Requires</b>: position must be a valid iterator of *this.
|
Chris@16
|
1745 //!
|
Chris@16
|
1746 //! <b>Effects</b>: Insert a copy of x before position.
|
Chris@16
|
1747 //!
|
Chris@16
|
1748 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
|
Chris@16
|
1749 //!
|
Chris@16
|
1750 //! <b>Complexity</b>: If position is end(), amortized constant time
|
Chris@16
|
1751 //! Linear time otherwise.
|
Chris@16
|
1752 iterator insert(const_iterator position, const T &x);
|
Chris@16
|
1753
|
Chris@16
|
1754 //! <b>Requires</b>: position must be a valid iterator of *this.
|
Chris@16
|
1755 //!
|
Chris@101
|
1756 //! <b>Effects</b>: Insert a new element before position with x's resources.
|
Chris@16
|
1757 //!
|
Chris@16
|
1758 //! <b>Throws</b>: If memory allocation throws.
|
Chris@16
|
1759 //!
|
Chris@16
|
1760 //! <b>Complexity</b>: If position is end(), amortized constant time
|
Chris@16
|
1761 //! Linear time otherwise.
|
Chris@16
|
1762 iterator insert(const_iterator position, T &&x);
|
Chris@16
|
1763 #else
|
Chris@16
|
1764 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
|
Chris@16
|
1765 #endif
|
Chris@16
|
1766
|
Chris@16
|
1767 //! <b>Requires</b>: p must be a valid iterator of *this.
|
Chris@16
|
1768 //!
|
Chris@16
|
1769 //! <b>Effects</b>: Insert n copies of x before pos.
|
Chris@16
|
1770 //!
|
Chris@16
|
1771 //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
|
Chris@16
|
1772 //!
|
Chris@101
|
1773 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor throws.
|
Chris@16
|
1774 //!
|
Chris@16
|
1775 //! <b>Complexity</b>: Linear to n.
|
Chris@16
|
1776 iterator insert(const_iterator p, size_type n, const T& x)
|
Chris@16
|
1777 {
|
Chris@101
|
1778 container_detail::insert_n_copies_proxy<Allocator, T*> proxy(x);
|
Chris@101
|
1779 return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy);
|
Chris@16
|
1780 }
|
Chris@16
|
1781
|
Chris@16
|
1782 //! <b>Requires</b>: p must be a valid iterator of *this.
|
Chris@16
|
1783 //!
|
Chris@16
|
1784 //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
|
Chris@16
|
1785 //!
|
Chris@16
|
1786 //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
|
Chris@16
|
1787 //!
|
Chris@16
|
1788 //! <b>Throws</b>: If memory allocation throws, T's constructor from a
|
Chris@16
|
1789 //! dereferenced InpIt throws or T's copy/move constructor/assignment throws.
|
Chris@16
|
1790 //!
|
Chris@101
|
1791 //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
|
Chris@16
|
1792 template <class InIt>
|
Chris@16
|
1793 iterator insert(const_iterator pos, InIt first, InIt last
|
Chris@101
|
1794 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
|
Chris@101
|
1795 < !container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
|
Chris@16
|
1796 && container_detail::is_input_iterator<InIt>::value
|
Chris@101
|
1797 >::type * = 0)
|
Chris@16
|
1798 )
|
Chris@16
|
1799 {
|
Chris@16
|
1800 const size_type n_pos = pos - this->cbegin();
|
Chris@16
|
1801 iterator it(vector_iterator_get_ptr(pos));
|
Chris@16
|
1802 for(;first != last; ++first){
|
Chris@16
|
1803 it = this->emplace(it, *first);
|
Chris@16
|
1804 ++it;
|
Chris@16
|
1805 }
|
Chris@16
|
1806 return iterator(this->m_holder.start() + n_pos);
|
Chris@16
|
1807 }
|
Chris@16
|
1808
|
Chris@16
|
1809 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
Chris@16
|
1810 template <class FwdIt>
|
Chris@16
|
1811 iterator insert(const_iterator pos, FwdIt first, FwdIt last
|
Chris@16
|
1812 , typename container_detail::enable_if_c
|
Chris@16
|
1813 < !container_detail::is_convertible<FwdIt, size_type>::value
|
Chris@16
|
1814 && !container_detail::is_input_iterator<FwdIt>::value
|
Chris@16
|
1815 >::type * = 0
|
Chris@16
|
1816 )
|
Chris@16
|
1817 {
|
Chris@101
|
1818 container_detail::insert_range_proxy<Allocator, FwdIt, T*> proxy(first);
|
Chris@101
|
1819 return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
|
Chris@101
|
1820 }
|
Chris@101
|
1821 #endif
|
Chris@101
|
1822
|
Chris@101
|
1823 //! <b>Requires</b>: p must be a valid iterator of *this. num, must
|
Chris@101
|
1824 //! be equal to boost::container::iterator_distance(first, last)
|
Chris@101
|
1825 //!
|
Chris@101
|
1826 //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
|
Chris@101
|
1827 //!
|
Chris@101
|
1828 //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
|
Chris@101
|
1829 //!
|
Chris@101
|
1830 //! <b>Throws</b>: If memory allocation throws, T's constructor from a
|
Chris@101
|
1831 //! dereferenced InpIt throws or T's copy/move constructor/assignment throws.
|
Chris@101
|
1832 //!
|
Chris@101
|
1833 //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
|
Chris@101
|
1834 //!
|
Chris@101
|
1835 //! <b>Note</b>: This function avoids a linear operation to calculate boost::container::iterator_distance[first, last)
|
Chris@101
|
1836 //! for forward and bidirectional iterators, and a one by one insertion for input iterators. This is a
|
Chris@101
|
1837 //! a non-standard extension.
|
Chris@101
|
1838 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
Chris@101
|
1839 template <class InIt>
|
Chris@101
|
1840 iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
|
Chris@101
|
1841 {
|
Chris@101
|
1842 BOOST_ASSERT(container_detail::is_input_iterator<InIt>::value ||
|
Chris@101
|
1843 num == static_cast<size_type>(boost::container::iterator_distance(first, last)));
|
Chris@101
|
1844 (void)last;
|
Chris@101
|
1845 container_detail::insert_range_proxy<Allocator, InIt, T*> proxy(first);
|
Chris@101
|
1846 return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy);
|
Chris@101
|
1847 }
|
Chris@101
|
1848 #endif
|
Chris@101
|
1849
|
Chris@101
|
1850 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
Chris@101
|
1851 //! <b>Requires</b>: position must be a valid iterator of *this.
|
Chris@101
|
1852 //!
|
Chris@101
|
1853 //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before position.
|
Chris@101
|
1854 //!
|
Chris@101
|
1855 //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
|
Chris@101
|
1856 //!
|
Chris@101
|
1857 //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
|
Chris@101
|
1858 iterator insert(const_iterator position, std::initializer_list<value_type> il)
|
Chris@101
|
1859 {
|
Chris@101
|
1860 return this->insert(position, il.begin(), il.end());
|
Chris@16
|
1861 }
|
Chris@16
|
1862 #endif
|
Chris@16
|
1863
|
Chris@16
|
1864 //! <b>Effects</b>: Removes the last element from the vector.
|
Chris@16
|
1865 //!
|
Chris@16
|
1866 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1867 //!
|
Chris@16
|
1868 //! <b>Complexity</b>: Constant time.
|
Chris@101
|
1869 void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1870 {
|
Chris@16
|
1871 //Destroy last element
|
Chris@101
|
1872 this->priv_destroy_last();
|
Chris@16
|
1873 }
|
Chris@16
|
1874
|
Chris@16
|
1875 //! <b>Effects</b>: Erases the element at position pos.
|
Chris@16
|
1876 //!
|
Chris@16
|
1877 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1878 //!
|
Chris@16
|
1879 //! <b>Complexity</b>: Linear to the elements between pos and the
|
Chris@16
|
1880 //! last element. Constant if pos is the last element.
|
Chris@16
|
1881 iterator erase(const_iterator position)
|
Chris@16
|
1882 {
|
Chris@101
|
1883 const pointer p = vector_iterator_get_ptr(position);
|
Chris@101
|
1884 T *const pos_ptr = container_detail::to_raw_pointer(p);
|
Chris@101
|
1885 T *const beg_ptr = container_detail::to_raw_pointer(this->m_holder.start());
|
Chris@101
|
1886 T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
|
Chris@16
|
1887 //Move elements forward and destroy last
|
Chris@101
|
1888 this->priv_destroy_last(pos_ptr == new_end_ptr);
|
Chris@101
|
1889 return iterator(p);
|
Chris@16
|
1890 }
|
Chris@16
|
1891
|
Chris@16
|
1892 //! <b>Effects</b>: Erases the elements pointed by [first, last).
|
Chris@16
|
1893 //!
|
Chris@16
|
1894 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1895 //!
|
Chris@16
|
1896 //! <b>Complexity</b>: Linear to the distance between first and last
|
Chris@16
|
1897 //! plus linear to the elements between pos and the last element.
|
Chris@16
|
1898 iterator erase(const_iterator first, const_iterator last)
|
Chris@16
|
1899 {
|
Chris@16
|
1900 if (first != last){
|
Chris@101
|
1901 T* const old_end_ptr = this->back_raw();
|
Chris@101
|
1902 T* const first_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(first));
|
Chris@101
|
1903 T* const last_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(last));
|
Chris@101
|
1904 T* const ptr = container_detail::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
|
Chris@101
|
1905 this->priv_destroy_last_n(old_end_ptr - ptr, last_ptr == old_end_ptr);
|
Chris@16
|
1906 }
|
Chris@16
|
1907 return iterator(vector_iterator_get_ptr(first));
|
Chris@16
|
1908 }
|
Chris@16
|
1909
|
Chris@16
|
1910 //! <b>Effects</b>: Swaps the contents of *this and x.
|
Chris@16
|
1911 //!
|
Chris@16
|
1912 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1913 //!
|
Chris@16
|
1914 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1915 void swap(vector& x)
|
Chris@101
|
1916 BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value
|
Chris@101
|
1917 || allocator_traits_type::is_always_equal::value) &&
|
Chris@101
|
1918 !container_detail::is_version<Allocator, 0>::value))
|
Chris@16
|
1919 {
|
Chris@101
|
1920 this->priv_swap(x, container_detail::bool_<container_detail::is_version<Allocator, 0>::value>());
|
Chris@16
|
1921 }
|
Chris@16
|
1922
|
Chris@16
|
1923 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
1924
|
Chris@16
|
1925 //! <b>Effects</b>: Swaps the contents of *this and x.
|
Chris@16
|
1926 //!
|
Chris@101
|
1927 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1928 //!
|
Chris@16
|
1929 //! <b>Complexity</b>: Linear
|
Chris@16
|
1930 //!
|
Chris@101
|
1931 //! <b>Note</b>: Non-standard extension to support static_vector
|
Chris@16
|
1932 template<class OtherAllocator>
|
Chris@101
|
1933 void swap(vector<T, OtherAllocator> & x
|
Chris@101
|
1934 , typename container_detail::enable_if_c
|
Chris@101
|
1935 < container_detail::is_version<OtherAllocator, 0>::value &&
|
Chris@101
|
1936 !container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0
|
Chris@101
|
1937 )
|
Chris@101
|
1938 { this->m_holder.deep_swap(x.m_holder); }
|
Chris@16
|
1939
|
Chris@16
|
1940 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
1941
|
Chris@16
|
1942 //! <b>Effects</b>: Erases all the elements of the vector.
|
Chris@16
|
1943 //!
|
Chris@16
|
1944 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1945 //!
|
Chris@101
|
1946 //! <b>Complexity</b>: Linear to the number of elements in the container.
|
Chris@101
|
1947 void clear() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
1948 { this->priv_destroy_all(); }
|
Chris@16
|
1949
|
Chris@101
|
1950 //! <b>Effects</b>: Returns true if x and y are equal
|
Chris@101
|
1951 //!
|
Chris@101
|
1952 //! <b>Complexity</b>: Linear to the number of elements in the container.
|
Chris@101
|
1953 friend bool operator==(const vector& x, const vector& y)
|
Chris@101
|
1954 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
|
Chris@101
|
1955
|
Chris@101
|
1956 //! <b>Effects</b>: Returns true if x and y are unequal
|
Chris@101
|
1957 //!
|
Chris@101
|
1958 //! <b>Complexity</b>: Linear to the number of elements in the container.
|
Chris@101
|
1959 friend bool operator!=(const vector& x, const vector& y)
|
Chris@101
|
1960 { return !(x == y); }
|
Chris@101
|
1961
|
Chris@101
|
1962 //! <b>Effects</b>: Returns true if x is less than y
|
Chris@101
|
1963 //!
|
Chris@101
|
1964 //! <b>Complexity</b>: Linear to the number of elements in the container.
|
Chris@101
|
1965 friend bool operator<(const vector& x, const vector& y)
|
Chris@101
|
1966 {
|
Chris@101
|
1967 const_iterator first1(x.cbegin()), first2(y.cbegin());
|
Chris@101
|
1968 const const_iterator last1(x.cend()), last2(y.cend());
|
Chris@101
|
1969 for ( ; (first1 != last1) && (first2 != last2); ++first1, ++first2 ) {
|
Chris@101
|
1970 if (*first1 < *first2) return true;
|
Chris@101
|
1971 if (*first2 < *first1) return false;
|
Chris@101
|
1972 }
|
Chris@101
|
1973 return (first1 == last1) && (first2 != last2);
|
Chris@101
|
1974 }
|
Chris@101
|
1975
|
Chris@101
|
1976 //! <b>Effects</b>: Returns true if x is greater than y
|
Chris@101
|
1977 //!
|
Chris@101
|
1978 //! <b>Complexity</b>: Linear to the number of elements in the container.
|
Chris@101
|
1979 friend bool operator>(const vector& x, const vector& y)
|
Chris@101
|
1980 { return y < x; }
|
Chris@101
|
1981
|
Chris@101
|
1982 //! <b>Effects</b>: Returns true if x is equal or less than y
|
Chris@101
|
1983 //!
|
Chris@101
|
1984 //! <b>Complexity</b>: Linear to the number of elements in the container.
|
Chris@101
|
1985 friend bool operator<=(const vector& x, const vector& y)
|
Chris@101
|
1986 { return !(y < x); }
|
Chris@101
|
1987
|
Chris@101
|
1988 //! <b>Effects</b>: Returns true if x is equal or greater than y
|
Chris@101
|
1989 //!
|
Chris@101
|
1990 //! <b>Complexity</b>: Linear to the number of elements in the container.
|
Chris@101
|
1991 friend bool operator>=(const vector& x, const vector& y)
|
Chris@101
|
1992 { return !(x < y); }
|
Chris@101
|
1993
|
Chris@101
|
1994 //! <b>Effects</b>: x.swap(y)
|
Chris@101
|
1995 //!
|
Chris@101
|
1996 //! <b>Complexity</b>: Constant.
|
Chris@101
|
1997 friend void swap(vector& x, vector& y)
|
Chris@101
|
1998 { x.swap(y); }
|
Chris@101
|
1999
|
Chris@101
|
2000 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@101
|
2001 //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
|
Chris@101
|
2002 //! effect. Otherwise, it is a request for allocation of additional memory
|
Chris@101
|
2003 //! (memory expansion) that will not invalidate iterators.
|
Chris@101
|
2004 //! If the request is successful, then capacity() is greater than or equal to
|
Chris@101
|
2005 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
|
Chris@101
|
2006 //!
|
Chris@101
|
2007 //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
|
Chris@101
|
2008 //!
|
Chris@101
|
2009 //! <b>Note</b>: Non-standard extension.
|
Chris@101
|
2010 bool stable_reserve(size_type new_cap)
|
Chris@101
|
2011 {
|
Chris@101
|
2012 const size_type cp = this->capacity();
|
Chris@101
|
2013 return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(new_cap - cp));
|
Chris@101
|
2014 }
|
Chris@16
|
2015
|
Chris@16
|
2016 //Absolutely experimental. This function might change, disappear or simply crash!
|
Chris@16
|
2017 template<class BiDirPosConstIt, class BiDirValueIt>
|
Chris@101
|
2018 void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
|
Chris@16
|
2019 {
|
Chris@101
|
2020 const size_type old_size_pos = this->size();
|
Chris@101
|
2021 this->reserve(old_size_pos + element_count);
|
Chris@101
|
2022 T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
|
Chris@101
|
2023 size_type insertions_left = element_count;
|
Chris@101
|
2024 size_type next_pos = old_size_pos;
|
Chris@101
|
2025 size_type hole_size = element_count;
|
Chris@16
|
2026
|
Chris@101
|
2027 //Exception rollback. If any copy throws before the hole is filled, values
|
Chris@101
|
2028 //already inserted/copied at the end of the buffer will be destroyed.
|
Chris@101
|
2029 typename value_traits::ArrayDestructor past_hole_values_destroyer
|
Chris@101
|
2030 (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
|
Chris@101
|
2031 //Loop for each insertion backwards, first moving the elements after the insertion point,
|
Chris@101
|
2032 //then inserting the element.
|
Chris@101
|
2033 while(insertions_left){
|
Chris@101
|
2034 size_type pos = static_cast<size_type>(*(--last_position_it));
|
Chris@101
|
2035 while(pos == size_type(-1)){
|
Chris@101
|
2036 --last_value_it;
|
Chris@101
|
2037 pos = static_cast<size_type>(*(--last_position_it));
|
Chris@101
|
2038 }
|
Chris@101
|
2039
|
Chris@101
|
2040 BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos);
|
Chris@101
|
2041 //If needed shift the range after the insertion point and the previous insertion point.
|
Chris@101
|
2042 //Function will take care if the shift crosses the size() boundary, using copy/move
|
Chris@101
|
2043 //or uninitialized copy/move if necessary.
|
Chris@101
|
2044 size_type new_hole_size = (pos != next_pos)
|
Chris@101
|
2045 ? priv_insert_ordered_at_shift_range(pos, next_pos, this->size(), insertions_left)
|
Chris@101
|
2046 : hole_size
|
Chris@101
|
2047 ;
|
Chris@101
|
2048 if(new_hole_size > 0){
|
Chris@101
|
2049 //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
|
Chris@101
|
2050 past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
|
Chris@101
|
2051 //Insert the new value in the hole
|
Chris@101
|
2052 allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
|
Chris@101
|
2053 --new_hole_size;
|
Chris@101
|
2054 if(new_hole_size == 0){
|
Chris@101
|
2055 //Hole was just filled, disable exception rollback and change vector size
|
Chris@101
|
2056 past_hole_values_destroyer.release();
|
Chris@101
|
2057 this->m_holder.m_size += element_count;
|
Chris@101
|
2058 }
|
Chris@101
|
2059 else{
|
Chris@101
|
2060 //The hole was reduced by the new insertion by one
|
Chris@101
|
2061 past_hole_values_destroyer.increment_size_backwards(size_type(1u));
|
Chris@101
|
2062 }
|
Chris@101
|
2063 }
|
Chris@101
|
2064 else{
|
Chris@101
|
2065 if(hole_size){
|
Chris@101
|
2066 //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
|
Chris@101
|
2067 past_hole_values_destroyer.release();
|
Chris@101
|
2068 this->m_holder.m_size += element_count;
|
Chris@101
|
2069 }
|
Chris@101
|
2070 //Insert the new value in the already constructed range
|
Chris@101
|
2071 begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
|
Chris@101
|
2072 }
|
Chris@101
|
2073 --insertions_left;
|
Chris@101
|
2074 hole_size = new_hole_size;
|
Chris@101
|
2075 next_pos = pos;
|
Chris@101
|
2076 }
|
Chris@16
|
2077 }
|
Chris@16
|
2078
|
Chris@16
|
2079 private:
|
Chris@16
|
2080
|
Chris@101
|
2081 bool room_enough() const
|
Chris@101
|
2082 { return this->m_holder.m_size < this->m_holder.capacity(); }
|
Chris@101
|
2083
|
Chris@101
|
2084 pointer back_ptr() const
|
Chris@101
|
2085 { return this->m_holder.start() + this->m_holder.m_size; }
|
Chris@101
|
2086
|
Chris@101
|
2087 T* back_raw() const
|
Chris@101
|
2088 { return container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; }
|
Chris@101
|
2089
|
Chris@101
|
2090 size_type priv_index_of(pointer p) const
|
Chris@101
|
2091 {
|
Chris@101
|
2092 BOOST_ASSERT(this->m_holder.start() <= p);
|
Chris@101
|
2093 BOOST_ASSERT(p <= (this->m_holder.start()+this->size()));
|
Chris@101
|
2094 return static_cast<size_type>(p - this->m_holder.start());
|
Chris@101
|
2095 }
|
Chris@101
|
2096
|
Chris@101
|
2097 template<class OtherAllocator>
|
Chris@16
|
2098 void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
|
Chris@16
|
2099 , typename container_detail::enable_if_c
|
Chris@101
|
2100 < container_detail::is_version<OtherAllocator, 0>::value >::type * = 0)
|
Chris@16
|
2101 {
|
Chris@101
|
2102 if(!container_detail::is_same<OtherAllocator, allocator_type>::value &&
|
Chris@101
|
2103 this->capacity() < x.size()){
|
Chris@16
|
2104 throw_bad_alloc();
|
Chris@16
|
2105 }
|
Chris@16
|
2106 T* const this_start = container_detail::to_raw_pointer(m_holder.start());
|
Chris@16
|
2107 T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
|
Chris@16
|
2108 const size_type this_sz = m_holder.m_size;
|
Chris@16
|
2109 const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
|
Chris@16
|
2110 boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
|
Chris@16
|
2111 this->m_holder.m_size = other_sz;
|
Chris@16
|
2112 }
|
Chris@16
|
2113
|
Chris@101
|
2114 template<class OtherAllocator>
|
Chris@101
|
2115 void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
|
Chris@16
|
2116 , typename container_detail::enable_if_c
|
Chris@101
|
2117 < !container_detail::is_version<OtherAllocator, 0>::value &&
|
Chris@101
|
2118 container_detail::is_same<OtherAllocator, allocator_type>::value>::type * = 0)
|
Chris@16
|
2119 {
|
Chris@16
|
2120 //for move constructor, no aliasing (&x != this) is assummed.
|
Chris@101
|
2121 BOOST_ASSERT(this != &x);
|
Chris@16
|
2122 allocator_type &this_alloc = this->m_holder.alloc();
|
Chris@16
|
2123 allocator_type &x_alloc = x.m_holder.alloc();
|
Chris@101
|
2124 const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
|
Chris@101
|
2125
|
Chris@101
|
2126 const bool is_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc);
|
Chris@101
|
2127 const bool is_propagable_from_t = is_propagable_from(this_alloc, m_holder.start(), x_alloc, propagate_alloc);
|
Chris@101
|
2128 const bool are_both_propagable = is_propagable_from_x && is_propagable_from_t;
|
Chris@101
|
2129
|
Chris@101
|
2130 //Resources can be transferred if both allocators are
|
Chris@101
|
2131 //going to be equal after this function (either propagated or already equal)
|
Chris@101
|
2132 if(are_both_propagable){
|
Chris@16
|
2133 //Destroy objects but retain memory in case x reuses it in the future
|
Chris@16
|
2134 this->clear();
|
Chris@101
|
2135 this->m_holder.swap_resources(x.m_holder);
|
Chris@16
|
2136 }
|
Chris@101
|
2137 else if(is_propagable_from_x){
|
Chris@101
|
2138 this->clear();
|
Chris@101
|
2139 this->m_holder.alloc().deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
|
Chris@101
|
2140 this->m_holder.steal_resources(x.m_holder);
|
Chris@101
|
2141 }
|
Chris@101
|
2142 //Else do a one by one move
|
Chris@16
|
2143 else{
|
Chris@101
|
2144 this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin()))
|
Chris@101
|
2145 , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end() ))
|
Chris@101
|
2146 );
|
Chris@16
|
2147 }
|
Chris@101
|
2148 //Move allocator if needed
|
Chris@101
|
2149 container_detail::move_alloc(this_alloc, x_alloc, container_detail::bool_<propagate_alloc>());
|
Chris@16
|
2150 }
|
Chris@16
|
2151
|
Chris@101
|
2152 template<class OtherAllocator>
|
Chris@101
|
2153 void priv_copy_assign(const vector<T, OtherAllocator> &x
|
Chris@16
|
2154 , typename container_detail::enable_if_c
|
Chris@101
|
2155 < container_detail::is_version<OtherAllocator, 0>::value >::type * = 0)
|
Chris@16
|
2156 {
|
Chris@101
|
2157 if(!container_detail::is_same<OtherAllocator, allocator_type>::value &&
|
Chris@101
|
2158 this->capacity() < x.size()){
|
Chris@101
|
2159 throw_bad_alloc();
|
Chris@101
|
2160 }
|
Chris@16
|
2161 T* const this_start = container_detail::to_raw_pointer(m_holder.start());
|
Chris@16
|
2162 T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
|
Chris@16
|
2163 const size_type this_sz = m_holder.m_size;
|
Chris@16
|
2164 const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
|
Chris@16
|
2165 boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
|
Chris@16
|
2166 this->m_holder.m_size = other_sz;
|
Chris@16
|
2167 }
|
Chris@16
|
2168
|
Chris@101
|
2169 template<class OtherAllocator>
|
Chris@101
|
2170 void priv_copy_assign(const vector<T, OtherAllocator> &x
|
Chris@16
|
2171 , typename container_detail::enable_if_c
|
Chris@101
|
2172 < !container_detail::is_version<OtherAllocator, 0>::value &&
|
Chris@101
|
2173 container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0)
|
Chris@16
|
2174 {
|
Chris@16
|
2175 allocator_type &this_alloc = this->m_holder.alloc();
|
Chris@16
|
2176 const allocator_type &x_alloc = x.m_holder.alloc();
|
Chris@16
|
2177 container_detail::bool_<allocator_traits_type::
|
Chris@16
|
2178 propagate_on_container_copy_assignment::value> flag;
|
Chris@16
|
2179 if(flag && this_alloc != x_alloc){
|
Chris@16
|
2180 this->clear();
|
Chris@16
|
2181 this->shrink_to_fit();
|
Chris@16
|
2182 }
|
Chris@16
|
2183 container_detail::assign_alloc(this_alloc, x_alloc, flag);
|
Chris@16
|
2184 this->assign( container_detail::to_raw_pointer(x.m_holder.start())
|
Chris@16
|
2185 , container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size));
|
Chris@16
|
2186 }
|
Chris@16
|
2187
|
Chris@101
|
2188 template<class Vector> //Template it to avoid it in explicit instantiations
|
Chris@101
|
2189 void priv_swap(Vector &x, container_detail::true_type) //version_0
|
Chris@101
|
2190 { this->m_holder.deep_swap(x.m_holder); }
|
Chris@101
|
2191
|
Chris@101
|
2192 template<class Vector> //Template it to avoid it in explicit instantiations
|
Chris@101
|
2193 void priv_swap(Vector &x, container_detail::false_type) //version_N
|
Chris@16
|
2194 {
|
Chris@101
|
2195 const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
|
Chris@101
|
2196 if(are_swap_propagable( this->get_stored_allocator(), this->m_holder.start()
|
Chris@101
|
2197 , x.get_stored_allocator(), this->m_holder.start(), propagate_alloc)){
|
Chris@101
|
2198 //Just swap internals
|
Chris@101
|
2199 this->m_holder.swap_resources(x.m_holder);
|
Chris@101
|
2200 }
|
Chris@101
|
2201 else{
|
Chris@101
|
2202 //Else swap element by element...
|
Chris@101
|
2203 bool const t_smaller = this->size() < x.size();
|
Chris@101
|
2204 vector &sml = t_smaller ? *this : x;
|
Chris@101
|
2205 vector &big = t_smaller ? x : *this;
|
Chris@101
|
2206
|
Chris@101
|
2207 size_type const common_elements = sml.size();
|
Chris@101
|
2208 for(size_type i = 0; i != common_elements; ++i){
|
Chris@101
|
2209 boost::adl_move_swap(sml[i], big[i]);
|
Chris@101
|
2210 }
|
Chris@101
|
2211 //... and move-insert the remaining range
|
Chris@101
|
2212 sml.insert( sml.cend()
|
Chris@101
|
2213 , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.nth(common_elements)))
|
Chris@101
|
2214 , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.end()))
|
Chris@101
|
2215 );
|
Chris@101
|
2216 }
|
Chris@101
|
2217 //And now swap the allocator
|
Chris@101
|
2218 container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), container_detail::bool_<propagate_alloc>());
|
Chris@16
|
2219 }
|
Chris@16
|
2220
|
Chris@101
|
2221 void priv_reserve_no_capacity(size_type, version_0)
|
Chris@101
|
2222 { throw_bad_alloc(); }
|
Chris@101
|
2223
|
Chris@101
|
2224 container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
|
Chris@101
|
2225 {
|
Chris@101
|
2226 return container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
|
Chris@101
|
2227 (::boost::make_move_iterator((T *)0));
|
Chris@101
|
2228 }
|
Chris@101
|
2229
|
Chris@101
|
2230 void priv_reserve_no_capacity(size_type new_cap, version_1)
|
Chris@16
|
2231 {
|
Chris@16
|
2232 //There is not enough memory, allocate a new buffer
|
Chris@101
|
2233 //Pass the hint so that allocators can take advantage of this.
|
Chris@101
|
2234 pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start);
|
Chris@101
|
2235 //We will reuse insert code, so create a dummy input iterator
|
Chris@101
|
2236 this->priv_forward_range_insert_new_allocation
|
Chris@101
|
2237 ( container_detail::to_raw_pointer(p), new_cap, this->back_raw(), 0, this->priv_dummy_empty_proxy());
|
Chris@16
|
2238 }
|
Chris@16
|
2239
|
Chris@101
|
2240 void priv_reserve_no_capacity(size_type new_cap, version_2)
|
Chris@16
|
2241 {
|
Chris@16
|
2242 //There is not enough memory, allocate a new
|
Chris@16
|
2243 //buffer or expand the old one.
|
Chris@16
|
2244 bool same_buffer_start;
|
Chris@16
|
2245 size_type real_cap = 0;
|
Chris@101
|
2246 pointer reuse = 0;
|
Chris@101
|
2247 pointer const ret(this->m_holder.allocation_command(allocate_new | expand_fwd | expand_bwd, new_cap, real_cap = new_cap, reuse));
|
Chris@16
|
2248
|
Chris@16
|
2249 //Check for forward expansion
|
Chris@101
|
2250 same_buffer_start = reuse && this->m_holder.start() == ret;
|
Chris@16
|
2251 if(same_buffer_start){
|
Chris@16
|
2252 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2253 ++this->num_expand_fwd;
|
Chris@16
|
2254 #endif
|
Chris@16
|
2255 this->m_holder.capacity(real_cap);
|
Chris@16
|
2256 }
|
Chris@101
|
2257 else{ //If there is no forward expansion, move objects, we will reuse insertion code
|
Chris@101
|
2258 T * const new_mem = container_detail::to_raw_pointer(ret);
|
Chris@101
|
2259 T * const ins_pos = this->back_raw();
|
Chris@101
|
2260 if(reuse){ //Backwards (and possibly forward) expansion
|
Chris@16
|
2261 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2262 ++this->num_expand_bwd;
|
Chris@16
|
2263 #endif
|
Chris@16
|
2264 this->priv_forward_range_insert_expand_backwards
|
Chris@101
|
2265 ( new_mem , real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
|
Chris@16
|
2266 }
|
Chris@101
|
2267 else{ //New buffer
|
Chris@16
|
2268 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2269 ++this->num_alloc;
|
Chris@16
|
2270 #endif
|
Chris@101
|
2271 this->priv_forward_range_insert_new_allocation
|
Chris@101
|
2272 ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
|
Chris@16
|
2273 }
|
Chris@16
|
2274 }
|
Chris@16
|
2275 }
|
Chris@16
|
2276
|
Chris@101
|
2277 void priv_destroy_last() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
2278 {
|
Chris@101
|
2279 if(!value_traits::trivial_dctr){
|
Chris@101
|
2280 value_type* const p = this->back_raw() - 1;
|
Chris@101
|
2281 allocator_traits_type::destroy(this->get_stored_allocator(), p);
|
Chris@101
|
2282 }
|
Chris@101
|
2283 --this->m_holder.m_size;
|
Chris@16
|
2284 }
|
Chris@16
|
2285
|
Chris@101
|
2286 void priv_destroy_last(const bool moved) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
2287 {
|
Chris@101
|
2288 (void)moved;
|
Chris@101
|
2289 if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
|
Chris@101
|
2290 value_type* const p = this->back_raw() - 1;
|
Chris@16
|
2291 allocator_traits_type::destroy(this->get_stored_allocator(), p);
|
Chris@101
|
2292 }
|
Chris@101
|
2293 --this->m_holder.m_size;
|
Chris@16
|
2294 }
|
Chris@16
|
2295
|
Chris@101
|
2296 void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
2297 {
|
Chris@101
|
2298 BOOST_ASSERT(n <= this->m_holder.m_size);
|
Chris@101
|
2299 if(!value_traits::trivial_dctr){
|
Chris@101
|
2300 T* const destroy_pos = container_detail::to_raw_pointer(this->m_holder.start()) + (this->m_holder.m_size-n);
|
Chris@101
|
2301 boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
|
Chris@101
|
2302 }
|
Chris@16
|
2303 this->m_holder.m_size -= n;
|
Chris@16
|
2304 }
|
Chris@16
|
2305
|
Chris@101
|
2306 void priv_destroy_last_n(const size_type n, const bool moved) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@101
|
2307 {
|
Chris@101
|
2308 BOOST_ASSERT(n <= this->m_holder.m_size);
|
Chris@101
|
2309 (void)moved;
|
Chris@101
|
2310 if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
|
Chris@101
|
2311 T* const destroy_pos = container_detail::to_raw_pointer(this->m_holder.start()) + (this->m_holder.m_size-n);
|
Chris@101
|
2312 boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
|
Chris@101
|
2313 }
|
Chris@101
|
2314 this->m_holder.m_size -= n;
|
Chris@101
|
2315 }
|
Chris@101
|
2316
|
Chris@101
|
2317 template<class InpIt>
|
Chris@101
|
2318 void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
|
Chris@101
|
2319 {
|
Chris@101
|
2320 T* const old_end_pos = this->back_raw();
|
Chris@101
|
2321 T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
|
Chris@101
|
2322 this->m_holder.m_size += new_end_pos - old_end_pos;
|
Chris@101
|
2323 }
|
Chris@101
|
2324
|
Chris@101
|
2325 void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
2326 {
|
Chris@16
|
2327 boost::container::destroy_alloc_n
|
Chris@16
|
2328 (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size);
|
Chris@16
|
2329 this->m_holder.m_size = 0;
|
Chris@16
|
2330 }
|
Chris@16
|
2331
|
Chris@16
|
2332 template<class U>
|
Chris@16
|
2333 iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x)
|
Chris@16
|
2334 {
|
Chris@16
|
2335 return this->priv_forward_range_insert
|
Chris@101
|
2336 ( vector_iterator_get_ptr(p), 1, container_detail::get_insert_value_proxy<T*, Allocator>(::boost::forward<U>(x)));
|
Chris@16
|
2337 }
|
Chris@16
|
2338
|
Chris@101
|
2339 container_detail::insert_copy_proxy<Allocator, T*> priv_single_insert_proxy(const T &x)
|
Chris@101
|
2340 { return container_detail::insert_copy_proxy<Allocator, T*> (x); }
|
Chris@101
|
2341
|
Chris@101
|
2342 container_detail::insert_move_proxy<Allocator, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
|
Chris@101
|
2343 { return container_detail::insert_move_proxy<Allocator, T*> (x); }
|
Chris@101
|
2344
|
Chris@101
|
2345 template <class U>
|
Chris@101
|
2346 void priv_push_back(BOOST_FWD_REF(U) u)
|
Chris@16
|
2347 {
|
Chris@101
|
2348 if (BOOST_LIKELY(this->room_enough())){
|
Chris@16
|
2349 //There is more memory, just construct a new object at the end
|
Chris@16
|
2350 allocator_traits_type::construct
|
Chris@16
|
2351 ( this->m_holder.alloc()
|
Chris@16
|
2352 , container_detail::to_raw_pointer(this->m_holder.start() + this->m_holder.m_size)
|
Chris@101
|
2353 , ::boost::forward<U>(u) );
|
Chris@16
|
2354 ++this->m_holder.m_size;
|
Chris@16
|
2355 }
|
Chris@16
|
2356 else{
|
Chris@101
|
2357 this->priv_forward_range_insert_no_capacity
|
Chris@101
|
2358 ( this->back_ptr(), 1
|
Chris@101
|
2359 , this->priv_single_insert_proxy(::boost::forward<U>(u)), alloc_version());
|
Chris@16
|
2360 }
|
Chris@16
|
2361 }
|
Chris@16
|
2362
|
Chris@101
|
2363 container_detail::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x)
|
Chris@101
|
2364 { return container_detail::insert_n_copies_proxy<Allocator, T*>(x); }
|
Chris@101
|
2365
|
Chris@101
|
2366 container_detail::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t)
|
Chris@101
|
2367 { return container_detail::insert_default_initialized_n_proxy<Allocator, T*>(); }
|
Chris@101
|
2368
|
Chris@101
|
2369 container_detail::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t)
|
Chris@101
|
2370 { return container_detail::insert_value_initialized_n_proxy<Allocator, T*>(); }
|
Chris@101
|
2371
|
Chris@101
|
2372 template <class U>
|
Chris@101
|
2373 void priv_resize(size_type new_size, const U& u)
|
Chris@16
|
2374 {
|
Chris@101
|
2375 const size_type sz = this->size();
|
Chris@101
|
2376 if (new_size < sz){
|
Chris@101
|
2377 //Destroy last elements
|
Chris@101
|
2378 this->priv_destroy_last_n(sz - new_size);
|
Chris@16
|
2379 }
|
Chris@16
|
2380 else{
|
Chris@101
|
2381 const size_type n = new_size - this->size();
|
Chris@101
|
2382 this->priv_forward_range_insert_at_end(n, this->priv_resize_proxy(u), alloc_version());
|
Chris@16
|
2383 }
|
Chris@16
|
2384 }
|
Chris@16
|
2385
|
Chris@101
|
2386 void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
2387 {}
|
Chris@16
|
2388
|
Chris@101
|
2389 void priv_shrink_to_fit(version_1)
|
Chris@16
|
2390 {
|
Chris@16
|
2391 const size_type cp = this->m_holder.capacity();
|
Chris@16
|
2392 if(cp){
|
Chris@16
|
2393 const size_type sz = this->size();
|
Chris@16
|
2394 if(!sz){
|
Chris@16
|
2395 this->m_holder.alloc().deallocate(this->m_holder.m_start, cp);
|
Chris@16
|
2396 this->m_holder.m_start = pointer();
|
Chris@16
|
2397 this->m_holder.m_capacity = 0;
|
Chris@16
|
2398 }
|
Chris@16
|
2399 else if(sz < cp){
|
Chris@16
|
2400 //Allocate a new buffer.
|
Chris@101
|
2401 //Pass the hint so that allocators can take advantage of this.
|
Chris@101
|
2402 pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), sz, this->m_holder.m_start);
|
Chris@16
|
2403
|
Chris@16
|
2404 //We will reuse insert code, so create a dummy input iterator
|
Chris@16
|
2405 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2406 ++this->num_alloc;
|
Chris@16
|
2407 #endif
|
Chris@16
|
2408 this->priv_forward_range_insert_new_allocation
|
Chris@101
|
2409 ( container_detail::to_raw_pointer(p), sz
|
Chris@16
|
2410 , container_detail::to_raw_pointer(this->m_holder.start())
|
Chris@101
|
2411 , 0, this->priv_dummy_empty_proxy());
|
Chris@16
|
2412 }
|
Chris@16
|
2413 }
|
Chris@16
|
2414 }
|
Chris@16
|
2415
|
Chris@101
|
2416 void priv_shrink_to_fit(version_2) BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
2417 {
|
Chris@16
|
2418 const size_type cp = this->m_holder.capacity();
|
Chris@16
|
2419 if(cp){
|
Chris@16
|
2420 const size_type sz = this->size();
|
Chris@16
|
2421 if(!sz){
|
Chris@16
|
2422 this->m_holder.alloc().deallocate(this->m_holder.m_start, cp);
|
Chris@16
|
2423 this->m_holder.m_start = pointer();
|
Chris@16
|
2424 this->m_holder.m_capacity = 0;
|
Chris@16
|
2425 }
|
Chris@16
|
2426 else{
|
Chris@101
|
2427 size_type received_size = sz;
|
Chris@101
|
2428 pointer reuse(this->m_holder.start());
|
Chris@16
|
2429 if(this->m_holder.allocation_command
|
Chris@101
|
2430 (shrink_in_place | nothrow_allocation, cp, received_size, reuse)){
|
Chris@16
|
2431 this->m_holder.capacity(received_size);
|
Chris@16
|
2432 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2433 ++this->num_shrink;
|
Chris@16
|
2434 #endif
|
Chris@16
|
2435 }
|
Chris@16
|
2436 }
|
Chris@16
|
2437 }
|
Chris@16
|
2438 }
|
Chris@16
|
2439
|
Chris@16
|
2440 template <class InsertionProxy>
|
Chris@16
|
2441 iterator priv_forward_range_insert_no_capacity
|
Chris@101
|
2442 (const pointer &pos, const size_type, const InsertionProxy , version_0)
|
Chris@16
|
2443 {
|
Chris@16
|
2444 throw_bad_alloc();
|
Chris@16
|
2445 return iterator(pos);
|
Chris@16
|
2446 }
|
Chris@16
|
2447
|
Chris@16
|
2448 template <class InsertionProxy>
|
Chris@16
|
2449 iterator priv_forward_range_insert_no_capacity
|
Chris@101
|
2450 (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
|
Chris@16
|
2451 {
|
Chris@16
|
2452 //Check if we have enough memory or try to expand current memory
|
Chris@16
|
2453 const size_type n_pos = pos - this->m_holder.start();
|
Chris@16
|
2454 T *const raw_pos = container_detail::to_raw_pointer(pos);
|
Chris@16
|
2455
|
Chris@16
|
2456 const size_type new_cap = this->m_holder.next_capacity(n);
|
Chris@101
|
2457 //Pass the hint so that allocators can take advantage of this.
|
Chris@101
|
2458 T * const new_buf = container_detail::to_raw_pointer(allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start));
|
Chris@16
|
2459 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2460 ++this->num_alloc;
|
Chris@16
|
2461 #endif
|
Chris@16
|
2462 this->priv_forward_range_insert_new_allocation
|
Chris@16
|
2463 ( new_buf, new_cap, raw_pos, n, insert_range_proxy);
|
Chris@16
|
2464 return iterator(this->m_holder.start() + n_pos);
|
Chris@16
|
2465 }
|
Chris@16
|
2466
|
Chris@16
|
2467 template <class InsertionProxy>
|
Chris@16
|
2468 iterator priv_forward_range_insert_no_capacity
|
Chris@101
|
2469 (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
|
Chris@16
|
2470 {
|
Chris@16
|
2471 //Check if we have enough memory or try to expand current memory
|
Chris@16
|
2472 T *const raw_pos = container_detail::to_raw_pointer(pos);
|
Chris@16
|
2473 const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
|
Chris@16
|
2474
|
Chris@16
|
2475 //There is not enough memory, allocate a new
|
Chris@16
|
2476 //buffer or expand the old one.
|
Chris@101
|
2477 size_type real_cap = this->m_holder.next_capacity(n);
|
Chris@101
|
2478 pointer reuse(this->m_holder.start());
|
Chris@101
|
2479 pointer const ret (this->m_holder.allocation_command
|
Chris@101
|
2480 (allocate_new | expand_fwd | expand_bwd, this->m_holder.m_size + n, real_cap, reuse));
|
Chris@16
|
2481
|
Chris@16
|
2482 //Buffer reallocated
|
Chris@101
|
2483 if(reuse){
|
Chris@16
|
2484 //Forward expansion, delay insertion
|
Chris@101
|
2485 if(this->m_holder.start() == ret){
|
Chris@16
|
2486 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2487 ++this->num_expand_fwd;
|
Chris@16
|
2488 #endif
|
Chris@16
|
2489 this->m_holder.capacity(real_cap);
|
Chris@16
|
2490 //Expand forward
|
Chris@16
|
2491 this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
|
Chris@16
|
2492 }
|
Chris@16
|
2493 //Backwards (and possibly forward) expansion
|
Chris@16
|
2494 else{
|
Chris@16
|
2495 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2496 ++this->num_expand_bwd;
|
Chris@16
|
2497 #endif
|
Chris@16
|
2498 this->priv_forward_range_insert_expand_backwards
|
Chris@101
|
2499 (container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
|
Chris@16
|
2500 }
|
Chris@16
|
2501 }
|
Chris@16
|
2502 //New buffer
|
Chris@16
|
2503 else{
|
Chris@16
|
2504 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
2505 ++this->num_alloc;
|
Chris@16
|
2506 #endif
|
Chris@16
|
2507 this->priv_forward_range_insert_new_allocation
|
Chris@101
|
2508 ( container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
|
Chris@16
|
2509 }
|
Chris@16
|
2510
|
Chris@16
|
2511 return iterator(this->m_holder.start() + n_pos);
|
Chris@16
|
2512 }
|
Chris@16
|
2513
|
Chris@16
|
2514 template <class InsertionProxy>
|
Chris@16
|
2515 iterator priv_forward_range_insert
|
Chris@101
|
2516 (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
|
Chris@16
|
2517 {
|
Chris@101
|
2518 BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
|
Chris@16
|
2519 //Check if we have enough memory or try to expand current memory
|
Chris@16
|
2520 const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
|
Chris@16
|
2521
|
Chris@16
|
2522 bool same_buffer_start = n <= remaining;
|
Chris@16
|
2523 if (!same_buffer_start){
|
Chris@16
|
2524 return priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
|
Chris@16
|
2525 }
|
Chris@16
|
2526 else{
|
Chris@16
|
2527 //Expand forward
|
Chris@16
|
2528 T *const raw_pos = container_detail::to_raw_pointer(pos);
|
Chris@16
|
2529 const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
|
Chris@16
|
2530 this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
|
Chris@16
|
2531 return iterator(this->m_holder.start() + n_pos);
|
Chris@16
|
2532 }
|
Chris@16
|
2533 }
|
Chris@16
|
2534
|
Chris@16
|
2535 template <class InsertionProxy>
|
Chris@16
|
2536 iterator priv_forward_range_insert_at_end
|
Chris@101
|
2537 (const size_type n, const InsertionProxy insert_range_proxy, version_0)
|
Chris@16
|
2538 {
|
Chris@16
|
2539 //Check if we have enough memory or try to expand current memory
|
Chris@16
|
2540 const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
|
Chris@16
|
2541
|
Chris@16
|
2542 if (n > remaining){
|
Chris@16
|
2543 //This will trigger an error
|
Chris@16
|
2544 throw_bad_alloc();
|
Chris@16
|
2545 }
|
Chris@16
|
2546 this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
|
Chris@16
|
2547 return this->end();
|
Chris@16
|
2548 }
|
Chris@16
|
2549
|
Chris@101
|
2550 template <class InsertionProxy, class AllocVersion>
|
Chris@16
|
2551 iterator priv_forward_range_insert_at_end
|
Chris@101
|
2552 (const size_type n, const InsertionProxy insert_range_proxy, AllocVersion)
|
Chris@16
|
2553 {
|
Chris@101
|
2554 return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy);
|
Chris@16
|
2555 }
|
Chris@16
|
2556
|
Chris@16
|
2557 //Absolutely experimental. This function might change, disappear or simply crash!
|
Chris@16
|
2558 template<class BiDirPosConstIt, class BiDirSkipConstIt, class BiDirValueIt>
|
Chris@16
|
2559 void priv_insert_ordered_at( size_type element_count, BiDirPosConstIt last_position_it
|
Chris@16
|
2560 , bool do_skip, BiDirSkipConstIt last_skip_it, BiDirValueIt last_value_it)
|
Chris@16
|
2561 {
|
Chris@16
|
2562 const size_type old_size_pos = this->size();
|
Chris@16
|
2563 this->reserve(old_size_pos + element_count);
|
Chris@16
|
2564 T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
|
Chris@16
|
2565 size_type insertions_left = element_count;
|
Chris@16
|
2566 size_type next_pos = old_size_pos;
|
Chris@16
|
2567 size_type hole_size = element_count;
|
Chris@16
|
2568
|
Chris@16
|
2569 //Exception rollback. If any copy throws before the hole is filled, values
|
Chris@16
|
2570 //already inserted/copied at the end of the buffer will be destroyed.
|
Chris@16
|
2571 typename value_traits::ArrayDestructor past_hole_values_destroyer
|
Chris@16
|
2572 (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
|
Chris@16
|
2573 //Loop for each insertion backwards, first moving the elements after the insertion point,
|
Chris@16
|
2574 //then inserting the element.
|
Chris@16
|
2575 while(insertions_left){
|
Chris@16
|
2576 if(do_skip){
|
Chris@16
|
2577 size_type n = *(--last_skip_it);
|
Chris@101
|
2578 boost::container::iterator_advance(last_value_it, -difference_type(n));
|
Chris@16
|
2579 }
|
Chris@16
|
2580 const size_type pos = static_cast<size_type>(*(--last_position_it));
|
Chris@16
|
2581 BOOST_ASSERT(pos <= old_size_pos);
|
Chris@16
|
2582 //If needed shift the range after the insertion point and the previous insertion point.
|
Chris@16
|
2583 //Function will take care if the shift crosses the size() boundary, using copy/move
|
Chris@16
|
2584 //or uninitialized copy/move if necessary.
|
Chris@16
|
2585 size_type new_hole_size = (pos != next_pos)
|
Chris@16
|
2586 ? priv_insert_ordered_at_shift_range(pos, next_pos, this->size(), insertions_left)
|
Chris@16
|
2587 : hole_size
|
Chris@16
|
2588 ;
|
Chris@16
|
2589 if(new_hole_size > 0){
|
Chris@16
|
2590 //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
|
Chris@16
|
2591 past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
|
Chris@16
|
2592 //Insert the new value in the hole
|
Chris@16
|
2593 allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
|
Chris@16
|
2594 --new_hole_size;
|
Chris@16
|
2595 if(new_hole_size == 0){
|
Chris@16
|
2596 //Hole was just filled, disable exception rollback and change vector size
|
Chris@16
|
2597 past_hole_values_destroyer.release();
|
Chris@16
|
2598 this->m_holder.m_size += element_count;
|
Chris@16
|
2599 }
|
Chris@16
|
2600 else{
|
Chris@16
|
2601 //The hole was reduced by the new insertion by one
|
Chris@16
|
2602 past_hole_values_destroyer.increment_size_backwards(size_type(1u));
|
Chris@16
|
2603 }
|
Chris@16
|
2604 }
|
Chris@16
|
2605 else{
|
Chris@16
|
2606 if(hole_size){
|
Chris@16
|
2607 //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
|
Chris@16
|
2608 past_hole_values_destroyer.release();
|
Chris@16
|
2609 this->m_holder.m_size += element_count;
|
Chris@16
|
2610 }
|
Chris@16
|
2611 //Insert the new value in the already constructed range
|
Chris@16
|
2612 begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
|
Chris@16
|
2613 }
|
Chris@16
|
2614 --insertions_left;
|
Chris@16
|
2615 hole_size = new_hole_size;
|
Chris@16
|
2616 next_pos = pos;
|
Chris@16
|
2617 }
|
Chris@16
|
2618 }
|
Chris@16
|
2619
|
Chris@16
|
2620 //Takes the range pointed by [first_pos, last_pos) and shifts it to the right
|
Chris@16
|
2621 //by 'shift_count'. 'limit_pos' marks the end of constructed elements.
|
Chris@16
|
2622 //
|
Chris@16
|
2623 //Precondition: first_pos <= last_pos <= limit_pos
|
Chris@16
|
2624 //
|
Chris@16
|
2625 //The shift operation might cross limit_pos so elements to moved beyond limit_pos
|
Chris@16
|
2626 //are uninitialized_moved with an allocator. Other elements are moved.
|
Chris@16
|
2627 //
|
Chris@16
|
2628 //The shift operation might left uninitialized elements after limit_pos
|
Chris@16
|
2629 //and the number of uninitialized elements is returned by the function.
|
Chris@16
|
2630 //
|
Chris@16
|
2631 //Old situation:
|
Chris@16
|
2632 // first_pos last_pos old_limit
|
Chris@101
|
2633 // | | |
|
Chris@16
|
2634 // ____________V_______V__________________V_____________
|
Chris@16
|
2635 //| prefix | range | suffix |raw_mem ~
|
Chris@16
|
2636 //|____________|_______|__________________|_____________~
|
Chris@16
|
2637 //
|
Chris@101
|
2638 //New situation in Case A (hole_size == 0):
|
Chris@16
|
2639 // range is moved through move assignments
|
Chris@16
|
2640 //
|
Chris@16
|
2641 // first_pos last_pos limit_pos
|
Chris@101
|
2642 // | | |
|
Chris@16
|
2643 // ____________V_______V__________________V_____________
|
Chris@16
|
2644 //| prefix' | | | range |suffix'|raw_mem ~
|
Chris@16
|
2645 //|________________+______|___^___|_______|_____________~
|
Chris@16
|
2646 // | |
|
Chris@101
|
2647 // |_>_>_>_>_>^
|
Chris@16
|
2648 //
|
Chris@16
|
2649 //
|
Chris@16
|
2650 //New situation in Case B (hole_size > 0):
|
Chris@16
|
2651 // range is moved through uninitialized moves
|
Chris@16
|
2652 //
|
Chris@16
|
2653 // first_pos last_pos limit_pos
|
Chris@101
|
2654 // | | |
|
Chris@16
|
2655 // ____________V_______V__________________V________________
|
Chris@16
|
2656 //| prefix' | | | [hole] | range |
|
Chris@16
|
2657 //|_______________________________________|________|___^___|
|
Chris@16
|
2658 // | |
|
Chris@16
|
2659 // |_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_^
|
Chris@16
|
2660 //
|
Chris@16
|
2661 //New situation in Case C (hole_size == 0):
|
Chris@16
|
2662 // range is moved through move assignments and uninitialized moves
|
Chris@16
|
2663 //
|
Chris@16
|
2664 // first_pos last_pos limit_pos
|
Chris@101
|
2665 // | | |
|
Chris@16
|
2666 // ____________V_______V__________________V___
|
Chris@16
|
2667 //| prefix' | | | range |
|
Chris@16
|
2668 //|___________________________________|___^___|
|
Chris@16
|
2669 // | |
|
Chris@16
|
2670 // |_>_>_>_>_>_>_>_>_>_>_>^
|
Chris@16
|
2671 size_type priv_insert_ordered_at_shift_range
|
Chris@16
|
2672 (size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
|
Chris@16
|
2673 {
|
Chris@16
|
2674 BOOST_ASSERT(first_pos <= last_pos);
|
Chris@16
|
2675 BOOST_ASSERT(last_pos <= limit_pos);
|
Chris@16
|
2676 //
|
Chris@16
|
2677 T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
|
Chris@16
|
2678 T* const first_ptr = begin_ptr + first_pos;
|
Chris@16
|
2679 T* const last_ptr = begin_ptr + last_pos;
|
Chris@16
|
2680
|
Chris@16
|
2681 size_type hole_size = 0;
|
Chris@101
|
2682 //Case A:
|
Chris@16
|
2683 if((last_pos + shift_count) <= limit_pos){
|
Chris@16
|
2684 //All move assigned
|
Chris@101
|
2685 boost::container::move_backward(first_ptr, last_ptr, last_ptr + shift_count);
|
Chris@16
|
2686 }
|
Chris@16
|
2687 //Case B:
|
Chris@16
|
2688 else if((first_pos + shift_count) >= limit_pos){
|
Chris@16
|
2689 //All uninitialized_moved
|
Chris@16
|
2690 ::boost::container::uninitialized_move_alloc
|
Chris@16
|
2691 (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
|
Chris@16
|
2692 hole_size = last_pos + shift_count - limit_pos;
|
Chris@16
|
2693 }
|
Chris@16
|
2694 //Case C:
|
Chris@16
|
2695 else{
|
Chris@16
|
2696 //Some uninitialized_moved
|
Chris@16
|
2697 T* const limit_ptr = begin_ptr + limit_pos;
|
Chris@16
|
2698 T* const boundary_ptr = limit_ptr - shift_count;
|
Chris@16
|
2699 ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
|
Chris@16
|
2700 //The rest is move assigned
|
Chris@101
|
2701 boost::container::move_backward(first_ptr, boundary_ptr, limit_ptr);
|
Chris@16
|
2702 }
|
Chris@16
|
2703 return hole_size;
|
Chris@16
|
2704 }
|
Chris@16
|
2705
|
Chris@16
|
2706 private:
|
Chris@16
|
2707 template <class InsertionProxy>
|
Chris@16
|
2708 void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy)
|
Chris@16
|
2709 {
|
Chris@101
|
2710 T* const old_finish = this->back_raw();
|
Chris@101
|
2711 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
|
Chris@16
|
2712 this->m_holder.m_size += n;
|
Chris@16
|
2713 }
|
Chris@16
|
2714
|
Chris@16
|
2715 template <class InsertionProxy>
|
Chris@16
|
2716 void priv_forward_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
Chris@16
|
2717 {
|
Chris@16
|
2718 //n can't be 0, because there is nothing to do in that case
|
Chris@16
|
2719 if(!n) return;
|
Chris@16
|
2720 //There is enough memory
|
Chris@101
|
2721 T* const old_finish = this->back_raw();
|
Chris@16
|
2722 const size_type elems_after = old_finish - pos;
|
Chris@16
|
2723
|
Chris@16
|
2724 if (!elems_after){
|
Chris@101
|
2725 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
|
Chris@16
|
2726 this->m_holder.m_size += n;
|
Chris@16
|
2727 }
|
Chris@16
|
2728 else if (elems_after >= n){
|
Chris@16
|
2729 //New elements can be just copied.
|
Chris@16
|
2730 //Move to uninitialized memory last objects
|
Chris@16
|
2731 ::boost::container::uninitialized_move_alloc
|
Chris@16
|
2732 (this->m_holder.alloc(), old_finish - n, old_finish, old_finish);
|
Chris@16
|
2733 this->m_holder.m_size += n;
|
Chris@16
|
2734 //Copy previous to last objects to the initialized end
|
Chris@101
|
2735 boost::container::move_backward(pos, old_finish - n, old_finish);
|
Chris@16
|
2736 //Insert new objects in the pos
|
Chris@101
|
2737 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n);
|
Chris@16
|
2738 }
|
Chris@16
|
2739 else {
|
Chris@16
|
2740 //The new elements don't fit in the [pos, end()) range.
|
Chris@16
|
2741
|
Chris@16
|
2742 //Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
|
Chris@16
|
2743 ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pos, old_finish, pos + n);
|
Chris@16
|
2744 BOOST_TRY{
|
Chris@16
|
2745 //Copy first new elements in pos (gap is still there)
|
Chris@101
|
2746 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elems_after);
|
Chris@16
|
2747 //Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
|
Chris@101
|
2748 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n - elems_after);
|
Chris@16
|
2749 this->m_holder.m_size += n;
|
Chris@16
|
2750 }
|
Chris@16
|
2751 BOOST_CATCH(...){
|
Chris@16
|
2752 boost::container::destroy_alloc_n(this->get_stored_allocator(), pos + n, elems_after);
|
Chris@16
|
2753 BOOST_RETHROW
|
Chris@16
|
2754 }
|
Chris@16
|
2755 BOOST_CATCH_END
|
Chris@16
|
2756 }
|
Chris@16
|
2757 }
|
Chris@16
|
2758
|
Chris@16
|
2759 template <class InsertionProxy>
|
Chris@16
|
2760 void priv_forward_range_insert_new_allocation
|
Chris@16
|
2761 (T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
Chris@16
|
2762 {
|
Chris@16
|
2763 //n can be zero, if we want to reallocate!
|
Chris@16
|
2764 T *new_finish = new_start;
|
Chris@16
|
2765 T *old_finish;
|
Chris@16
|
2766 //Anti-exception rollbacks
|
Chris@101
|
2767 typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, this->m_holder.alloc(), new_cap);
|
Chris@101
|
2768 typename value_traits::ArrayDestructor new_values_destroyer(new_start, this->m_holder.alloc(), 0u);
|
Chris@16
|
2769
|
Chris@16
|
2770 //Initialize with [begin(), pos) old buffer
|
Chris@16
|
2771 //the start of the new buffer
|
Chris@101
|
2772 T * const old_buffer = container_detail::to_raw_pointer(this->m_holder.start());
|
Chris@16
|
2773 if(old_buffer){
|
Chris@16
|
2774 new_finish = ::boost::container::uninitialized_move_alloc
|
Chris@16
|
2775 (this->m_holder.alloc(), container_detail::to_raw_pointer(this->m_holder.start()), pos, old_finish = new_finish);
|
Chris@101
|
2776 new_values_destroyer.increment_size(new_finish - old_finish);
|
Chris@16
|
2777 }
|
Chris@16
|
2778 //Initialize new objects, starting from previous point
|
Chris@101
|
2779 old_finish = new_finish;
|
Chris@101
|
2780 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
|
Chris@16
|
2781 new_finish += n;
|
Chris@101
|
2782 new_values_destroyer.increment_size(new_finish - old_finish);
|
Chris@16
|
2783 //Initialize from the rest of the old buffer,
|
Chris@16
|
2784 //starting from previous point
|
Chris@16
|
2785 if(old_buffer){
|
Chris@16
|
2786 new_finish = ::boost::container::uninitialized_move_alloc
|
Chris@16
|
2787 (this->m_holder.alloc(), pos, old_buffer + this->m_holder.m_size, new_finish);
|
Chris@16
|
2788 //Destroy and deallocate old elements
|
Chris@16
|
2789 //If there is allocated memory, destroy and deallocate
|
Chris@16
|
2790 if(!value_traits::trivial_dctr_after_move)
|
Chris@16
|
2791 boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
|
Chris@16
|
2792 this->m_holder.alloc().deallocate(this->m_holder.start(), this->m_holder.capacity());
|
Chris@16
|
2793 }
|
Chris@16
|
2794 this->m_holder.start(new_start);
|
Chris@16
|
2795 this->m_holder.m_size = new_finish - new_start;
|
Chris@16
|
2796 this->m_holder.capacity(new_cap);
|
Chris@16
|
2797 //All construction successful, disable rollbacks
|
Chris@101
|
2798 new_values_destroyer.release();
|
Chris@101
|
2799 new_buffer_deallocator.release();
|
Chris@16
|
2800 }
|
Chris@16
|
2801
|
Chris@16
|
2802 template <class InsertionProxy>
|
Chris@16
|
2803 void priv_forward_range_insert_expand_backwards
|
Chris@16
|
2804 (T* const new_start, const size_type new_capacity,
|
Chris@16
|
2805 T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
Chris@16
|
2806 {
|
Chris@16
|
2807 //n can be zero to just expand capacity
|
Chris@16
|
2808 //Backup old data
|
Chris@16
|
2809 T* const old_start = container_detail::to_raw_pointer(this->m_holder.start());
|
Chris@16
|
2810 const size_type old_size = this->m_holder.m_size;
|
Chris@101
|
2811 T* const old_finish = old_start + old_size;
|
Chris@16
|
2812
|
Chris@16
|
2813 //We can have 8 possibilities:
|
Chris@16
|
2814 const size_type elemsbefore = static_cast<size_type>(pos - old_start);
|
Chris@16
|
2815 const size_type s_before = static_cast<size_type>(old_start - new_start);
|
Chris@16
|
2816 const size_type before_plus_new = elemsbefore + n;
|
Chris@16
|
2817
|
Chris@16
|
2818 //Update the vector buffer information to a safe state
|
Chris@16
|
2819 this->m_holder.start(new_start);
|
Chris@16
|
2820 this->m_holder.capacity(new_capacity);
|
Chris@16
|
2821 this->m_holder.m_size = 0;
|
Chris@16
|
2822
|
Chris@16
|
2823 //If anything goes wrong, this object will destroy
|
Chris@16
|
2824 //all the old objects to fulfill previous vector state
|
Chris@101
|
2825 typename value_traits::ArrayDestructor old_values_destroyer(old_start, this->m_holder.alloc(), old_size);
|
Chris@16
|
2826 //Check if s_before is big enough to hold the beginning of old data + new data
|
Chris@16
|
2827 if(s_before >= before_plus_new){
|
Chris@16
|
2828 //Copy first old values before pos, after that the new objects
|
Chris@101
|
2829 T *const new_elem_pos =
|
Chris@101
|
2830 ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), old_start, pos, new_start);
|
Chris@16
|
2831 this->m_holder.m_size = elemsbefore;
|
Chris@101
|
2832 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_elem_pos, n);
|
Chris@101
|
2833 this->m_holder.m_size = before_plus_new;
|
Chris@101
|
2834 const size_type new_size = old_size + n;
|
Chris@16
|
2835 //Check if s_before is so big that even copying the old data + new data
|
Chris@16
|
2836 //there is a gap between the new data and the old data
|
Chris@16
|
2837 if(s_before >= new_size){
|
Chris@16
|
2838 //Old situation:
|
Chris@16
|
2839 // _________________________________________________________
|
Chris@16
|
2840 //| raw_mem | old_begin | old_end |
|
Chris@16
|
2841 //| __________________________________|___________|_________|
|
Chris@16
|
2842 //
|
Chris@16
|
2843 //New situation:
|
Chris@16
|
2844 // _________________________________________________________
|
Chris@16
|
2845 //| old_begin | new | old_end | raw_mem |
|
Chris@16
|
2846 //|___________|__________|_________|________________________|
|
Chris@16
|
2847 //
|
Chris@16
|
2848 //Now initialize the rest of memory with the last old values
|
Chris@101
|
2849 if(before_plus_new != new_size){ //Special case to avoid operations in back insertion
|
Chris@101
|
2850 ::boost::container::uninitialized_move_alloc
|
Chris@101
|
2851 (this->m_holder.alloc(), pos, old_finish, new_start + before_plus_new);
|
Chris@101
|
2852 //All new elements correctly constructed, avoid new element destruction
|
Chris@101
|
2853 this->m_holder.m_size = new_size;
|
Chris@101
|
2854 }
|
Chris@16
|
2855 //Old values destroyed automatically with "old_values_destroyer"
|
Chris@16
|
2856 //when "old_values_destroyer" goes out of scope unless the have trivial
|
Chris@16
|
2857 //destructor after move.
|
Chris@16
|
2858 if(value_traits::trivial_dctr_after_move)
|
Chris@16
|
2859 old_values_destroyer.release();
|
Chris@16
|
2860 }
|
Chris@16
|
2861 //s_before is so big that divides old_end
|
Chris@16
|
2862 else{
|
Chris@16
|
2863 //Old situation:
|
Chris@16
|
2864 // __________________________________________________
|
Chris@16
|
2865 //| raw_mem | old_begin | old_end |
|
Chris@16
|
2866 //| ___________________________|___________|_________|
|
Chris@16
|
2867 //
|
Chris@16
|
2868 //New situation:
|
Chris@16
|
2869 // __________________________________________________
|
Chris@16
|
2870 //| old_begin | new | old_end | raw_mem |
|
Chris@16
|
2871 //|___________|__________|_________|_________________|
|
Chris@16
|
2872 //
|
Chris@16
|
2873 //Now initialize the rest of memory with the last old values
|
Chris@16
|
2874 //All new elements correctly constructed, avoid new element destruction
|
Chris@16
|
2875 const size_type raw_gap = s_before - before_plus_new;
|
Chris@101
|
2876 if(!value_traits::trivial_dctr){
|
Chris@101
|
2877 //Now initialize the rest of s_before memory with the
|
Chris@101
|
2878 //first of elements after new values
|
Chris@101
|
2879 ::boost::container::uninitialized_move_alloc_n
|
Chris@101
|
2880 (this->m_holder.alloc(), pos, raw_gap, new_start + before_plus_new);
|
Chris@101
|
2881 //Now we have a contiguous buffer so program trailing element destruction
|
Chris@101
|
2882 //and update size to the final size.
|
Chris@101
|
2883 old_values_destroyer.shrink_forward(new_size-s_before);
|
Chris@101
|
2884 this->m_holder.m_size = new_size;
|
Chris@101
|
2885 //Now move remaining last objects in the old buffer begin
|
Chris@101
|
2886 ::boost::container::move(pos + raw_gap, old_finish, old_start);
|
Chris@101
|
2887 //Once moved, avoid calling the destructors if trivial after move
|
Chris@101
|
2888 if(value_traits::trivial_dctr_after_move){
|
Chris@101
|
2889 old_values_destroyer.release();
|
Chris@101
|
2890 }
|
Chris@101
|
2891 }
|
Chris@101
|
2892 else{ //If trivial destructor, we can uninitialized copy + copy in a single uninitialized copy
|
Chris@101
|
2893 ::boost::container::uninitialized_move_alloc_n
|
Chris@101
|
2894 (this->m_holder.alloc(), pos, old_finish - pos, new_start + before_plus_new);
|
Chris@101
|
2895 this->m_holder.m_size = new_size;
|
Chris@101
|
2896 old_values_destroyer.release();
|
Chris@101
|
2897 }
|
Chris@16
|
2898 }
|
Chris@16
|
2899 }
|
Chris@16
|
2900 else{
|
Chris@16
|
2901 //Check if we have to do the insertion in two phases
|
Chris@16
|
2902 //since maybe s_before is not big enough and
|
Chris@16
|
2903 //the buffer was expanded both sides
|
Chris@16
|
2904 //
|
Chris@16
|
2905 //Old situation:
|
Chris@16
|
2906 // _________________________________________________
|
Chris@16
|
2907 //| raw_mem | old_begin + old_end | raw_mem |
|
Chris@16
|
2908 //|_________|_____________________|_________________|
|
Chris@16
|
2909 //
|
Chris@16
|
2910 //New situation with do_after:
|
Chris@16
|
2911 // _________________________________________________
|
Chris@16
|
2912 //| old_begin + new + old_end | raw_mem |
|
Chris@16
|
2913 //|___________________________________|_____________|
|
Chris@16
|
2914 //
|
Chris@16
|
2915 //New without do_after:
|
Chris@16
|
2916 // _________________________________________________
|
Chris@16
|
2917 //| old_begin + new + old_end | raw_mem |
|
Chris@16
|
2918 //|____________________________|____________________|
|
Chris@16
|
2919 //
|
Chris@16
|
2920 const bool do_after = n > s_before;
|
Chris@16
|
2921
|
Chris@16
|
2922 //Now we can have two situations: the raw_mem of the
|
Chris@16
|
2923 //beginning divides the old_begin, or the new elements:
|
Chris@16
|
2924 if (s_before <= elemsbefore) {
|
Chris@16
|
2925 //The raw memory divides the old_begin group:
|
Chris@16
|
2926 //
|
Chris@16
|
2927 //If we need two phase construction (do_after)
|
Chris@16
|
2928 //new group is divided in new = new_beg + new_end groups
|
Chris@16
|
2929 //In this phase only new_beg will be inserted
|
Chris@16
|
2930 //
|
Chris@16
|
2931 //Old situation:
|
Chris@16
|
2932 // _________________________________________________
|
Chris@16
|
2933 //| raw_mem | old_begin | old_end | raw_mem |
|
Chris@16
|
2934 //|_________|___________|_________|_________________|
|
Chris@16
|
2935 //
|
Chris@16
|
2936 //New situation with do_after(1):
|
Chris@16
|
2937 //This is not definitive situation, the second phase
|
Chris@16
|
2938 //will include
|
Chris@16
|
2939 // _________________________________________________
|
Chris@16
|
2940 //| old_begin | new_beg | old_end | raw_mem |
|
Chris@16
|
2941 //|___________|_________|_________|_________________|
|
Chris@16
|
2942 //
|
Chris@16
|
2943 //New situation without do_after:
|
Chris@16
|
2944 // _________________________________________________
|
Chris@16
|
2945 //| old_begin | new | old_end | raw_mem |
|
Chris@16
|
2946 //|___________|_____|_________|_____________________|
|
Chris@16
|
2947 //
|
Chris@16
|
2948 //Copy the first part of old_begin to raw_mem
|
Chris@16
|
2949 ::boost::container::uninitialized_move_alloc_n
|
Chris@16
|
2950 (this->m_holder.alloc(), old_start, s_before, new_start);
|
Chris@16
|
2951 //The buffer is all constructed until old_end,
|
Chris@101
|
2952 //so program trailing destruction and assign final size
|
Chris@101
|
2953 //if !do_after, s_before+n otherwise.
|
Chris@101
|
2954 size_type new_1st_range;
|
Chris@16
|
2955 if(do_after){
|
Chris@101
|
2956 new_1st_range = s_before;
|
Chris@101
|
2957 //release destroyer and update size
|
Chris@101
|
2958 old_values_destroyer.release();
|
Chris@16
|
2959 }
|
Chris@16
|
2960 else{
|
Chris@101
|
2961 new_1st_range = n;
|
Chris@101
|
2962 if(value_traits::trivial_dctr_after_move)
|
Chris@101
|
2963 old_values_destroyer.release();
|
Chris@101
|
2964 else{
|
Chris@101
|
2965 old_values_destroyer.shrink_forward(old_size - (s_before - n));
|
Chris@101
|
2966 }
|
Chris@101
|
2967 }
|
Chris@101
|
2968 this->m_holder.m_size = old_size + new_1st_range;
|
Chris@101
|
2969 //Now copy the second part of old_begin overwriting itself
|
Chris@101
|
2970 T *const next = ::boost::container::move(old_start + s_before, pos, old_start);
|
Chris@101
|
2971 //Now copy the new_beg elements
|
Chris@101
|
2972 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), next, new_1st_range);
|
Chris@101
|
2973
|
Chris@101
|
2974 //If there is no after work and the last old part needs to be moved to front, do it
|
Chris@101
|
2975 if(!do_after && (n != s_before)){
|
Chris@16
|
2976 //Now displace old_end elements
|
Chris@101
|
2977 ::boost::container::move(pos, old_finish, next + new_1st_range);
|
Chris@16
|
2978 }
|
Chris@16
|
2979 }
|
Chris@16
|
2980 else {
|
Chris@16
|
2981 //If we have to expand both sides,
|
Chris@16
|
2982 //we will play if the first new values so
|
Chris@16
|
2983 //calculate the upper bound of new values
|
Chris@16
|
2984
|
Chris@16
|
2985 //The raw memory divides the new elements
|
Chris@16
|
2986 //
|
Chris@16
|
2987 //If we need two phase construction (do_after)
|
Chris@16
|
2988 //new group is divided in new = new_beg + new_end groups
|
Chris@16
|
2989 //In this phase only new_beg will be inserted
|
Chris@16
|
2990 //
|
Chris@16
|
2991 //Old situation:
|
Chris@16
|
2992 // _______________________________________________________
|
Chris@16
|
2993 //| raw_mem | old_begin | old_end | raw_mem |
|
Chris@16
|
2994 //|_______________|___________|_________|_________________|
|
Chris@16
|
2995 //
|
Chris@16
|
2996 //New situation with do_after():
|
Chris@16
|
2997 // ____________________________________________________
|
Chris@16
|
2998 //| old_begin | new_beg | old_end | raw_mem |
|
Chris@16
|
2999 //|___________|_______________|_________|______________|
|
Chris@16
|
3000 //
|
Chris@16
|
3001 //New situation without do_after:
|
Chris@16
|
3002 // ______________________________________________________
|
Chris@16
|
3003 //| old_begin | new | old_end | raw_mem |
|
Chris@16
|
3004 //|___________|_____|_________|__________________________|
|
Chris@16
|
3005 //
|
Chris@16
|
3006 //First copy whole old_begin and part of new to raw_mem
|
Chris@16
|
3007 T * const new_pos = ::boost::container::uninitialized_move_alloc
|
Chris@16
|
3008 (this->m_holder.alloc(), old_start, pos, new_start);
|
Chris@16
|
3009 this->m_holder.m_size = elemsbefore;
|
Chris@16
|
3010 const size_type mid_n = s_before - elemsbefore;
|
Chris@101
|
3011 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_pos, mid_n);
|
Chris@16
|
3012 //The buffer is all constructed until old_end,
|
Chris@16
|
3013 //release destroyer
|
Chris@16
|
3014 this->m_holder.m_size = old_size + s_before;
|
Chris@16
|
3015 old_values_destroyer.release();
|
Chris@16
|
3016
|
Chris@16
|
3017 if(do_after){
|
Chris@16
|
3018 //Copy new_beg part
|
Chris@101
|
3019 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, elemsbefore);
|
Chris@16
|
3020 }
|
Chris@16
|
3021 else{
|
Chris@16
|
3022 //Copy all new elements
|
Chris@16
|
3023 const size_type rest_new = n - mid_n;
|
Chris@101
|
3024 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new);
|
Chris@101
|
3025 T* const move_start = old_start + rest_new;
|
Chris@16
|
3026 //Displace old_end
|
Chris@101
|
3027 T* const move_end = ::boost::container::move(pos, old_finish, move_start);
|
Chris@16
|
3028 //Destroy remaining moved elements from old_end except if they
|
Chris@16
|
3029 //have trivial destructor after being moved
|
Chris@16
|
3030 size_type n_destroy = s_before - n;
|
Chris@16
|
3031 if(!value_traits::trivial_dctr_after_move)
|
Chris@16
|
3032 boost::container::destroy_alloc_n(this->get_stored_allocator(), move_end, n_destroy);
|
Chris@16
|
3033 this->m_holder.m_size -= n_destroy;
|
Chris@16
|
3034 }
|
Chris@16
|
3035 }
|
Chris@16
|
3036
|
Chris@16
|
3037 //This is only executed if two phase construction is needed
|
Chris@16
|
3038 if(do_after){
|
Chris@16
|
3039 //The raw memory divides the new elements
|
Chris@16
|
3040 //
|
Chris@16
|
3041 //Old situation:
|
Chris@16
|
3042 // ______________________________________________________
|
Chris@16
|
3043 //| raw_mem | old_begin | old_end | raw_mem |
|
Chris@16
|
3044 //|______________|___________|____________|______________|
|
Chris@16
|
3045 //
|
Chris@16
|
3046 //New situation with do_after(1):
|
Chris@16
|
3047 // _______________________________________________________
|
Chris@16
|
3048 //| old_begin + new_beg | new_end |old_end | raw_mem |
|
Chris@16
|
3049 //|__________________________|_________|________|_________|
|
Chris@16
|
3050 //
|
Chris@16
|
3051 //New situation with do_after(2):
|
Chris@16
|
3052 // ______________________________________________________
|
Chris@16
|
3053 //| old_begin + new | old_end |raw |
|
Chris@16
|
3054 //|_______________________________________|_________|____|
|
Chris@16
|
3055 //
|
Chris@16
|
3056 const size_type n_after = n - s_before;
|
Chris@16
|
3057 const size_type elemsafter = old_size - elemsbefore;
|
Chris@16
|
3058
|
Chris@16
|
3059 //We can have two situations:
|
Chris@16
|
3060 if (elemsafter >= n_after){
|
Chris@16
|
3061 //The raw_mem from end will divide displaced old_end
|
Chris@16
|
3062 //
|
Chris@16
|
3063 //Old situation:
|
Chris@16
|
3064 // ______________________________________________________
|
Chris@16
|
3065 //| raw_mem | old_begin | old_end | raw_mem |
|
Chris@16
|
3066 //|______________|___________|____________|______________|
|
Chris@16
|
3067 //
|
Chris@16
|
3068 //New situation with do_after(1):
|
Chris@16
|
3069 // _______________________________________________________
|
Chris@16
|
3070 //| old_begin + new_beg | new_end |old_end | raw_mem |
|
Chris@16
|
3071 //|__________________________|_________|________|_________|
|
Chris@16
|
3072 //
|
Chris@16
|
3073 //First copy the part of old_end raw_mem
|
Chris@16
|
3074 T* finish_n = old_finish - n_after;
|
Chris@16
|
3075 ::boost::container::uninitialized_move_alloc
|
Chris@16
|
3076 (this->m_holder.alloc(), finish_n, old_finish, old_finish);
|
Chris@16
|
3077 this->m_holder.m_size += n_after;
|
Chris@16
|
3078 //Displace the rest of old_end to the new position
|
Chris@101
|
3079 boost::container::move_backward(pos, finish_n, old_finish);
|
Chris@16
|
3080 //Now overwrite with new_end
|
Chris@16
|
3081 //The new_end part is [first + (n - n_after), last)
|
Chris@101
|
3082 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n_after);
|
Chris@16
|
3083 }
|
Chris@16
|
3084 else {
|
Chris@16
|
3085 //The raw_mem from end will divide new_end part
|
Chris@16
|
3086 //
|
Chris@16
|
3087 //Old situation:
|
Chris@16
|
3088 // _____________________________________________________________
|
Chris@16
|
3089 //| raw_mem | old_begin | old_end | raw_mem |
|
Chris@16
|
3090 //|______________|___________|____________|_____________________|
|
Chris@16
|
3091 //
|
Chris@16
|
3092 //New situation with do_after(2):
|
Chris@16
|
3093 // _____________________________________________________________
|
Chris@16
|
3094 //| old_begin + new_beg | new_end |old_end | raw_mem |
|
Chris@16
|
3095 //|__________________________|_______________|________|_________|
|
Chris@16
|
3096 //
|
Chris@16
|
3097
|
Chris@16
|
3098 const size_type mid_last_dist = n_after - elemsafter;
|
Chris@16
|
3099 //First initialize data in raw memory
|
Chris@16
|
3100
|
Chris@16
|
3101 //Copy to the old_end part to the uninitialized zone leaving a gap.
|
Chris@16
|
3102 ::boost::container::uninitialized_move_alloc
|
Chris@16
|
3103 (this->m_holder.alloc(), pos, old_finish, old_finish + mid_last_dist);
|
Chris@16
|
3104
|
Chris@101
|
3105 typename value_traits::ArrayDestructor old_end_destroyer
|
Chris@101
|
3106 (old_finish + mid_last_dist, this->m_holder.alloc(), old_finish - pos);
|
Chris@16
|
3107
|
Chris@101
|
3108 //Copy the first part to the already constructed old_end zone
|
Chris@101
|
3109 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elemsafter);
|
Chris@101
|
3110 //Copy the rest to the uninitialized zone filling the gap
|
Chris@101
|
3111 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, mid_last_dist);
|
Chris@101
|
3112 this->m_holder.m_size += n_after;
|
Chris@101
|
3113 old_end_destroyer.release();
|
Chris@16
|
3114 }
|
Chris@16
|
3115 }
|
Chris@16
|
3116 }
|
Chris@16
|
3117 }
|
Chris@16
|
3118
|
Chris@16
|
3119 void priv_check_range(size_type n) const
|
Chris@16
|
3120 {
|
Chris@16
|
3121 //If n is out of range, throw an out_of_range exception
|
Chris@16
|
3122 if (n >= this->size()){
|
Chris@16
|
3123 throw_out_of_range("vector::at out of range");
|
Chris@16
|
3124 }
|
Chris@16
|
3125 }
|
Chris@16
|
3126
|
Chris@16
|
3127 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
Chris@16
|
3128 public:
|
Chris@16
|
3129 unsigned int num_expand_fwd;
|
Chris@16
|
3130 unsigned int num_expand_bwd;
|
Chris@16
|
3131 unsigned int num_shrink;
|
Chris@16
|
3132 unsigned int num_alloc;
|
Chris@16
|
3133 void reset_alloc_stats()
|
Chris@16
|
3134 { num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0; }
|
Chris@16
|
3135 #endif
|
Chris@101
|
3136 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
3137 };
|
Chris@16
|
3138
|
Chris@101
|
3139 }} //namespace boost::container
|
Chris@16
|
3140
|
Chris@101
|
3141 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
3142
|
Chris@16
|
3143 namespace boost {
|
Chris@16
|
3144
|
Chris@16
|
3145 //!has_trivial_destructor_after_move<> == true_type
|
Chris@16
|
3146 //!specialization for optimizations
|
Chris@16
|
3147 template <class T, class Allocator>
|
Chris@16
|
3148 struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> >
|
Chris@101
|
3149 {
|
Chris@101
|
3150 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
|
Chris@101
|
3151 static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
|
Chris@101
|
3152 ::boost::has_trivial_destructor_after_move<pointer>::value;
|
Chris@101
|
3153 };
|
Chris@16
|
3154
|
Chris@16
|
3155 }
|
Chris@16
|
3156
|
Chris@101
|
3157 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
Chris@16
|
3158
|
Chris@16
|
3159 #include <boost/container/detail/config_end.hpp>
|
Chris@16
|
3160
|
Chris@16
|
3161 #endif // #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
|