1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 // This file comes from SGI's stl_vector.h file. Modified by Ion Gaztanaga.
12 // Renaming, isolating and porting to generic algorithms. Pointer typedef
13 // set to allocator::pointer to allow placing it in shared memory.
15 ///////////////////////////////////////////////////////////////////////////////
17 // Hewlett-Packard Company
19 // Permission to use, copy, modify, distribute and sell this software
20 // and its documentation for any purpose is hereby granted without fee,
21 // provided that the above copyright notice appear in all copies and
22 // that both that copyright notice and this permission notice appear
23 // in supporting documentation. Hewlett-Packard Company makes no
24 // representations about the suitability of this software for any
25 // purpose. It is provided "as is" without express or implied warranty.
29 // Silicon Graphics Computer Systems, Inc.
31 // Permission to use, copy, modify, distribute and sell this software
32 // and its documentation for any purpose is hereby granted without fee,
33 // provided that the above copyright notice appear in all copies and
34 // that both that copyright notice and this permission notice appear
35 // in supporting documentation. Silicon Graphics makes no
36 // representations about the suitability of this software for any
37 // purpose. It is provided "as is" without express or implied warranty.
39 #ifndef BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP
40 #define BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP
42 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
46 #include <boost/interprocess/containers/container/detail/config_begin.hpp>
47 #include <boost/interprocess/containers/container/detail/workaround.hpp>
55 #include <boost/detail/no_exceptions_support.hpp>
56 #include <boost/type_traits/has_trivial_destructor.hpp>
57 #include <boost/type_traits/has_trivial_copy.hpp>
58 #include <boost/type_traits/has_trivial_assign.hpp>
59 #include <boost/type_traits/has_nothrow_copy.hpp>
60 #include <boost/type_traits/has_nothrow_assign.hpp>
61 #include <boost/interprocess/containers/container/detail/version_type.hpp>
62 #include <boost/interprocess/containers/container/detail/allocation_type.hpp>
63 #include <boost/interprocess/containers/container/detail/utilities.hpp>
64 #include <boost/interprocess/containers/container/detail/iterators.hpp>
65 #include <boost/interprocess/containers/container/detail/algorithms.hpp>
66 #include <boost/interprocess/containers/container/detail/destroyers.hpp>
67 #include <boost/interprocess/containers/container/containers_fwd.hpp>
68 #include <boost/interprocess/detail/move.hpp>
69 #include <boost/pointer_to_other.hpp>
70 #include <boost/interprocess/containers/container/detail/mpl.hpp>
71 #include <boost/interprocess/containers/container/detail/advanced_insert_int.hpp>
73 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
75 namespace interprocess
{
78 namespace interprocess_container
{
83 namespace containers_detail
{
85 //! Const vector_iterator used to iterate through a vector.
86 template <class Pointer
>
87 class vector_const_iterator
88 : public std::iterator
<std::random_access_iterator_tag
89 ,const typename
std::iterator_traits
<Pointer
>::value_type
90 ,typename
std::iterator_traits
<Pointer
>::difference_type
91 ,typename
boost::pointer_to_other
93 ,const typename
std::iterator_traits
<Pointer
>::value_type
95 ,const typename
std::iterator_traits
<Pointer
>::value_type
&>
98 typedef const typename
std::iterator_traits
<Pointer
>::value_type value_type
;
99 typedef typename
std::iterator_traits
<Pointer
>::difference_type difference_type
;
100 typedef typename
boost::pointer_to_other
<Pointer
, value_type
>::type pointer
;
101 typedef value_type
& reference
;
108 Pointer
get_ptr() const { return m_ptr
; }
109 explicit vector_const_iterator(Pointer ptr
) : m_ptr(ptr
){}
115 vector_const_iterator() : m_ptr(0){}
117 //Pointer like operators
118 reference
operator*() const
121 const value_type
* operator->() const
122 { return containers_detail::get_pointer(m_ptr
); }
124 reference
operator[](difference_type off
) const
125 { return m_ptr
[off
]; }
127 //Increment / Decrement
128 vector_const_iterator
& operator++()
129 { ++m_ptr
; return *this; }
131 vector_const_iterator
operator++(int)
132 { Pointer tmp
= m_ptr
; ++*this; return vector_const_iterator(tmp
); }
134 vector_const_iterator
& operator--()
135 { --m_ptr
; return *this; }
137 vector_const_iterator
operator--(int)
138 { Pointer tmp
= m_ptr
; --*this; return vector_const_iterator(tmp
); }
141 vector_const_iterator
& operator+=(difference_type off
)
142 { m_ptr
+= off
; return *this; }
144 vector_const_iterator
operator+(difference_type off
) const
145 { return vector_const_iterator(m_ptr
+off
); }
147 friend vector_const_iterator
operator+(difference_type off
, const vector_const_iterator
& right
)
148 { return vector_const_iterator(off
+ right
.m_ptr
); }
150 vector_const_iterator
& operator-=(difference_type off
)
151 { m_ptr
-= off
; return *this; }
153 vector_const_iterator
operator-(difference_type off
) const
154 { return vector_const_iterator(m_ptr
-off
); }
156 difference_type
operator-(const vector_const_iterator
& right
) const
157 { return m_ptr
- right
.m_ptr
; }
159 //Comparison operators
160 bool operator== (const vector_const_iterator
& r
) const
161 { return m_ptr
== r
.m_ptr
; }
163 bool operator!= (const vector_const_iterator
& r
) const
164 { return m_ptr
!= r
.m_ptr
; }
166 bool operator< (const vector_const_iterator
& r
) const
167 { return m_ptr
< r
.m_ptr
; }
169 bool operator<= (const vector_const_iterator
& r
) const
170 { return m_ptr
<= r
.m_ptr
; }
172 bool operator> (const vector_const_iterator
& r
) const
173 { return m_ptr
> r
.m_ptr
; }
175 bool operator>= (const vector_const_iterator
& r
) const
176 { return m_ptr
>= r
.m_ptr
; }
179 //! Iterator used to iterate through a vector
180 template <class Pointer
>
181 class vector_iterator
182 : public vector_const_iterator
<Pointer
>
185 explicit vector_iterator(Pointer ptr
)
186 : vector_const_iterator
<Pointer
>(ptr
)
190 typedef typename
std::iterator_traits
<Pointer
>::value_type value_type
;
191 typedef typename vector_const_iterator
<Pointer
>::difference_type difference_type
;
192 typedef Pointer pointer
;
193 typedef value_type
& reference
;
199 //Pointer like operators
200 reference
operator*() const
201 { return *this->m_ptr
; }
203 value_type
* operator->() const
204 { return containers_detail::get_pointer(this->m_ptr
); }
206 reference
operator[](difference_type off
) const
207 { return this->m_ptr
[off
]; }
209 //Increment / Decrement
210 vector_iterator
& operator++()
211 { ++this->m_ptr
; return *this; }
213 vector_iterator
operator++(int)
214 { pointer tmp
= this->m_ptr
; ++*this; return vector_iterator(tmp
); }
216 vector_iterator
& operator--()
217 { --this->m_ptr
; return *this; }
219 vector_iterator
operator--(int)
220 { vector_iterator tmp
= *this; --*this; return vector_iterator(tmp
); }
223 vector_iterator
& operator+=(difference_type off
)
224 { this->m_ptr
+= off
; return *this; }
226 vector_iterator
operator+(difference_type off
) const
227 { return vector_iterator(this->m_ptr
+off
); }
229 friend vector_iterator
operator+(difference_type off
, const vector_iterator
& right
)
230 { return vector_iterator(off
+ right
.m_ptr
); }
232 vector_iterator
& operator-=(difference_type off
)
233 { this->m_ptr
-= off
; return *this; }
235 vector_iterator
operator-(difference_type off
) const
236 { return vector_iterator(this->m_ptr
-off
); }
238 difference_type
operator-(const vector_const_iterator
<Pointer
>& right
) const
239 { return static_cast<const vector_const_iterator
<Pointer
>&>(*this) - right
; }
242 template <class T
, class A
>
243 struct vector_value_traits
245 typedef T value_type
;
246 typedef A allocator_type
;
247 static const bool trivial_dctr
= boost::has_trivial_destructor
<value_type
>::value
;
248 static const bool trivial_dctr_after_move
=
249 boost::interprocess::has_trivial_destructor_after_move
<value_type
>::value
|| trivial_dctr
;
250 static const bool trivial_copy
= has_trivial_copy
<value_type
>::value
;
251 static const bool nothrow_copy
= has_nothrow_copy
<value_type
>::value
;
252 static const bool trivial_assign
= has_trivial_assign
<value_type
>::value
;
253 static const bool nothrow_assign
= has_nothrow_assign
<value_type
>::value
;
255 //This is the anti-exception array destructor
256 //to deallocate values already constructed
257 typedef typename
containers_detail::if_c
259 ,containers_detail::null_scoped_destructor_n
<allocator_type
>
260 ,containers_detail::scoped_destructor_n
<allocator_type
>
261 >::type OldArrayDestructor
;
262 //This is the anti-exception array destructor
263 //to destroy objects created with copy construction
264 typedef typename
containers_detail::if_c
266 ,containers_detail::null_scoped_destructor_n
<allocator_type
>
267 ,containers_detail::scoped_destructor_n
<allocator_type
>
268 >::type UCopiedArrayDestructor
;
269 //This is the anti-exception array deallocator
270 typedef typename
containers_detail::if_c
272 ,containers_detail::null_scoped_array_deallocator
<allocator_type
>
273 ,containers_detail::scoped_array_deallocator
<allocator_type
>
274 >::type UCopiedArrayDeallocator
;
277 //!This struct deallocates and allocated memory
279 struct vector_alloc_holder
281 typedef typename
A::pointer pointer
;
282 typedef typename
A::size_type size_type
;
283 typedef typename
A::value_type value_type
;
284 typedef vector_value_traits
<value_type
, A
> value_traits
;
286 //Constructor, does not throw
287 vector_alloc_holder(const A
&a
)
291 //Constructor, does not throw
292 vector_alloc_holder(const vector_alloc_holder
<A
> &h
)
293 : members_(h
.alloc())
297 ~vector_alloc_holder()
299 this->prot_destroy_all();
300 this->prot_deallocate();
303 typedef containers_detail::integral_constant
<unsigned, 1> allocator_v1
;
304 typedef containers_detail::integral_constant
<unsigned, 2> allocator_v2
;
305 typedef containers_detail::integral_constant
<unsigned,
306 boost::interprocess_container::containers_detail::version
<A
>::value
> alloc_version
;
307 std::pair
<pointer
, bool>
308 allocation_command(allocation_type command
,
309 size_type limit_size
,
310 size_type preferred_size
,
311 size_type
&received_size
, const pointer
&reuse
= 0)
313 return allocation_command(command
, limit_size
, preferred_size
,
314 received_size
, reuse
, alloc_version());
317 std::pair
<pointer
, bool>
318 allocation_command(allocation_type command
,
319 size_type limit_size
,
320 size_type preferred_size
,
321 size_type
&received_size
,
322 const pointer
&reuse
,
327 if(!(command
& allocate_new
))
328 return std::pair
<pointer
, bool>(pointer(0), 0);
329 received_size
= preferred_size
;
330 return std::make_pair(this->alloc().allocate(received_size
), false);
333 std::pair
<pointer
, bool>
334 allocation_command(allocation_type command
,
335 size_type limit_size
,
336 size_type preferred_size
,
337 size_type
&received_size
,
338 const pointer
&reuse
,
341 return this->alloc().allocation_command
342 (command
, limit_size
, preferred_size
, received_size
, reuse
);
345 size_type
next_capacity(size_type additional_objects
) const
346 { return get_next_capacity(this->alloc().max_size(), this->members_
.m_capacity
, additional_objects
); }
348 struct members_holder
352 members_holder(const members_holder
&);
355 members_holder(const A
&alloc
)
356 : A(alloc
), m_start(0), m_size(0), m_capacity(0)
361 size_type m_capacity
;
365 void prot_deallocate()
367 if(!this->members_
.m_capacity
) return;
368 this->alloc().deallocate(this->members_
.m_start
, this->members_
.m_capacity
);
369 this->members_
.m_start
= 0;
370 this->members_
.m_size
= 0;
371 this->members_
.m_capacity
= 0;
374 void destroy(value_type
* p
)
376 if(!value_traits::trivial_dctr
)
377 containers_detail::get_pointer(p
)->~value_type();
380 void destroy_n(value_type
* p
, size_type n
)
382 if(!value_traits::trivial_dctr
)
383 for(; n
--; ++p
) p
->~value_type();
386 void prot_destroy_all()
388 this->destroy_n(containers_detail::get_pointer(this->members_
.m_start
), this->members_
.m_size
);
389 this->members_
.m_size
= 0;
395 const A
&alloc() const
399 } //namespace containers_detail {
402 //! \class ::boost::interprocess::vector boost/interprocess/containers/container/vector.hpp <boost/interprocess/containers/vector.hpp>
403 //! A vector is a sequence that supports random access to elements, constant
404 //! time insertion and removal of elements at the end, and linear time insertion
405 //! and removal of elements at the beginning or in the middle. The number of
406 //! elements in a vector may vary dynamically; memory management is automatic.
407 //! boost::interprocess_container::vector is similar to std::vector but it's compatible
408 //! with shared memory and memory mapped files.
409 template <class T
, class A
>
410 class vector
: private containers_detail::vector_alloc_holder
<A
>
413 typedef vector
<T
, A
> self_t
;
414 typedef containers_detail::vector_alloc_holder
<A
> base_t
;
417 //! The type of object, T, stored in the vector
418 typedef T value_type
;
420 typedef typename
A::pointer pointer
;
421 //! Const pointer to T
422 typedef typename
A::const_pointer const_pointer
;
424 typedef typename
A::reference reference
;
425 //! Const reference to T
426 typedef typename
A::const_reference const_reference
;
427 //! An unsigned integral type
428 typedef typename
A::size_type size_type
;
429 //! A signed integral type
430 typedef typename
A::difference_type difference_type
;
431 //! The allocator type
432 typedef A allocator_type
;
433 //! The random access iterator
434 typedef containers_detail::vector_iterator
<pointer
> iterator
;
435 //! The random access const_iterator
436 typedef containers_detail::vector_const_iterator
<pointer
> const_iterator
;
438 //! Iterator used to iterate backwards through a vector.
439 typedef std::reverse_iterator
<iterator
>
441 //! Const iterator used to iterate backwards through a vector.
442 typedef std::reverse_iterator
<const_iterator
>
443 const_reverse_iterator
;
444 //! The stored allocator type
445 typedef allocator_type stored_allocator_type
;
449 typedef containers_detail::advanced_insert_aux_int
<T
, T
*> advanced_insert_aux_int_t
;
450 typedef containers_detail::vector_value_traits
<value_type
, A
> value_traits
;
452 typedef typename
base_t::allocator_v1 allocator_v1
;
453 typedef typename
base_t::allocator_v2 allocator_v2
;
454 typedef typename
base_t::alloc_version alloc_version
;
456 typedef constant_iterator
<T
, difference_type
> cvalue_iterator
;
457 typedef repeat_iterator
<T
, difference_type
> repeat_it
;
458 typedef boost::interprocess::move_iterator
<repeat_it
> repeat_move_it
;
462 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(vector
)
464 //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
466 //! <b>Throws</b>: If allocator_type's copy constructor throws.
468 //! <b>Complexity</b>: Constant.
469 explicit vector(const A
& a
= A())
473 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
474 //! and inserts n default contructed values.
476 //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
477 //! throws or T's default or copy constructor throws.
479 //! <b>Complexity</b>: Linear to n.
481 : base_t(allocator_type())
484 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
485 //! and inserts n copies of value.
487 //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
488 //! throws or T's default or copy constructor throws.
490 //! <b>Complexity</b>: Linear to n.
491 vector(size_type n
, const T
& value
, const allocator_type
& a
= allocator_type())
493 { this->insert(this->cend(), n
, value
); }
495 //! <b>Effects</b>: Copy constructs a vector.
497 //! <b>Postcondition</b>: x == *this.
499 //! <b>Complexity</b>: Linear to the elements x contains.
500 vector(const vector
<T
, A
>& x
)
504 //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
506 //! <b>Throws</b>: If allocator_type's copy constructor throws.
508 //! <b>Complexity</b>: Constant.
509 vector(BOOST_INTERPROCESS_RV_REF(vector
) mx
)
510 : base_t(boost::interprocess::move(mx
))
513 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
514 //! and inserts a copy of the range [first, last) in the vector.
516 //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
517 //! throws or T's constructor taking an dereferenced InIt throws.
519 //! <b>Complexity</b>: Linear to the range [first, last).
520 template <class InIt
>
521 vector(InIt first
, InIt last
, const allocator_type
& a
= allocator_type())
523 { this->assign(first
, last
); }
525 //! <b>Effects</b>: Destroys the vector. All stored values are destroyed
526 //! and used memory is deallocated.
528 //! <b>Throws</b>: Nothing.
530 //! <b>Complexity</b>: Linear to the number of elements.
532 {} //vector_alloc_holder clears the data
534 //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
536 //! <b>Throws</b>: Nothing.
538 //! <b>Complexity</b>: Constant.
540 { return iterator(this->members_
.m_start
); }
542 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
544 //! <b>Throws</b>: Nothing.
546 //! <b>Complexity</b>: Constant.
547 const_iterator
begin() const
548 { return const_iterator(this->members_
.m_start
); }
550 //! <b>Effects</b>: Returns an iterator to the end of the vector.
552 //! <b>Throws</b>: Nothing.
554 //! <b>Complexity</b>: Constant.
556 { return iterator(this->members_
.m_start
+ this->members_
.m_size
); }
558 //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
560 //! <b>Throws</b>: Nothing.
562 //! <b>Complexity</b>: Constant.
563 const_iterator
end() const
564 { return this->cend(); }
566 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
567 //! of the reversed vector.
569 //! <b>Throws</b>: Nothing.
571 //! <b>Complexity</b>: Constant.
572 reverse_iterator
rbegin()
573 { return reverse_iterator(this->end()); }
575 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
576 //! of the reversed vector.
578 //! <b>Throws</b>: Nothing.
580 //! <b>Complexity</b>: Constant.
581 const_reverse_iterator
rbegin()const
582 { return this->crbegin(); }
584 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
585 //! of the reversed vector.
587 //! <b>Throws</b>: Nothing.
589 //! <b>Complexity</b>: Constant.
590 reverse_iterator
rend()
591 { return reverse_iterator(this->begin()); }
593 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
594 //! of the reversed vector.
596 //! <b>Throws</b>: Nothing.
598 //! <b>Complexity</b>: Constant.
599 const_reverse_iterator
rend() const
600 { return this->crend(); }
602 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
604 //! <b>Throws</b>: Nothing.
606 //! <b>Complexity</b>: Constant.
607 const_iterator
cbegin() const
608 { return const_iterator(this->members_
.m_start
); }
610 //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
612 //! <b>Throws</b>: Nothing.
614 //! <b>Complexity</b>: Constant.
615 const_iterator
cend() const
616 { return const_iterator(this->members_
.m_start
+ this->members_
.m_size
); }
618 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
619 //! of the reversed vector.
621 //! <b>Throws</b>: Nothing.
623 //! <b>Complexity</b>: Constant.
624 const_reverse_iterator
crbegin()const
625 { return const_reverse_iterator(this->end());}
627 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
628 //! of the reversed vector.
630 //! <b>Throws</b>: Nothing.
632 //! <b>Complexity</b>: Constant.
633 const_reverse_iterator
crend() const
634 { return const_reverse_iterator(this->begin()); }
636 //! <b>Requires</b>: !empty()
638 //! <b>Effects</b>: Returns a reference to the first element
639 //! from the beginning of the container.
641 //! <b>Throws</b>: Nothing.
643 //! <b>Complexity</b>: Constant.
645 { return *this->members_
.m_start
; }
647 //! <b>Requires</b>: !empty()
649 //! <b>Effects</b>: Returns a const reference to the first element
650 //! from the beginning of the container.
652 //! <b>Throws</b>: Nothing.
654 //! <b>Complexity</b>: Constant.
655 const_reference
front() const
656 { return *this->members_
.m_start
; }
658 //! <b>Requires</b>: !empty()
660 //! <b>Effects</b>: Returns a reference to the first element
661 //! from the beginning of the container.
663 //! <b>Throws</b>: Nothing.
665 //! <b>Complexity</b>: Constant.
667 { return this->members_
.m_start
[this->members_
.m_size
- 1]; }
669 //! <b>Effects</b>: Returns a const reference to the first element
670 //! from the beginning of the container.
672 //! <b>Throws</b>: Nothing.
674 //! <b>Complexity</b>: Constant.
675 const_reference
back() const
676 { return this->members_
.m_start
[this->members_
.m_size
- 1]; }
678 //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
679 //! For a non-empty vector, data() == &front().
681 //! <b>Throws</b>: Nothing.
683 //! <b>Complexity</b>: Constant.
685 { return this->members_
.m_start
; }
687 //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
688 //! For a non-empty vector, data() == &front().
690 //! <b>Throws</b>: Nothing.
692 //! <b>Complexity</b>: Constant.
693 const_pointer
data() const
694 { return this->members_
.m_start
; }
696 //! <b>Effects</b>: Returns the number of the elements contained in the vector.
698 //! <b>Throws</b>: Nothing.
700 //! <b>Complexity</b>: Constant.
701 size_type
size() const
702 { return this->members_
.m_size
; }
704 //! <b>Effects</b>: Returns the largest possible size of the vector.
706 //! <b>Throws</b>: Nothing.
708 //! <b>Complexity</b>: Constant.
709 size_type
max_size() const
710 { return this->alloc().max_size(); }
712 //! <b>Effects</b>: Number of elements for which memory has been allocated.
713 //! capacity() is always greater than or equal to size().
715 //! <b>Throws</b>: Nothing.
717 //! <b>Complexity</b>: Constant.
718 size_type
capacity() const
719 { return this->members_
.m_capacity
; }
721 //! <b>Effects</b>: Returns true if the vector contains no elements.
723 //! <b>Throws</b>: Nothing.
725 //! <b>Complexity</b>: Constant.
727 { return !this->members_
.m_size
; }
729 //! <b>Requires</b>: size() < n.
731 //! <b>Effects</b>: Returns a reference to the nth element
732 //! from the beginning of the container.
734 //! <b>Throws</b>: Nothing.
736 //! <b>Complexity</b>: Constant.
737 reference
operator[](size_type n
)
738 { return this->members_
.m_start
[n
]; }
740 //! <b>Requires</b>: size() < n.
742 //! <b>Effects</b>: Returns a const reference to the nth element
743 //! from the beginning of the container.
745 //! <b>Throws</b>: Nothing.
747 //! <b>Complexity</b>: Constant.
748 const_reference
operator[](size_type n
) const
749 { return this->members_
.m_start
[n
]; }
751 //! <b>Requires</b>: size() < n.
753 //! <b>Effects</b>: Returns a reference to the nth element
754 //! from the beginning of the container.
756 //! <b>Throws</b>: std::range_error if n >= size()
758 //! <b>Complexity</b>: Constant.
759 reference
at(size_type n
)
760 { this->priv_check_range(n
); return this->members_
.m_start
[n
]; }
762 //! <b>Requires</b>: size() < n.
764 //! <b>Effects</b>: Returns a const reference to the nth element
765 //! from the beginning of the container.
767 //! <b>Throws</b>: std::range_error if n >= size()
769 //! <b>Complexity</b>: Constant.
770 const_reference
at(size_type n
) const
771 { this->priv_check_range(n
); return this->members_
.m_start
[n
]; }
773 //! <b>Effects</b>: Returns a copy of the internal allocator.
775 //! <b>Throws</b>: If allocator's copy constructor throws.
777 //! <b>Complexity</b>: Constant.
778 allocator_type
get_allocator() const
779 { return this->alloc(); }
781 const stored_allocator_type
&get_stored_allocator() const
782 { return this->alloc(); }
784 stored_allocator_type
&get_stored_allocator()
785 { return this->alloc(); }
787 //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
788 //! effect. Otherwise, it is a request for allocation of additional memory.
789 //! If the request is successful, then capacity() is greater than or equal to
790 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
792 //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
793 void reserve(size_type new_cap
)
795 if (this->capacity() < new_cap
){
796 //There is not enough memory, allocate a new
797 //buffer or expand the old one.
798 bool same_buffer_start
;
799 size_type real_cap
= 0;
800 std::pair
<pointer
, bool> ret
=
801 this->allocation_command
802 (allocate_new
| expand_fwd
| expand_bwd
,
803 new_cap
, new_cap
, real_cap
, this->members_
.m_start
);
805 //Check for forward expansion
806 same_buffer_start
= ret
.second
&& this->members_
.m_start
== ret
.first
;
807 if(same_buffer_start
){
808 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
809 ++this->num_expand_fwd
;
811 this->members_
.m_capacity
= real_cap
;
814 //If there is no forward expansion, move objects
816 //We will reuse insert code, so create a dummy input iterator
817 T
*dummy_it(containers_detail::get_pointer(this->members_
.m_start
));
818 containers_detail::advanced_insert_aux_proxy
<T
, boost::interprocess::move_iterator
<T
*>, T
*>
819 proxy(boost::interprocess::make_move_iterator(dummy_it
), boost::interprocess::make_move_iterator(dummy_it
));
820 //Backwards (and possibly forward) expansion
822 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
823 ++this->num_expand_bwd
;
825 this->priv_range_insert_expand_backwards
826 ( containers_detail::get_pointer(ret
.first
)
828 , containers_detail::get_pointer(this->members_
.m_start
)
834 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
837 this->priv_range_insert_new_allocation
838 ( containers_detail::get_pointer(ret
.first
)
840 , containers_detail::get_pointer(this->members_
.m_start
)
848 //! <b>Effects</b>: Makes *this contain the same elements as x.
850 //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
851 //! of each of x's elements.
853 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
855 //! <b>Complexity</b>: Linear to the number of elements in x.
856 vector
& operator=(const vector
& x
)
859 this->assign(x
.members_
.m_start
, x
.members_
.m_start
+ x
.members_
.m_size
);
864 //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this.
866 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
867 //! before the function.
869 //! <b>Throws</b>: If allocator_type's copy constructor throws.
871 //! <b>Complexity</b>: Constant.
872 vector
& operator=(BOOST_INTERPROCESS_RV_REF(vector
) x
)
881 //! <b>Effects</b>: Assigns the n copies of val to *this.
883 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
885 //! <b>Complexity</b>: Linear to n.
886 void assign(size_type n
, const value_type
& val
)
887 { this->assign(cvalue_iterator(val
, n
), cvalue_iterator()); }
889 //! <b>Effects</b>: Assigns the the range [first, last) to *this.
891 //! <b>Throws</b>: If memory allocation throws or
892 //! T's constructor from dereferencing InpIt throws.
894 //! <b>Complexity</b>: Linear to n.
895 template <class InIt
>
896 void assign(InIt first
, InIt last
)
898 //Dispatch depending on integer/iterator
899 const bool aux_boolean
= containers_detail::is_convertible
<InIt
, std::size_t>::value
;
900 typedef containers_detail::bool_
<aux_boolean
> Result
;
901 this->priv_assign_dispatch(first
, last
, Result());
904 //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
906 //! <b>Throws</b>: If memory allocation throws or
907 //! T's copy constructor throws.
909 //! <b>Complexity</b>: Amortized constant time.
910 void push_back(const T
& x
)
912 if (this->members_
.m_size
< this->members_
.m_capacity
){
913 //There is more memory, just construct a new object at the end
914 new((void*)(containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
))value_type(x
);
915 ++this->members_
.m_size
;
918 this->insert(this->cend(), x
);
922 //! <b>Effects</b>: Constructs a new element in the end of the vector
923 //! and moves the resources of mx to this new element.
925 //! <b>Throws</b>: If memory allocation throws.
927 //! <b>Complexity</b>: Amortized constant time.
928 void push_back(BOOST_INTERPROCESS_RV_REF(T
) x
)
930 if (this->members_
.m_size
< this->members_
.m_capacity
){
931 //There is more memory, just construct a new object at the end
932 new((void*)containers_detail::get_pointer(this->members_
.m_start
+ this->members_
.m_size
))value_type(boost::interprocess::move(x
));
933 ++this->members_
.m_size
;
936 this->insert(this->cend(), boost::interprocess::move(x
));
940 #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
942 //! <b>Effects</b>: Inserts an object of type T constructed with
943 //! std::forward<Args>(args)... in the end of the vector.
945 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
947 //! <b>Complexity</b>: Amortized constant time.
948 template<class ...Args
>
949 void emplace_back(Args
&&...args
)
951 T
* back_pos
= containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
;
952 if (this->members_
.m_size
< this->members_
.m_capacity
){
953 //There is more memory, just construct a new object at the end
954 new((void*)(back_pos
))value_type(boost::interprocess::forward
<Args
>(args
)...);
955 ++this->members_
.m_size
;
958 containers_detail::advanced_insert_aux_emplace
<T
, T
*, Args
...> proxy
959 (boost::interprocess::forward
<Args
>(args
)...);
960 priv_range_insert(back_pos
, 1, proxy
);
964 //! <b>Requires</b>: position must be a valid iterator of *this.
966 //! <b>Effects</b>: Inserts an object of type T constructed with
967 //! std::forward<Args>(args)... before position
969 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
971 //! <b>Complexity</b>: If position is end(), amortized constant time
972 //! Linear time otherwise.
973 template<class ...Args
>
974 iterator
emplace(const_iterator position
, Args
&& ...args
)
976 //Just call more general insert(pos, size, value) and return iterator
977 size_type pos_n
= position
- cbegin();
978 containers_detail::advanced_insert_aux_emplace
<T
, T
*, Args
...> proxy
979 (boost::interprocess::forward
<Args
>(args
)...);
980 priv_range_insert(position
.get_ptr(), 1, proxy
);
981 return iterator(this->members_
.m_start
+ pos_n
);
988 T
* back_pos
= containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
;
989 if (this->members_
.m_size
< this->members_
.m_capacity
){
990 //There is more memory, just construct a new object at the end
991 new((void*)(back_pos
))value_type();
992 ++this->members_
.m_size
;
995 containers_detail::advanced_insert_aux_emplace
<value_type
, T
*> proxy
;
996 priv_range_insert(back_pos
, 1, proxy
);
1000 iterator
emplace(const_iterator position
)
1002 size_type pos_n
= position
- cbegin();
1003 containers_detail::advanced_insert_aux_emplace
<value_type
, T
*> proxy
;
1004 priv_range_insert(containers_detail::get_pointer(position
.get_ptr()), 1, proxy
);
1005 return iterator(this->members_
.m_start
+ pos_n
);
1008 #define BOOST_PP_LOCAL_MACRO(n) \
1009 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
1010 void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
1012 T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size; \
1013 if (this->members_.m_size < this->members_.m_capacity){ \
1014 new((void*)(back_pos))value_type \
1015 (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
1016 ++this->members_.m_size; \
1019 containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
1020 <value_type, T*, BOOST_PP_ENUM_PARAMS(n, P)> \
1021 proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
1022 priv_range_insert(back_pos, 1, proxy); \
1026 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
1027 iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
1029 size_type pos_n = pos - cbegin(); \
1030 containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
1031 <value_type, T*, BOOST_PP_ENUM_PARAMS(n, P)> \
1032 proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
1033 priv_range_insert(containers_detail::get_pointer(pos.get_ptr()), 1, proxy); \
1034 return iterator(this->members_.m_start + pos_n); \
1037 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
1038 #include BOOST_PP_LOCAL_ITERATE()
1040 #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
1042 //! <b>Effects</b>: Swaps the contents of *this and x.
1043 //! If this->allocator_type() != x.allocator_type()
1044 //! allocators are also swapped.
1046 //! <b>Throws</b>: Nothing.
1048 //! <b>Complexity</b>: Constant.
1049 void swap(vector
& x
)
1051 allocator_type
&this_al
= this->alloc(), &other_al
= x
.alloc();
1052 //Just swap internals
1053 containers_detail::do_swap(this->members_
.m_start
, x
.members_
.m_start
);
1054 containers_detail::do_swap(this->members_
.m_size
, x
.members_
.m_size
);
1055 containers_detail::do_swap(this->members_
.m_capacity
, x
.members_
.m_capacity
);
1057 if (this_al
!= other_al
){
1058 containers_detail::do_swap(this_al
, other_al
);
1062 //! <b>Requires</b>: position must be a valid iterator of *this.
1064 //! <b>Effects</b>: Insert a copy of x before position.
1066 //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
1068 //! <b>Complexity</b>: If position is end(), amortized constant time
1069 //! Linear time otherwise.
1070 iterator
insert(const_iterator position
, const T
& x
)
1072 //Just call more general insert(pos, size, value) and return iterator
1073 size_type pos_n
= position
- cbegin();
1074 this->insert(position
, (size_type
)1, x
);
1075 return iterator(this->members_
.m_start
+ pos_n
);
1078 //! <b>Requires</b>: position must be a valid iterator of *this.
1080 //! <b>Effects</b>: Insert a new element before position with mx's resources.
1082 //! <b>Throws</b>: If memory allocation throws.
1084 //! <b>Complexity</b>: If position is end(), amortized constant time
1085 //! Linear time otherwise.
1086 iterator
insert(const_iterator position
, BOOST_INTERPROCESS_RV_REF(T
) x
)
1088 //Just call more general insert(pos, size, value) and return iterator
1089 size_type pos_n
= position
- cbegin();
1090 this->insert(position
1091 ,repeat_move_it(repeat_it(x
, 1))
1092 ,repeat_move_it(repeat_it()));
1093 return iterator(this->members_
.m_start
+ pos_n
);
1096 //! <b>Requires</b>: pos must be a valid iterator of *this.
1098 //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
1100 //! <b>Throws</b>: If memory allocation throws, T's constructor from a
1101 //! dereferenced InpIt throws or T's copy constructor throws.
1103 //! <b>Complexity</b>: Linear to std::distance [first, last).
1104 template <class InIt
>
1105 void insert(const_iterator pos
, InIt first
, InIt last
)
1107 //Dispatch depending on integer/iterator
1108 const bool aux_boolean
= containers_detail::is_convertible
<InIt
, std::size_t>::value
;
1109 typedef containers_detail::bool_
<aux_boolean
> Result
;
1110 this->priv_insert_dispatch(pos
, first
, last
, Result());
1113 //! <b>Requires</b>: pos must be a valid iterator of *this.
1115 //! <b>Effects</b>: Insert n copies of x before pos.
1117 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
1119 //! <b>Complexity</b>: Linear to n.
1120 void insert(const_iterator p
, size_type n
, const T
& x
)
1121 { this->insert(p
, cvalue_iterator(x
, n
), cvalue_iterator()); }
1123 //! <b>Effects</b>: Removes the last element from the vector.
1125 //! <b>Throws</b>: Nothing.
1127 //! <b>Complexity</b>: Constant time.
1130 //Destroy last element
1131 --this->members_
.m_size
;
1132 this->destroy(containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
);
1135 //! <b>Effects</b>: Erases the element at position pos.
1137 //! <b>Throws</b>: Nothing.
1139 //! <b>Complexity</b>: Linear to the elements between pos and the
1140 //! last element. Constant if pos is the first or the last element.
1141 iterator
erase(const_iterator position
)
1143 T
*pos
= containers_detail::get_pointer(position
.get_ptr());
1144 T
*beg
= containers_detail::get_pointer(this->members_
.m_start
);
1145 boost::interprocess::move(pos
+ 1, beg
+ this->members_
.m_size
, pos
);
1146 --this->members_
.m_size
;
1147 //Destroy last element
1148 base_t::destroy(containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
);
1149 return iterator(position
.get_ptr());
1152 //! <b>Effects</b>: Erases the elements pointed by [first, last).
1154 //! <b>Throws</b>: Nothing.
1156 //! <b>Complexity</b>: Linear to the distance between first and last.
1157 iterator
erase(const_iterator first
, const_iterator last
)
1159 if (first
!= last
){ // worth doing, copy down over hole
1160 T
* end_pos
= containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
;
1161 T
* ptr
= containers_detail::get_pointer(boost::interprocess::move
1162 (containers_detail::get_pointer(last
.get_ptr())
1164 ,containers_detail::get_pointer(first
.get_ptr())
1166 size_type destroyed
= (end_pos
- ptr
);
1167 this->destroy_n(ptr
, destroyed
);
1168 this->members_
.m_size
-= destroyed
;
1170 return iterator(first
.get_ptr());
1173 //! <b>Effects</b>: Inserts or erases elements at the end such that
1174 //! the size becomes n. New elements are copy constructed from x.
1176 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
1178 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1179 void resize(size_type new_size
, const T
& x
)
1181 pointer finish
= this->members_
.m_start
+ this->members_
.m_size
;
1182 if (new_size
< size()){
1183 //Destroy last elements
1184 this->erase(const_iterator(this->members_
.m_start
+ new_size
), this->end());
1187 //Insert new elements at the end
1188 this->insert(const_iterator(finish
), new_size
- this->size(), x
);
1192 //! <b>Effects</b>: Inserts or erases elements at the end such that
1193 //! the size becomes n. New elements are default constructed.
1195 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
1197 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1198 void resize(size_type new_size
)
1200 if (new_size
< this->size()){
1201 //Destroy last elements
1202 this->erase(const_iterator(this->members_
.m_start
+ new_size
), this->end());
1205 size_type n
= new_size
- this->size();
1206 this->reserve(new_size
);
1207 containers_detail::default_construct_aux_proxy
<T
, T
*, size_type
> proxy(n
);
1208 priv_range_insert(this->cend().get_ptr(), n
, proxy
);
1212 //! <b>Effects</b>: Erases all the elements of the vector.
1214 //! <b>Throws</b>: Nothing.
1216 //! <b>Complexity</b>: Linear to the number of elements in the vector.
1218 { this->prot_destroy_all(); }
1222 //! <b>Effects</b>: Tries to deallocate the excess of memory created
1223 //! with previous allocations. The size of the vector is unchanged
1225 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
1227 //! <b>Complexity</b>: Linear to size().
1228 void shrink_to_fit()
1229 { priv_shrink_to_fit(alloc_version()); }
1232 void priv_shrink_to_fit(allocator_v1
)
1234 if(this->members_
.m_capacity
){
1236 this->prot_deallocate();
1239 //This would not work with stateful allocators
1240 vector
<T
, A
>(*this).swap(*this);
1245 void priv_shrink_to_fit(allocator_v2
)
1247 if(this->members_
.m_capacity
){
1249 this->prot_deallocate();
1252 size_type received_size
;
1253 if(this->alloc().allocation_command
1254 ( shrink_in_place
| nothrow_allocation
1255 , this->capacity(), this->size()
1256 , received_size
, this->members_
.m_start
).first
){
1257 this->members_
.m_capacity
= received_size
;
1258 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
1266 template <class FwdIt
>
1267 void priv_range_insert(pointer pos
, FwdIt first
, FwdIt last
, std::forward_iterator_tag
)
1270 const size_type n
= std::distance(first
, last
);
1271 containers_detail::advanced_insert_aux_proxy
<T
, FwdIt
, T
*> proxy(first
, last
);
1272 priv_range_insert(pos
, n
, proxy
);
1276 void priv_range_insert(pointer pos
, const size_type n
, advanced_insert_aux_int_t
&interf
)
1278 //Check if we have enough memory or try to expand current memory
1279 size_type remaining
= this->members_
.m_capacity
- this->members_
.m_size
;
1280 bool same_buffer_start
;
1281 std::pair
<pointer
, bool> ret
;
1282 size_type real_cap
= this->members_
.m_capacity
;
1284 //Check if we already have room
1285 if (n
<= remaining
){
1286 same_buffer_start
= true;
1289 //There is not enough memory, allocate a new
1290 //buffer or expand the old one.
1291 size_type new_cap
= this->next_capacity(n
);
1292 ret
= this->allocation_command
1293 (allocate_new
| expand_fwd
| expand_bwd
,
1294 this->members_
.m_size
+ n
, new_cap
, real_cap
, this->members_
.m_start
);
1296 //Check for forward expansion
1297 same_buffer_start
= ret
.second
&& this->members_
.m_start
== ret
.first
;
1298 if(same_buffer_start
){
1299 this->members_
.m_capacity
= real_cap
;
1303 //If we had room or we have expanded forward
1304 if (same_buffer_start
){
1305 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
1306 ++this->num_expand_fwd
;
1308 this->priv_range_insert_expand_forward
1309 (containers_detail::get_pointer(pos
), n
, interf
);
1311 //Backwards (and possibly forward) expansion
1312 else if(ret
.second
){
1313 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
1314 ++this->num_expand_bwd
;
1316 this->priv_range_insert_expand_backwards
1317 ( containers_detail::get_pointer(ret
.first
)
1319 , containers_detail::get_pointer(pos
)
1325 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
1328 this->priv_range_insert_new_allocation
1329 ( containers_detail::get_pointer(ret
.first
)
1331 , containers_detail::get_pointer(pos
)
1337 void priv_range_insert_expand_forward(T
* pos
, size_type n
, advanced_insert_aux_int_t
&interf
)
1339 //There is enough memory
1340 T
* old_finish
= containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
;
1341 const size_type elems_after
= old_finish
- pos
;
1343 if (elems_after
> n
){
1344 //New elements can be just copied.
1345 //Move to uninitialized memory last objects
1346 boost::interprocess::uninitialized_move(old_finish
- n
, old_finish
, old_finish
);
1347 this->members_
.m_size
+= n
;
1348 //Copy previous to last objects to the initialized end
1349 boost::interprocess::move_backward(pos
, old_finish
- n
, old_finish
);
1350 //Insert new objects in the pos
1351 interf
.copy_all_to(pos
);
1354 //The new elements don't fit in the [pos, end()) range. Copy
1355 //to the beginning of the unallocated zone the last new elements.
1356 interf
.uninitialized_copy_some_and_update(old_finish
, elems_after
, false);
1357 this->members_
.m_size
+= n
- elems_after
;
1358 //Copy old [pos, end()) elements to the uninitialized memory
1359 boost::interprocess::uninitialized_move
1360 ( pos
, old_finish
, containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
);
1361 this->members_
.m_size
+= elems_after
;
1362 //Copy first new elements in pos
1363 interf
.copy_all_to(pos
);
1367 void priv_range_insert_new_allocation
1368 (T
* new_start
, size_type new_cap
, T
* pos
, size_type n
, advanced_insert_aux_int_t
&interf
)
1370 T
* new_finish
= new_start
;
1372 //Anti-exception rollbacks
1373 typename
value_traits::UCopiedArrayDeallocator
scoped_alloc(new_start
, this->alloc(), new_cap
);
1374 typename
value_traits::UCopiedArrayDestructor
constructed_values_destroyer(new_start
, 0u);
1376 //Initialize with [begin(), pos) old buffer
1377 //the start of the new buffer
1378 new_finish
= boost::interprocess::uninitialized_move
1379 (containers_detail::get_pointer(this->members_
.m_start
), pos
, old_finish
= new_finish
);
1380 constructed_values_destroyer
.increment_size(new_finish
- old_finish
);
1381 //Initialize new objects, starting from previous point
1382 interf
.uninitialized_copy_all_to(old_finish
= new_finish
);
1384 constructed_values_destroyer
.increment_size(new_finish
- old_finish
);
1385 //Initialize from the rest of the old buffer,
1386 //starting from previous point
1387 new_finish
= boost::interprocess::uninitialized_move
1388 ( pos
, containers_detail::get_pointer(this->members_
.m_start
) + this->members_
.m_size
, new_finish
);
1389 //All construction successful, disable rollbacks
1390 constructed_values_destroyer
.release();
1391 scoped_alloc
.release();
1392 //Destroy and deallocate old elements
1393 //If there is allocated memory, destroy and deallocate
1394 if(this->members_
.m_start
!= 0){
1395 if(!value_traits::trivial_dctr_after_move
)
1396 this->destroy_n(containers_detail::get_pointer(this->members_
.m_start
), this->members_
.m_size
);
1397 this->alloc().deallocate(this->members_
.m_start
, this->members_
.m_capacity
);
1399 this->members_
.m_start
= new_start
;
1400 this->members_
.m_size
= new_finish
- new_start
;
1401 this->members_
.m_capacity
= new_cap
;
1404 void priv_range_insert_expand_backwards
1405 (T
* new_start
, size_type new_capacity
,
1406 T
* pos
, const size_type n
, advanced_insert_aux_int_t
&interf
)
1409 T
* old_start
= containers_detail::get_pointer(this->members_
.m_start
);
1410 T
* old_finish
= old_start
+ this->members_
.m_size
;
1411 size_type old_size
= this->members_
.m_size
;
1413 //We can have 8 possibilities:
1414 const size_type elemsbefore
= (size_type
)(pos
- old_start
);
1415 const size_type s_before
= (size_type
)(old_start
- new_start
);
1417 //Update the vector buffer information to a safe state
1418 this->members_
.m_start
= new_start
;
1419 this->members_
.m_capacity
= new_capacity
;
1420 this->members_
.m_size
= 0;
1422 //If anything goes wrong, this object will destroy
1423 //all the old objects to fulfill previous vector state
1424 typename
value_traits::OldArrayDestructor
old_values_destroyer(old_start
, old_size
);
1425 //Check if s_before is big enough to hold the beginning of old data + new data
1426 if(difference_type(s_before
) >= difference_type(elemsbefore
+ n
)){
1427 //Copy first old values before pos, after that the new objects
1428 boost::interprocess::uninitialized_move(old_start
, pos
, new_start
);
1429 this->members_
.m_size
= elemsbefore
;
1430 interf
.uninitialized_copy_all_to(new_start
+ elemsbefore
);
1431 this->members_
.m_size
+= n
;
1432 //Check if s_before is so big that even copying the old data + new data
1433 //there is a gap between the new data and the old data
1434 if(s_before
>= (old_size
+ n
)){
1436 // _________________________________________________________
1437 //| raw_mem | old_begin | old_end |
1438 //| __________________________________|___________|_________|
1441 // _________________________________________________________
1442 //| old_begin | new | old_end | raw_mem |
1443 //|___________|__________|_________|________________________|
1445 //Now initialize the rest of memory with the last old values
1446 boost::interprocess::uninitialized_move
1447 (pos
, old_finish
, new_start
+ elemsbefore
+ n
);
1448 //All new elements correctly constructed, avoid new element destruction
1449 this->members_
.m_size
= old_size
+ n
;
1450 //Old values destroyed automatically with "old_values_destroyer"
1451 //when "old_values_destroyer" goes out of scope unless the have trivial
1452 //destructor after move.
1453 if(value_traits::trivial_dctr_after_move
)
1454 old_values_destroyer
.release();
1456 //s_before is so big that divides old_end
1459 // __________________________________________________
1460 //| raw_mem | old_begin | old_end |
1461 //| ___________________________|___________|_________|
1464 // __________________________________________________
1465 //| old_begin | new | old_end | raw_mem |
1466 //|___________|__________|_________|_________________|
1468 //Now initialize the rest of memory with the last old values
1469 //All new elements correctly constructed, avoid new element destruction
1470 size_type raw_gap
= s_before
- (elemsbefore
+ n
);
1471 //Now initialize the rest of s_before memory with the
1472 //first of elements after new values
1473 boost::interprocess::uninitialized_move(pos
, pos
+ raw_gap
, new_start
+ elemsbefore
+ n
);
1474 //Update size since we have a contiguous buffer
1475 this->members_
.m_size
= old_size
+ s_before
;
1476 //All new elements correctly constructed, avoid old element destruction
1477 old_values_destroyer
.release();
1478 //Now copy remaining last objects in the old buffer begin
1479 T
*to_destroy
= boost::interprocess::move(pos
+ raw_gap
, old_finish
, old_start
);
1480 //Now destroy redundant elements except if they were moved and
1481 //they have trivial destructor after move
1482 size_type n_destroy
= old_finish
- to_destroy
;
1483 if(!value_traits::trivial_dctr_after_move
)
1484 this->destroy_n(to_destroy
, n_destroy
);
1485 this->members_
.m_size
-= n_destroy
;
1489 //Check if we have to do the insertion in two phases
1490 //since maybe s_before is not big enough and
1491 //the buffer was expanded both sides
1494 // _________________________________________________
1495 //| raw_mem | old_begin + old_end | raw_mem |
1496 //|_________|_____________________|_________________|
1498 //New situation with do_after:
1499 // _________________________________________________
1500 //| old_begin + new + old_end | raw_mem |
1501 //|___________________________________|_____________|
1503 //New without do_after:
1504 // _________________________________________________
1505 //| old_begin + new + old_end | raw_mem |
1506 //|____________________________|____________________|
1508 bool do_after
= n
> s_before
;
1510 //Now we can have two situations: the raw_mem of the
1511 //beginning divides the old_begin, or the new elements:
1512 if (s_before
<= elemsbefore
) {
1513 //The raw memory divides the old_begin group:
1515 //If we need two phase construction (do_after)
1516 //new group is divided in new = new_beg + new_end groups
1517 //In this phase only new_beg will be inserted
1520 // _________________________________________________
1521 //| raw_mem | old_begin | old_end | raw_mem |
1522 //|_________|___________|_________|_________________|
1524 //New situation with do_after(1):
1525 //This is not definitive situation, the second phase
1527 // _________________________________________________
1528 //| old_begin | new_beg | old_end | raw_mem |
1529 //|___________|_________|_________|_________________|
1531 //New situation without do_after:
1532 // _________________________________________________
1533 //| old_begin | new | old_end | raw_mem |
1534 //|___________|_____|_________|_____________________|
1536 //Copy the first part of old_begin to raw_mem
1537 T
*start_n
= old_start
+ difference_type(s_before
);
1538 boost::interprocess::uninitialized_move(old_start
, start_n
, new_start
);
1539 //The buffer is all constructed until old_end,
1540 //release destroyer and update size
1541 old_values_destroyer
.release();
1542 this->members_
.m_size
= old_size
+ s_before
;
1543 //Now copy the second part of old_begin overwriting himself
1544 T
* next
= boost::interprocess::move(start_n
, pos
, old_start
);
1546 //Now copy the new_beg elements
1547 interf
.copy_some_and_update(next
, s_before
, true);
1550 //Now copy the all the new elements
1551 interf
.copy_all_to(next
);
1552 T
* move_start
= next
+ n
;
1553 //Now displace old_end elements
1554 T
* move_end
= boost::interprocess::move(pos
, old_finish
, move_start
);
1555 //Destroy remaining moved elements from old_end except if
1556 //they have trivial destructor after being moved
1557 difference_type n_destroy
= s_before
- n
;
1558 if(!value_traits::trivial_dctr_after_move
)
1559 this->destroy_n(move_end
, n_destroy
);
1560 this->members_
.m_size
-= n_destroy
;
1564 //If we have to expand both sides,
1565 //we will play if the first new values so
1566 //calculate the upper bound of new values
1568 //The raw memory divides the new elements
1570 //If we need two phase construction (do_after)
1571 //new group is divided in new = new_beg + new_end groups
1572 //In this phase only new_beg will be inserted
1575 // _______________________________________________________
1576 //| raw_mem | old_begin | old_end | raw_mem |
1577 //|_______________|___________|_________|_________________|
1579 //New situation with do_after():
1580 // ____________________________________________________
1581 //| old_begin | new_beg | old_end | raw_mem |
1582 //|___________|_______________|_________|______________|
1584 //New situation without do_after:
1585 // ______________________________________________________
1586 //| old_begin | new | old_end | raw_mem |
1587 //|___________|_____|_________|__________________________|
1589 //First copy whole old_begin and part of new to raw_mem
1590 boost::interprocess::uninitialized_move(old_start
, pos
, new_start
);
1591 this->members_
.m_size
= elemsbefore
;
1593 const size_type mid_n
= difference_type(s_before
) - elemsbefore
;
1594 interf
.uninitialized_copy_some_and_update(new_start
+ elemsbefore
, mid_n
, true);
1595 this->members_
.m_size
= old_size
+ s_before
;
1596 //The buffer is all constructed until old_end,
1597 //release destroyer and update size
1598 old_values_destroyer
.release();
1602 interf
.copy_some_and_update(old_start
, s_before
- mid_n
, true);
1605 //Copy all new elements
1606 interf
.copy_all_to(old_start
);
1607 T
* move_start
= old_start
+ (n
-mid_n
);
1609 T
* move_end
= boost::interprocess::move(pos
, old_finish
, move_start
);
1610 //Destroy remaining moved elements from old_end except if they
1611 //have trivial destructor after being moved
1612 difference_type n_destroy
= s_before
- n
;
1613 if(!value_traits::trivial_dctr_after_move
)
1614 this->destroy_n(move_end
, n_destroy
);
1615 this->members_
.m_size
-= n_destroy
;
1619 //This is only executed if two phase construction is needed
1620 //This can be executed without exception handling since we
1621 //have to just copy and append in raw memory and
1622 //old_values_destroyer has been released in phase 1.
1624 //The raw memory divides the new elements
1627 // ______________________________________________________
1628 //| raw_mem | old_begin | old_end | raw_mem |
1629 //|______________|___________|____________|______________|
1631 //New situation with do_after(1):
1632 // _______________________________________________________
1633 //| old_begin + new_beg | new_end |old_end | raw_mem |
1634 //|__________________________|_________|________|_________|
1636 //New situation with do_after(2):
1637 // ______________________________________________________
1638 //| old_begin + new | old_end |raw |
1639 //|_______________________________________|_________|____|
1641 const size_type n_after
= n
- s_before
;
1642 const difference_type elemsafter
= old_size
- elemsbefore
;
1644 //We can have two situations:
1645 if (elemsafter
> difference_type(n_after
)){
1646 //The raw_mem from end will divide displaced old_end
1649 // ______________________________________________________
1650 //| raw_mem | old_begin | old_end | raw_mem |
1651 //|______________|___________|____________|______________|
1653 //New situation with do_after(1):
1654 // _______________________________________________________
1655 //| old_begin + new_beg | new_end |old_end | raw_mem |
1656 //|__________________________|_________|________|_________|
1658 //First copy the part of old_end raw_mem
1659 T
* finish_n
= old_finish
- difference_type(n_after
);
1660 boost::interprocess::uninitialized_move(finish_n
, old_finish
, old_finish
);
1661 this->members_
.m_size
+= n_after
;
1662 //Displace the rest of old_end to the new position
1663 boost::interprocess::move_backward(pos
, finish_n
, old_finish
);
1664 //Now overwrite with new_end
1665 //The new_end part is [first + (n - n_after), last)
1666 interf
.copy_all_to(pos
);
1669 //The raw_mem from end will divide new_end part
1672 // _____________________________________________________________
1673 //| raw_mem | old_begin | old_end | raw_mem |
1674 //|______________|___________|____________|_____________________|
1676 //New situation with do_after(2):
1677 // _____________________________________________________________
1678 //| old_begin + new_beg | new_end |old_end | raw_mem |
1679 //|__________________________|_______________|________|_________|
1681 size_type mid_last_dist
= n_after
- elemsafter
;
1682 //First initialize data in raw memory
1683 //The new_end part is [first + (n - n_after), last)
1684 interf
.uninitialized_copy_some_and_update(old_finish
, elemsafter
, false);
1685 this->members_
.m_size
+= mid_last_dist
;
1686 boost::interprocess::uninitialized_move(pos
, old_finish
, old_finish
+ mid_last_dist
);
1687 this->members_
.m_size
+= n_after
- mid_last_dist
;
1688 //Now copy the part of new_end over constructed elements
1689 interf
.copy_all_to(pos
);
1695 template <class InIt
>
1696 void priv_range_insert(const_iterator pos
, InIt first
, InIt last
, std::input_iterator_tag
)
1698 for(;first
!= last
; ++first
){
1699 this->insert(pos
, boost::interprocess::move(value_type(*first
)));
1703 template <class InIt
>
1704 void priv_assign_aux(InIt first
, InIt last
, std::input_iterator_tag
)
1706 //Overwrite all elements we can from [first, last)
1707 iterator cur
= begin();
1708 for ( ; first
!= last
&& cur
!= end(); ++cur
, ++first
){
1713 //There are no more elements in the sequence, erase remaining
1714 this->erase(cur
, cend());
1717 //There are more elements in the range, insert the remaining ones
1718 this->insert(this->cend(), first
, last
);
1722 template <class FwdIt
>
1723 void priv_assign_aux(FwdIt first
, FwdIt last
, std::forward_iterator_tag
)
1725 size_type n
= std::distance(first
, last
);
1726 //Check if we have enough memory or try to expand current memory
1727 size_type remaining
= this->members_
.m_capacity
- this->members_
.m_size
;
1728 bool same_buffer_start
;
1729 std::pair
<pointer
, bool> ret
;
1730 size_type real_cap
= this->members_
.m_capacity
;
1732 if (n
<= remaining
){
1733 same_buffer_start
= true;
1736 //There is not enough memory, allocate a new buffer
1737 size_type new_cap
= this->next_capacity(n
);
1738 ret
= this->allocation_command
1739 (allocate_new
| expand_fwd
| expand_bwd
,
1740 this->size() + n
, new_cap
, real_cap
, this->members_
.m_start
);
1741 same_buffer_start
= ret
.second
&& this->members_
.m_start
== ret
.first
;
1742 if(same_buffer_start
){
1743 this->members_
.m_capacity
= real_cap
;
1747 if(same_buffer_start
){
1748 T
*start
= containers_detail::get_pointer(this->members_
.m_start
);
1749 if (this->size() >= n
){
1750 //There is memory, but there are more old elements than new ones
1751 //Overwrite old elements with new ones
1752 // iG std::copy(first, last, start);
1753 std::copy(first
, last
, start
);
1754 //Destroy remaining old elements
1755 this->destroy_n(start
+ n
, this->members_
.m_size
- n
);
1756 this->members_
.m_size
= n
;
1759 //There is memory, but there are less old elements than new ones
1760 //First overwrite some old elements with new ones
1762 std::advance(mid
, this->size());
1763 // iG T *end = std::copy(first, mid, start);
1764 T
*end
= std::copy(first
, mid
, start
);
1765 //Initialize the remaining new elements in the uninitialized memory
1766 // iG std::uninitialized_copy(mid, last, end);
1767 boost::interprocess::uninitialized_copy_or_move(mid
, last
, end
);
1768 this->members_
.m_size
= n
;
1771 else if(!ret
.second
){
1772 typename
value_traits::UCopiedArrayDeallocator
scoped_alloc(ret
.first
, this->alloc(), real_cap
);
1773 // iG std::uninitialized_copy(first, last, containers_detail::get_pointer(ret.first));
1774 boost::interprocess::uninitialized_copy_or_move(first
, last
, containers_detail::get_pointer(ret
.first
));
1775 scoped_alloc
.release();
1776 //Destroy and deallocate old buffer
1777 if(this->members_
.m_start
!= 0){
1778 this->destroy_n(containers_detail::get_pointer(this->members_
.m_start
), this->members_
.m_size
);
1779 this->alloc().deallocate(this->members_
.m_start
, this->members_
.m_capacity
);
1781 this->members_
.m_start
= ret
.first
;
1782 this->members_
.m_size
= n
;
1783 this->members_
.m_capacity
= real_cap
;
1786 //Backwards expansion
1787 //If anything goes wrong, this object will destroy old objects
1788 T
*old_start
= containers_detail::get_pointer(this->members_
.m_start
);
1789 size_type old_size
= this->members_
.m_size
;
1790 typename
value_traits::OldArrayDestructor
old_values_destroyer(old_start
, old_size
);
1791 //If something goes wrong size will be 0
1792 //but holding the whole buffer
1793 this->members_
.m_size
= 0;
1794 this->members_
.m_start
= ret
.first
;
1795 this->members_
.m_capacity
= real_cap
;
1797 //Backup old buffer data
1798 size_type old_offset
= old_start
- containers_detail::get_pointer(ret
.first
);
1799 size_type first_count
= containers_detail::min_value(n
, old_offset
);
1802 std::advance(mid
, first_count
);
1803 // iG std::uninitialized_copy(first, mid, containers_detail::get_pointer(ret.first));
1804 boost::interprocess::uninitialized_copy_or_move(first
, mid
, containers_detail::get_pointer(ret
.first
));
1807 //All old elements will be destroyed by "old_values_destroyer"
1808 this->members_
.m_size
= n
;
1811 //We have constructed objects from the new begin until
1812 //the old end so release the rollback destruction
1813 old_values_destroyer
.release();
1814 this->members_
.m_start
= ret
.first
;
1815 this->members_
.m_size
= first_count
+ old_size
;
1816 //Now overwrite the old values
1817 size_type second_count
= containers_detail::min_value(old_size
, n
- first_count
);
1819 std::advance(mid2
, second_count
);
1820 // iG std::copy(mid, mid2, old_start);
1821 std::copy(mid
, mid2
, old_start
);
1823 //Check if we still have to append elements in the
1825 if(second_count
== old_size
){
1826 // iG std::copy(mid2, last, old_start + old_size);
1827 std::copy(mid2
, last
, old_start
+ old_size
);
1830 //We have to destroy some old values
1832 (old_start
+ second_count
, old_size
- second_count
);
1833 this->members_
.m_size
= n
;
1835 this->members_
.m_size
= n
;
1840 template <class Integer
>
1841 void priv_assign_dispatch(Integer n
, Integer val
, containers_detail::true_
)
1842 { this->assign((size_type
) n
, (T
) val
); }
1844 template <class InIt
>
1845 void priv_assign_dispatch(InIt first
, InIt last
, containers_detail::false_
)
1847 //Dispatch depending on integer/iterator
1848 typedef typename
std::iterator_traits
<InIt
>::iterator_category ItCat
;
1849 this->priv_assign_aux(first
, last
, ItCat());
1852 template <class Integer
>
1853 void priv_insert_dispatch(const_iterator pos
, Integer n
, Integer val
, containers_detail::true_
)
1854 { this->insert(pos
, (size_type
)n
, (T
)val
); }
1856 template <class InIt
>
1857 void priv_insert_dispatch(const_iterator pos
, InIt first
,
1858 InIt last
, containers_detail::false_
)
1860 //Dispatch depending on integer/iterator
1861 typedef typename
std::iterator_traits
<InIt
>::iterator_category ItCat
;
1862 this->priv_range_insert(pos
.get_ptr(), first
, last
, ItCat());
1865 void priv_check_range(size_type n
) const
1867 //If n is out of range, throw an out_of_range exception
1869 throw std::out_of_range("vector::at");
1872 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
1874 unsigned int num_expand_fwd
;
1875 unsigned int num_expand_bwd
;
1876 unsigned int num_shrink
;
1877 unsigned int num_alloc
;
1878 void reset_alloc_stats()
1879 { num_expand_fwd
= num_expand_bwd
= num_alloc
= 0, num_shrink
= 0; }
1884 template <class T
, class A
>
1886 operator==(const vector
<T
, A
>& x
, const vector
<T
, A
>& y
)
1888 //Check first size and each element if needed
1889 return x
.size() == y
.size() && std::equal(x
.begin(), x
.end(), y
.begin());
1892 template <class T
, class A
>
1894 operator!=(const vector
<T
, A
>& x
, const vector
<T
, A
>& y
)
1896 //Check first size and each element if needed
1897 return x
.size() != y
.size() || !std::equal(x
.begin(), x
.end(), y
.begin());
1900 template <class T
, class A
>
1902 operator<(const vector
<T
, A
>& x
, const vector
<T
, A
>& y
)
1904 return std::lexicographical_compare(x
.begin(), x
.end(), y
.begin(), y
.end());
1907 template <class T
, class A
>
1908 inline void swap(vector
<T
, A
>& x
, vector
<T
, A
>& y
)
1916 namespace interprocess
{
1918 //!has_trivial_destructor_after_move<> == true_type
1919 //!specialization for optimizations
1920 template <class T
, class A
>
1921 struct has_trivial_destructor_after_move
<boost::interprocess_container::vector
<T
, A
> >
1923 static const bool value
= has_trivial_destructor
<A
>::value
;
1930 #include <boost/interprocess/containers/container/detail/config_end.hpp>
1932 #endif // #ifndef BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP