|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r83126 - in trunk: boost/container boost/container/detail libs/container/bench libs/container/bench/detail libs/container/doc libs/container/proj/vc7ide libs/container/test
From: igaztanaga_at_[hidden]
Date: 2013-02-24 08:13:39
Author: igaztanaga
Date: 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
New Revision: 83126
URL: http://svn.boost.org/trac/boost/changeset/83126
Log:
Additional vector speed improvements, added basic benchmark against varray
Added:
trunk/libs/container/bench/
trunk/libs/container/bench/Jamfile.v2 (contents, props changed)
trunk/libs/container/bench/bench_static_vector.cpp (contents, props changed)
trunk/libs/container/bench/detail/
trunk/libs/container/bench/detail/varray.hpp (contents, props changed)
trunk/libs/container/bench/detail/varray_concept.hpp (contents, props changed)
trunk/libs/container/bench/detail/varray_util.hpp (contents, props changed)
trunk/libs/container/bench/varray.hpp (contents, props changed)
Removed:
trunk/libs/container/test/movable.hpp
Text files modified:
trunk/boost/container/allocator_traits.hpp | 16
trunk/boost/container/detail/advanced_insert_int.hpp | 16
trunk/boost/container/static_vector.hpp | 68 +
trunk/boost/container/vector.hpp | 527 ++++++++++------
trunk/libs/container/doc/container.qbk | 3
trunk/libs/container/proj/vc7ide/container.sln | 16
trunk/libs/container/proj/vc7ide/container.vcproj | 26
trunk/libs/container/test/Jamfile.v2 | 2
trunk/libs/container/test/movable_int.hpp | 97 +-
trunk/libs/container/test/static_vector_test.cpp | 1215 ++++++++++++++++++++-------------------
trunk/libs/container/test/static_vector_test.hpp | 2
trunk/libs/container/test/vector_test.hpp | 7
12 files changed, 1119 insertions(+), 876 deletions(-)
Modified: trunk/boost/container/allocator_traits.hpp
==============================================================================
--- trunk/boost/container/allocator_traits.hpp (original)
+++ trunk/boost/container/allocator_traits.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -250,7 +250,19 @@
//! <b>Returns</b>: `a.select_on_container_copy_construction()` if that expression is well-formed;
//! otherwise, a.
- static Alloc select_on_container_copy_construction(const Alloc &a)
+ static
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ typename container_detail::if_c
+ < boost::container::container_detail::
+ has_member_function_callable_with_select_on_container_copy_construction
+ <const Alloc>::value
+ , Alloc
+ , const Alloc &
+ >::type
+ #else
+ Alloc
+ #endif
+ select_on_container_copy_construction(const Alloc &a)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_select_on_container_copy_construction
@@ -295,7 +307,7 @@
static Alloc priv_select_on_container_copy_construction(boost::true_type, const Alloc &a)
{ return a.select_on_container_copy_construction(); }
- static Alloc priv_select_on_container_copy_construction(boost::false_type, const Alloc &a)
+ static const Alloc &priv_select_on_container_copy_construction(boost::false_type, const Alloc &a)
{ return a; }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Modified: trunk/boost/container/detail/advanced_insert_int.hpp
==============================================================================
--- trunk/boost/container/detail/advanced_insert_int.hpp (original)
+++ trunk/boost/container/detail/advanced_insert_int.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -89,10 +89,10 @@
: a_(a), v_(v)
{}
- void uninitialized_copy_n_and_update(Iterator p, size_type n)
+ void uninitialized_copy_n_and_update(Iterator p, size_type n) const
{ boost::container::uninitialized_fill_alloc_n(this->a_, v_, n, p); }
- void copy_n_and_update(Iterator p, size_type n)
+ void copy_n_and_update(Iterator p, size_type n) const
{ std::fill_n(p, n, v_); }
A &a_;
@@ -111,10 +111,10 @@
: a_(a)
{}
- void uninitialized_copy_n_and_update(Iterator p, size_type n)
+ void uninitialized_copy_n_and_update(Iterator p, size_type n) const
{ boost::container::uninitialized_default_alloc_n(this->a_, n, p); }
- void copy_n_and_update(Iterator, size_type)
+ void copy_n_and_update(Iterator, size_type) const
{
BOOST_ASSERT(false);
}
@@ -134,7 +134,7 @@
: a_(a), v_(v)
{}
- void uninitialized_copy_n_and_update(Iterator p, size_type n)
+ void uninitialized_copy_n_and_update(Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( this->a_
@@ -143,7 +143,7 @@
);
}
- void copy_n_and_update(Iterator p, size_type n)
+ void copy_n_and_update(Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p =v_;
@@ -165,7 +165,7 @@
: a_(a), v_(v)
{}
- void uninitialized_copy_n_and_update(Iterator p, size_type n)
+ void uninitialized_copy_n_and_update(Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( this->a_
@@ -174,7 +174,7 @@
);
}
- void copy_n_and_update(Iterator p, size_type n)
+ void copy_n_and_update(Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p = ::boost::move(v_);
Modified: trunk/boost/container/static_vector.hpp
==============================================================================
--- trunk/boost/container/static_vector.hpp (original)
+++ trunk/boost/container/static_vector.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -57,20 +57,29 @@
public:
typedef T value_type;
- T* internal_storage() const
+ static_storage_allocator() BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ static_storage_allocator(const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ static_storage_allocator & operator=(const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ T* internal_storage() const BOOST_CONTAINER_NOEXCEPT
{ return const_cast<T*>(static_cast<const T*>(static_cast<const void*>(&storage))); }
- T* internal_storage()
+ T* internal_storage() BOOST_CONTAINER_NOEXCEPT
{ return static_cast<T*>(static_cast<void*>(&storage)); }
static const std::size_t internal_capacity = N;
typedef boost::container::container_detail::version_type<static_storage_allocator, 0> version;
- friend bool operator==(const static_storage_allocator &, const static_storage_allocator &)
+ friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT
{ return false; }
- friend bool operator!=(const static_storage_allocator &, const static_storage_allocator &)
+ friend bool operator!=(const static_storage_allocator &, const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT
{ return true; }
private:
@@ -123,7 +132,7 @@
//!
//! @par Complexity
//! Constant O(1).
- static_vector()
+ static_vector() BOOST_CONTAINER_NOEXCEPT
: base_t()
{}
@@ -386,7 +395,7 @@
//!
//! @par Complexity
//! Linear O(N).
- void reserve(size_type count);
+ void reserve(size_type count) BOOST_CONTAINER_NOEXCEPT;
//! @pre <tt>size() < capacity()</tt>
//!
@@ -594,7 +603,7 @@
//!
//! @par Complexity
//! Constant O(1).
- void clear();
+ void clear() BOOST_CONTAINER_NOEXCEPT;
//! @pre <tt>i < size()</tt>
//!
@@ -724,7 +733,7 @@
//!
//! @par Complexity
//! Constant O(1).
- Value * data();
+ Value * data() BOOST_CONTAINER_NOEXCEPT;
//! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
//! For a non-empty vector <tt>data() == &front()</tt>.
@@ -734,7 +743,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const Value * data() const;
+ const Value * data() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns iterator to the first element.
//!
@@ -745,7 +754,7 @@
//!
//! @par Complexity
//! Constant O(1).
- iterator begin();
+ iterator begin() BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns const iterator to the first element.
//!
@@ -756,7 +765,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const_iterator begin() const;
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns const iterator to the first element.
//!
@@ -767,7 +776,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const_iterator cbegin() const;
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns iterator to the one after the last element.
//!
@@ -778,7 +787,7 @@
//!
//! @par Complexity
//! Constant O(1).
- iterator end();
+ iterator end() BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns const iterator to the one after the last element.
//!
@@ -789,7 +798,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const_iterator end() const;
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns const iterator to the one after the last element.
//!
@@ -800,7 +809,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const_iterator cend() const;
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns reverse iterator to the first element of the reversed container.
//!
@@ -812,7 +821,7 @@
//!
//! @par Complexity
//! Constant O(1).
- reverse_iterator rbegin();
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns const reverse iterator to the first element of the reversed container.
//!
@@ -824,7 +833,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const_reverse_iterator rbegin() const;
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns const reverse iterator to the first element of the reversed container.
//!
@@ -836,7 +845,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const_reverse_iterator crbegin() const;
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns reverse iterator to the one after the last element of the reversed container.
//!
@@ -848,7 +857,7 @@
//!
//! @par Complexity
//! Constant O(1).
- reverse_iterator rend();
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns const reverse iterator to the one after the last element of the reversed container.
//!
@@ -860,7 +869,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const_reverse_iterator rend() const;
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns const reverse iterator to the one after the last element of the reversed container.
//!
@@ -872,7 +881,7 @@
//!
//! @par Complexity
//! Constant O(1).
- const_reverse_iterator crend() const;
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns container's capacity.
//!
@@ -883,7 +892,7 @@
//!
//! @par Complexity
//! Constant O(1).
- static size_type capacity();
+ static size_type capacity() BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns container's capacity.
//!
@@ -894,7 +903,7 @@
//!
//! @par Complexity
//! Constant O(1).
- static size_type max_size();
+ static size_type max_size() BOOST_CONTAINER_NOEXCEPT;
//! @brief Returns the number of stored elements.
//!
@@ -905,7 +914,7 @@
//!
//! @par Complexity
//! Constant O(1).
- size_type size() const;
+ size_type size() const BOOST_CONTAINER_NOEXCEPT;
//! @brief Queries if the container contains elements.
//!
@@ -917,7 +926,13 @@
//!
//! @par Complexity
//! Constant O(1).
- bool empty() const;
+ bool empty() const BOOST_CONTAINER_NOEXCEPT;
+#else
+
+ friend void swap(static_vector &x, static_vector &y)
+ {
+ x.swap(y);
+ }
#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1026,7 +1041,8 @@
#else
template<typename V, std::size_t C1, std::size_t C2>
-inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y)
+inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y
+ , typename container_detail::enable_if_c< C1 != C2>::type * = 0)
{
x.swap(y);
}
Modified: trunk/boost/container/vector.hpp
==============================================================================
--- trunk/boost/container/vector.hpp (original)
+++ trunk/boost/container/vector.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -89,7 +89,11 @@
//Constructors
vector_const_iterator() BOOST_CONTAINER_NOEXCEPT
+ #ifndef NDEBUG
: m_ptr()
+ #else
+ // No value initialization of m_ptr() to speed up things a bit:
+ #endif
{}
//Pointer like operators
@@ -107,13 +111,13 @@
{ ++m_ptr; return *this; }
vector_const_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
- { Pointer tmp = m_ptr; ++*this; return vector_const_iterator(tmp); }
+ { return vector_const_iterator(m_ptr++); }
vector_const_iterator& operator--() BOOST_CONTAINER_NOEXCEPT
{ --m_ptr; return *this; }
vector_const_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
- { Pointer tmp = m_ptr; --*this; return vector_const_iterator(tmp); }
+ { return vector_const_iterator(m_ptr--); }
//Arithmetic
vector_const_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT
@@ -125,11 +129,11 @@
friend vector_const_iterator operator+(const vector_const_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT
{ return vector_const_iterator(x.m_ptr+off); }
- friend vector_const_iterator operator+(difference_type off, const vector_const_iterator& right) BOOST_CONTAINER_NOEXCEPT
- { return vector_const_iterator(off + right.m_ptr); }
+ friend vector_const_iterator operator+(difference_type off, vector_const_iterator right) BOOST_CONTAINER_NOEXCEPT
+ { right.m_ptr += off; return right; }
- friend vector_const_iterator operator-(const vector_const_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT
- { return vector_const_iterator(x.m_ptr-off); }
+ friend vector_const_iterator operator-(vector_const_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { left.m_ptr += off; return left; }
friend difference_type operator-(const vector_const_iterator &left, const vector_const_iterator& right) BOOST_CONTAINER_NOEXCEPT
{ return left.m_ptr - right.m_ptr; }
@@ -159,9 +163,10 @@
class vector_iterator
: public vector_const_iterator<Pointer>
{
+ typedef vector_const_iterator<Pointer> base_t;
public:
explicit vector_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT
- : vector_const_iterator<Pointer>(ptr)
+ : base_t(ptr)
{}
public:
@@ -173,6 +178,7 @@
//Constructors
vector_iterator() BOOST_CONTAINER_NOEXCEPT
+ : base_t()
{}
//Pointer like operators
@@ -180,7 +186,7 @@
{ return *this->m_ptr; }
value_type* operator->() const BOOST_CONTAINER_NOEXCEPT
- { return container_detail::to_raw_pointer(this->m_ptr); }
+ { return container_detail::to_raw_pointer(this->m_ptr); }
reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT
{ return this->m_ptr[off]; }
@@ -190,13 +196,13 @@
{ ++this->m_ptr; return *this; }
vector_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
- { pointer tmp = this->m_ptr; ++*this; return vector_iterator(tmp); }
+ { return vector_iterator(this->m_ptr++); }
vector_iterator& operator--() BOOST_CONTAINER_NOEXCEPT
{ --this->m_ptr; return *this; }
vector_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
- { vector_iterator tmp = *this; --*this; return vector_iterator(tmp); }
+ { return vector_iterator(this->m_ptr--); }
// Arithmetic
vector_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT
@@ -205,14 +211,14 @@
vector_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT
{ this->m_ptr -= off; return *this; }
- friend vector_iterator operator+(const vector_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT
- { return vector_iterator(x.m_ptr+off); }
+ friend vector_iterator operator+(vector_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { left.m_ptr += off; return left; }
- friend vector_iterator operator+(difference_type off, const vector_iterator& right) BOOST_CONTAINER_NOEXCEPT
- { return vector_iterator(off + right.m_ptr); }
+ friend vector_iterator operator+(difference_type off, vector_iterator right) BOOST_CONTAINER_NOEXCEPT
+ { right.m_ptr += off; return right; }
- friend vector_iterator operator-(const vector_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT
- { return vector_iterator(x.m_ptr-off); }
+ friend vector_iterator operator-(vector_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { left.m_ptr -= off; return left; }
};
template <class T, class Allocator>
@@ -271,35 +277,38 @@
//Constructor, does not throw
vector_alloc_holder()
BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value)
- : Allocator(), m_start(), m_size(0), m_capacity(0)
+ : Allocator(), m_start(), m_size(), m_capacity()
{}
//Constructor, does not throw
template<class AllocConvertible>
explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT
- : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(0), m_capacity(0)
+ : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
{}
//Constructor, does not throw
template<class AllocConvertible>
- explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type cap)
- : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
+ explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
+ : Allocator(boost::forward<AllocConvertible>(a))
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
{
- m_start = this->allocation_command
- (allocate_new, cap, cap, m_capacity, m_start).first;
+ m_start = this->allocation_command(allocate_new, initial_size, initial_size, m_capacity, m_start).first;
}
//Constructor, does not throw
- explicit vector_alloc_holder(size_type cap)
- : Allocator(), m_start(), m_size(), m_capacity()
+ explicit vector_alloc_holder(size_type initial_size)
+ : Allocator()
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
{
m_start = this->allocation_command
- (allocate_new, cap, cap, m_capacity, m_start).first;
+ (allocate_new, initial_size, initial_size, m_capacity, m_start).first;
}
vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_CONTAINER_NOEXCEPT
: Allocator(boost::move(static_cast<Allocator&>(holder)))
- , m_start(holder.m_start), m_size(holder.m_size), m_capacity(holder.m_capacity)
+ , m_start(holder.m_start)
+ , m_size(holder.m_size)
+ , m_capacity(holder.m_capacity)
{
holder.m_start = pointer();
holder.m_size = holder.m_capacity = 0;
@@ -311,6 +320,9 @@
(allocate_new, cap, cap, m_capacity, m_start).first;
}
+ void first_allocation_same_allocator_type(size_type cap)
+ { this->first_allocation(cap); }
+
//Destructor
~vector_alloc_holder() BOOST_CONTAINER_NOEXCEPT
{
@@ -347,6 +359,9 @@
container_detail::do_swap(this->m_start, x.m_start);
container_detail::do_swap(this->m_size, x.m_size);
container_detail::do_swap(this->m_capacity, x.m_capacity);
+ //And now the allocator
+ container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
+ container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
}
void move_from_empty(vector_alloc_holder &x) BOOST_CONTAINER_NOEXCEPT
@@ -400,43 +415,50 @@
//Constructor, does not throw
vector_alloc_holder()
BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value)
- : Allocator(), m_size(0)
+ : Allocator(), m_size()
{}
//Constructor, does not throw
template<class AllocConvertible>
explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT
- : Allocator(boost::forward<AllocConvertible>(a)), m_size(0)
+ : Allocator(boost::forward<AllocConvertible>(a)), m_size()
{}
//Constructor, does not throw
template<class AllocConvertible>
- explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type cap)
- : Allocator(boost::forward<AllocConvertible>(a)), m_size()
+ explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
+ : Allocator(boost::forward<AllocConvertible>(a))
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
{
- this->first_allocation(cap);
+ this->first_allocation(initial_size);
}
//Constructor, does not throw
- explicit vector_alloc_holder(size_type cap)
- : Allocator(), m_size()
+ explicit vector_alloc_holder(size_type initial_size)
+ : Allocator()
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
{
- this->first_allocation(cap);
+ this->first_allocation(initial_size);
}
vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
: Allocator(boost::move(static_cast<Allocator&>(holder)))
- , m_size()
+ , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
{
- this->priv_move_construct_impl(holder);
+ ::boost::container::uninitialized_move_alloc_n
+ (this->alloc(), container_detail::to_raw_pointer(holder.start()), m_size, this->start());
}
template<class OtherAllocator, class OtherAllocatorVersion>
vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> BOOST_RV_REF_END holder)
: Allocator()
- , m_size()
+ , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
{
- this->priv_move_construct_impl(holder);
+ //Different allocator type so we must check we have enough storage
+ const size_type n = holder.m_size;
+ this->first_allocation(n);
+ ::boost::container::uninitialized_move_alloc_n
+ (this->alloc(), container_detail::to_raw_pointer(holder.start()), n, this->start());
}
void first_allocation(size_type cap)
@@ -446,6 +468,9 @@
}
}
+ void first_allocation_same_allocator_type(size_type)
+ {}
+
//Destructor
~vector_alloc_holder() BOOST_CONTAINER_NOEXCEPT
{}
@@ -458,7 +483,7 @@
template<class OtherAllocator, class OtherAllocatorVersion>
void swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
{
- if(this->m_size > x.capacity() || x.m_size > this->capacity()){
+ if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){
throw_bad_alloc();
}
this->priv_swap_members_impl(x);
@@ -485,19 +510,6 @@
private:
template<class OtherAllocator, class OtherAllocatorVersion>
- void priv_move_construct_impl(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &holder)
- { //Containers with version 0 allocators can't be moved
- const size_type n = holder.m_size;
- this->first_allocation(n);
- //Copy first new elements in pos
- container_detail::move_insert_range_proxy<Allocator, const value_type*, value_type*> proxy
- (this->alloc(), container_detail::to_raw_pointer(holder.start()));
- proxy.uninitialized_copy_n_and_update
- (container_detail::to_raw_pointer(this->start()), n);
- this->m_size = n;
- }
-
- template<class OtherAllocator, class OtherAllocatorVersion>
void priv_swap_members_impl(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
{
value_type *const first_this = container_detail::to_raw_pointer(this->start());
@@ -530,7 +542,10 @@
#endif
class vector
{
- container_detail::vector_alloc_holder<Allocator> m_holder;
+ typedef container_detail::integral_constant
+ <unsigned, boost::container::container_detail::version
+ <Allocator>::value > alloc_version;
+ boost::container::container_detail::vector_alloc_holder<Allocator, alloc_version> m_holder;
/// @cond
typedef container_detail::vector_alloc_holder<Allocator> base_t;
typedef allocator_traits<Allocator> allocator_traits_type;
@@ -566,9 +581,6 @@
typedef container_detail::integral_constant<unsigned, 0> allocator_v0;
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
- typedef container_detail::integral_constant
- <unsigned, boost::container::container_detail::version
- <Allocator>::value > alloc_version;
typedef constant_iterator<T, difference_type> cvalue_iterator;
/// @endcond
@@ -609,8 +621,7 @@
explicit vector(size_type n)
: m_holder(n)
{
- this->priv_first_allocation_fill
- (container_detail::insert_default_constructed_n_proxy<Allocator, T*> (this->m_holder.alloc()), n);
+ boost::container::uninitialized_default_alloc_n(this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Constructs a vector
@@ -623,8 +634,8 @@
vector(size_type n, const T& value)
: m_holder(n)
{
- this->priv_first_allocation_fill
- (container_detail::insert_n_copies_proxy<Allocator, T*> (this->m_holder.alloc(), value), n);
+ boost::container::uninitialized_fill_alloc_n
+ (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
@@ -637,8 +648,8 @@
vector(size_type n, const T& value, const allocator_type& a)
: m_holder(a, n)
{
- this->priv_first_allocation_fill
- (container_detail::insert_n_copies_proxy<Allocator, T*> (this->m_holder.alloc(), value), n);
+ boost::container::uninitialized_fill_alloc_n
+ (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Constructs a vector
@@ -676,9 +687,9 @@
vector(const vector &x)
: m_holder(allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc()), x.size())
{
- this->priv_first_allocation_fill
- (container_detail::insert_range_proxy<Allocator, const T*, T*>
- (this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())), x.size());
+ ::boost::container::uninitialized_copy_or_move_alloc_n_source
+ ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
+ , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
@@ -717,9 +728,9 @@
vector(const vector &x, const allocator_type &a)
: m_holder(a, x.size())
{
- this->priv_first_allocation_fill
- (container_detail::insert_range_proxy<Allocator, const T*, T*>
- (this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())), x.size());
+ ::boost::container::uninitialized_copy_or_move_alloc_n_source
+ ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
+ , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Move constructor using the specified allocator.
@@ -737,10 +748,11 @@
}
else{
const size_type n = mx.size();
- this->m_holder.first_allocation(n);
- this->priv_first_allocation_fill
- (container_detail::move_insert_range_proxy<Allocator, const T*, T*>
- (this->m_holder.alloc(), container_detail::to_raw_pointer(mx.m_holder.start())), n);
+ this->m_holder.first_allocation_same_allocator_type(n);
+ ::boost::container::uninitialized_move_alloc_n_source
+ ( this->m_holder.alloc(), container_detail::to_raw_pointer(mx.m_holder.start())
+ , n, container_detail::to_raw_pointer(this->m_holder.start()));
+ this->m_holder.m_size = n;
}
}
@@ -767,17 +779,7 @@
vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
{
if (&x != this){
- allocator_type &this_alloc = this->m_holder.alloc();
- const allocator_type &x_alloc = x.m_holder.alloc();
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_copy_assignment::value> flag;
- if(flag && this_alloc != x_alloc){
- this->clear();
- this->shrink_to_fit();
- }
- container_detail::assign_alloc(this_alloc, x_alloc, flag);
- this->assign( container_detail::to_raw_pointer(x.m_holder.start())
- , container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size));
+ this->priv_copy_assign(boost::move(x), alloc_version());
}
return *this;
}
@@ -794,25 +796,7 @@
//iG BOOST_CONTAINER_NOEXCEPT_IF(!allocator_type::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<allocator_type>::value);)
BOOST_CONTAINER_NOEXCEPT
{
- if (&x != this){
- allocator_type &this_alloc = this->m_holder.alloc();
- allocator_type &x_alloc = x.m_holder.alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy objects but retain memory in case x reuses it in the future
- this->clear();
- this->m_holder.swap(x.m_holder);
- //Move allocator if needed
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_move_assignment::value> flag;
- container_detail::move_alloc(this_alloc, x_alloc, flag);
- }
- //If unequal allocators, then do a one by one move
- else{
- this->assign( boost::make_move_iterator(container_detail::to_raw_pointer(x.m_holder.start()))
- , boost::make_move_iterator(container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size)));
- }
- }
+ this->priv_move_assign(boost::move(x), alloc_version());
return *this;
}
@@ -829,8 +813,7 @@
template<class OtherAllocator, class OtherAllocatorVersion>
vector& operator=(BOOST_RV_REF_BEG vector<OtherAllocator, OtherAllocatorVersion> BOOST_RV_REF_END x)
{
- this->assign( boost::make_move_iterator(container_detail::to_raw_pointer(x.m_holder.start()))
- , boost::make_move_iterator(container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size)));
+ this->priv_move_assign(boost::move(x), alloc_version());
return *this;
}
@@ -1259,8 +1242,8 @@
}
else{
typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
- this->priv_forward_range_insert_at_end
- (1, type(this->m_holder.alloc(), ::boost::forward<Args>(args)...), alloc_version());
+ this->priv_forward_range_insert_no_capacity
+ (this->cend().get_ptr(), 1, type(this->m_holder.alloc(), ::boost::forward<Args>(args)...), alloc_version());
}
}
@@ -1300,7 +1283,8 @@
container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
<Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->m_holder.alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- this->priv_forward_range_insert_at_end(1, proxy, alloc_version()); \
+ this->priv_forward_range_insert_no_capacity \
+ (this->cend().get_ptr(), 1, proxy, alloc_version()); \
} \
} \
\
@@ -1482,9 +1466,6 @@
{
//Just swap internals in case of !allocator_v0. Otherwise, deep swap
this->m_holder.swap(x.m_holder);
- //And now the allocator
- container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
- container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), flag);
}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1531,6 +1512,125 @@
private:
+ template<class OtherAllocator, class AllocVersion>
+ void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , AllocVersion
+ , typename container_detail::enable_if_c
+ < container_detail::is_same<AllocVersion, allocator_v0>::value &&
+ !container_detail::is_same<OtherAllocator, allocator_type>::value
+ >::type * = 0)
+ {
+ if(this->capacity() < x.size()){
+ throw_bad_alloc();
+ }
+ this->priv_move_assign_impl(boost::move(x), AllocVersion());
+ }
+
+ template<class OtherAllocator, class AllocVersion>
+ void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , AllocVersion
+ , typename container_detail::enable_if_c
+ < !container_detail::is_same<AllocVersion, allocator_v0>::value ||
+ container_detail::is_same<OtherAllocator, allocator_type>::value
+ >::type * = 0)
+ {
+ this->priv_move_assign_impl(boost::move(x), AllocVersion());
+ }
+
+ template<class OtherAllocator, class AllocVersion>
+ void priv_move_assign_impl(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , AllocVersion
+ , typename container_detail::enable_if_c
+ < container_detail::is_same<AllocVersion, allocator_v0>::value
+ >::type * = 0)
+ {
+ T* const this_start = container_detail::to_raw_pointer(m_holder.start());
+ T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
+ const size_type this_sz = m_holder.m_size;
+ const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
+ if (this_sz < other_sz){
+ move_n(other_start, this_sz, this_start); // may throw
+ uninitialized_move_alloc_n( this->m_holder.alloc(), other_start + this_sz
+ , other_sz - this_sz, this_start + this_sz); // may throw
+ }
+ else
+ {
+ move_n(other_start, other_sz, this_start);
+ destroy_alloc_n(this->m_holder.alloc(), this_start + other_sz, this_sz - other_sz);
+ }
+ this->m_holder.m_size = other_sz;
+ }
+
+ template<class OtherAllocator, class AllocVersion>
+ void priv_move_assign_impl(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , AllocVersion
+ , typename container_detail::enable_if_c
+ < !container_detail::is_same<AllocVersion, allocator_v0>::value
+ >::type * = 0)
+ {
+ //for move constructor, no aliasing (&x != this) is assummed.
+ allocator_type &this_alloc = this->m_holder.alloc();
+ allocator_type &x_alloc = x.m_holder.alloc();
+ //If allocators are equal we can just swap pointers
+ if(this_alloc == x_alloc){
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ this->m_holder.swap(x.m_holder);
+ //Move allocator if needed
+ container_detail::bool_<allocator_traits_type::
+ propagate_on_container_move_assignment::value> flag;
+ container_detail::move_alloc(this_alloc, x_alloc, flag);
+ }
+ //If unequal allocators, then do a one by one move
+ else{
+ //TO-DO: optimize this
+ this->assign( boost::make_move_iterator(container_detail::to_raw_pointer(x.m_holder.start()))
+ , boost::make_move_iterator(container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size)));
+ }
+ }
+
+ template<class AllocVersion>
+ void priv_copy_assign(const vector &x, AllocVersion
+ , typename container_detail::enable_if_c
+ < container_detail::is_same<AllocVersion, allocator_v0>::value
+ >::type * = 0)
+ {
+ T* const this_start = container_detail::to_raw_pointer(m_holder.start());
+ T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
+ const size_type this_sz = m_holder.m_size;
+ const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
+ if (this_sz < other_sz){
+ copy_or_move_n(other_start, this_sz, this_start); // may throw
+ uninitialized_copy_or_move_alloc_n( this->m_holder.alloc(), other_start + this_sz
+ , other_sz - this_sz, this_start + this_sz); // may throw
+ }
+ else
+ {
+ copy_or_move_n(other_start, other_sz, this_start);
+ destroy_alloc_n(this->m_holder.alloc(), this_start + other_sz, this_sz - other_sz);
+ }
+ this->m_holder.m_size = other_sz;
+ }
+
+ template<class AllocVersion>
+ void priv_copy_assign(const vector &x, AllocVersion
+ , typename container_detail::enable_if_c
+ < !container_detail::is_same<AllocVersion, allocator_v0>::value
+ >::type * = 0)
+ {
+ allocator_type &this_alloc = this->m_holder.alloc();
+ const allocator_type &x_alloc = x.m_holder.alloc();
+ container_detail::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ this->shrink_to_fit();
+ }
+ container_detail::assign_alloc(this_alloc, x_alloc, flag);
+ this->assign( container_detail::to_raw_pointer(x.m_holder.start())
+ , container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size));
+ }
+
void priv_reserve(size_type, allocator_v0)
{
throw_bad_alloc();
@@ -1540,20 +1640,17 @@
{
//There is not enough memory, allocate a new buffer
pointer p = this->m_holder.allocate(new_cap);
-
- //We will reuse insert code, so create a dummy input iterator
- container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
- proxy(this->m_holder.alloc(), ::boost::make_move_iterator((T *)0));
//Backwards (and possibly forward) expansion
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc;
#endif
- this->priv_range_insert_new_allocation
- ( container_detail::to_raw_pointer(p)
- , new_cap
- , container_detail::to_raw_pointer(this->m_holder.start())
- , 0
- , proxy);
+ T * const raw_beg = container_detail::to_raw_pointer(this->m_holder.start());
+ const size_type sz = m_holder.m_size;
+ ::boost::container::uninitialized_move_alloc_n_source
+ ( this->m_holder.alloc(), raw_beg, sz, container_detail::to_raw_pointer(p) );
+ destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz);
+ this->m_holder.start(p);
+ this->m_holder.capacity(new_cap);
}
void priv_reserve(size_type new_cap, allocator_v2)
@@ -1575,14 +1672,13 @@
#endif
this->m_holder.capacity(real_cap);
}
-
//If there is no forward expansion, move objects
else{
- //We will reuse insert code, so create a dummy input iterator
- container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
- proxy(this->m_holder.alloc(), ::boost::make_move_iterator((T *)0));
//Backwards (and possibly forward) expansion
if(ret.second){
+ //We will reuse insert code, so create a dummy input iterator
+ container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
+ proxy(this->m_holder.alloc(), ::boost::make_move_iterator((T *)0));
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_expand_bwd;
#endif
@@ -1595,26 +1691,28 @@
}
//New buffer
else{
+ //Backwards (and possibly forward) expansion
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc;
#endif
- this->priv_range_insert_new_allocation
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(this->m_holder.start())
- , 0
- , proxy);
+ T * const raw_beg = container_detail::to_raw_pointer(this->m_holder.start());
+ const size_type sz = m_holder.m_size;
+ ::boost::container::uninitialized_move_alloc_n_source
+ ( this->m_holder.alloc(), raw_beg, sz, container_detail::to_raw_pointer(ret.first) );
+ destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz);
+ this->m_holder.start(ret.first);
+ this->m_holder.capacity(real_cap);
}
}
}
template<class Proxy>
- void priv_first_allocation_fill(Proxy proxy, size_type n)
+ void priv_uninitialized_fill(Proxy proxy, size_type n) const
{
//Copy first new elements in pos
proxy.uninitialized_copy_n_and_update
(container_detail::to_raw_pointer(this->m_holder.start()), n);
- this->m_holder.m_size = n;
+ //m_holder.size was already initialized to n in vector_alloc_holder's constructor
}
void priv_destroy(value_type* p) BOOST_CONTAINER_NOEXCEPT
@@ -1644,19 +1742,35 @@
, ::boost::forward<U>(x)), alloc_version());
}
- template <class U>
- void priv_push_back(BOOST_FWD_REF(U) x)
+ void priv_push_back(const T &x)
+ {
+ if (this->m_holder.m_size < this->m_holder.capacity()){
+ //There is more memory, just construct a new object at the end
+ allocator_traits_type::construct
+ ( this->m_holder.alloc()
+ , container_detail::to_raw_pointer(this->m_holder.start() + this->m_holder.m_size)
+ , x );
+ ++this->m_holder.m_size;
+ }
+ else{
+ container_detail::insert_copy_proxy<Allocator, T*> proxy(this->m_holder.alloc(), x);
+ this->priv_forward_range_insert_no_capacity(this->cend().get_ptr(), 1, proxy, alloc_version());
+ }
+ }
+
+ void priv_push_back(BOOST_RV_REF(T) x)
{
if (this->m_holder.m_size < this->m_holder.capacity()){
//There is more memory, just construct a new object at the end
allocator_traits_type::construct
( this->m_holder.alloc()
, container_detail::to_raw_pointer(this->m_holder.start() + this->m_holder.m_size)
- , ::boost::forward<U>(x) );
+ , ::boost::move(x) );
++this->m_holder.m_size;
}
else{
- this->priv_insert(this->cend(), ::boost::forward<U>(x));
+ container_detail::insert_move_proxy<Allocator, T*> proxy(this->m_holder.alloc(), x);
+ this->priv_forward_range_insert_no_capacity(this->cend().get_ptr(), 1, proxy, alloc_version());
}
}
@@ -1713,22 +1827,27 @@
}
template <class InsertionProxy>
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type, const InsertionProxy , allocator_v0)
+ {
+ throw_bad_alloc();
+ return iterator(pos);
+ }
+
+ template <class InsertionProxy>
iterator priv_forward_range_insert
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v0)
{
//Check if we have enough memory or try to expand current memory
const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
- const size_type n_pos = pos - this->m_holder.start();
- T *const raw_pos = container_detail::to_raw_pointer(pos);
- if (n <= remaining){
- this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
- }
- else{
+ if (n > remaining){
//This will trigger an error
throw_bad_alloc();
}
-
+ const size_type n_pos = pos - this->m_holder.start();
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+ this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
return iterator(this->m_holder.start() + n_pos);
}
@@ -1739,40 +1858,49 @@
//Check if we have enough memory or try to expand current memory
const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
- if (n <= remaining){
- this->priv_range_insert_at_end_expand_forward(n, insert_range_proxy);
- }
- else{
+ if (n > remaining){
//This will trigger an error
throw_bad_alloc();
}
-
+ this->priv_range_insert_at_end_expand_forward(n, insert_range_proxy);
return this->end();
}
template <class InsertionProxy>
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v1)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type n_pos = pos - this->m_holder.start();
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+
+ const size_type new_cap = this->m_holder.next_capacity(n);
+ T * new_buf = container_detail::to_raw_pointer(this->m_holder.alloc().allocate(new_cap));
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_range_insert_new_allocation
+ ( new_buf, new_cap, raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
+ }
+
+ template <class InsertionProxy>
iterator priv_forward_range_insert
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v1)
{
//Check if we have enough memory or try to expand current memory
const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
- const size_type n_pos = pos - this->m_holder.start();
T *const raw_pos = container_detail::to_raw_pointer(pos);
if (n <= remaining){
+ const size_type n_pos = pos - this->m_holder.start();
this->priv_range_insert_expand_forward
(raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
}
else{
- const size_type new_cap = this->m_holder.next_capacity(n);
- T * new_buf = container_detail::to_raw_pointer(this->m_holder.alloc().allocate(new_cap));
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
- #endif
- this->priv_range_insert_new_allocation
- ( new_buf, new_cap, raw_pos, n, insert_range_proxy);
+ return this->priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
}
- return iterator(this->m_holder.start() + n_pos);
}
template <class InsertionProxy>
@@ -1783,63 +1911,75 @@
}
template <class InsertionProxy>
- iterator priv_forward_range_insert
+ iterator priv_forward_range_insert_no_capacity
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
{
//Check if we have enough memory or try to expand current memory
- const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
const size_type n_pos = pos - this->m_holder.start();
T *const raw_pos = container_detail::to_raw_pointer(pos);
- bool same_buffer_start = n <= remaining;
- if (!same_buffer_start){
- size_type real_cap = 0;
- //There is not enough memory, allocate a new
- //buffer or expand the old one.
- std::pair<pointer, bool> ret = (this->m_holder.allocation_command
- (allocate_new | expand_fwd | expand_bwd,
- this->m_holder.m_size + n, this->m_holder.next_capacity(n), real_cap, this->m_holder.start()));
+ size_type real_cap = 0;
+ //There is not enough memory, allocate a new
+ //buffer or expand the old one.
+ std::pair<pointer, bool> ret = (this->m_holder.allocation_command
+ (allocate_new | expand_fwd | expand_bwd,
+ this->m_holder.m_size + n, this->m_holder.next_capacity(n), real_cap, this->m_holder.start()));
- //Buffer reallocated
- if(ret.second){
- //Forward expansion, delay insertion
- if(this->m_holder.start() == ret.first){
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_fwd;
- #endif
- this->m_holder.capacity(real_cap);
- //Expand forward
- this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
- }
- //Backwards (and possibly forward) expansion
- else{
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_bwd;
- #endif
- this->priv_range_insert_expand_backwards
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap, raw_pos, n, insert_range_proxy);
- }
+ //Buffer reallocated
+ if(ret.second){
+ //Forward expansion, delay insertion
+ if(this->m_holder.start() == ret.first){
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->m_holder.capacity(real_cap);
+ //Expand forward
+ this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
}
- //New buffer
+ //Backwards (and possibly forward) expansion
else{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
+ ++this->num_expand_bwd;
#endif
- this->priv_range_insert_new_allocation
+ this->priv_range_insert_expand_backwards
( container_detail::to_raw_pointer(ret.first)
, real_cap, raw_pos, n, insert_range_proxy);
}
}
+ //New buffer
else{
- //Expand forward
- this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_range_insert_new_allocation
+ ( container_detail::to_raw_pointer(ret.first)
+ , real_cap, raw_pos, n, insert_range_proxy);
}
return iterator(this->m_holder.start() + n_pos);
}
template <class InsertionProxy>
+ iterator priv_forward_range_insert
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+
+ bool same_buffer_start = n <= remaining;
+ if (!same_buffer_start){
+ return priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
+ }
+ else{
+ //Expand forward
+ const size_type n_pos = pos - this->m_holder.start();
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+ this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
+ }
+ }
+
+ template <class InsertionProxy>
iterator priv_forward_range_insert_at_end
(const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
{
@@ -1979,7 +2119,8 @@
//Case B:
else if((first_pos + shift_count) >= limit_pos){
//All uninitialized_moved
- ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
+ ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
hole_size = last_pos + shift_count - limit_pos;
}
//Case C:
Added: trunk/libs/container/bench/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/container/bench/Jamfile.v2 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -0,0 +1,34 @@
+# Boost Container Library Test Jamfile
+
+# (C) Copyright Ion Gaztanaga 2009.
+# Use, modification and distribution are subject to the
+# Boost Software License, Version 1.0. (See accompanying file
+# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# Adapted from John Maddock's TR1 Jamfile.v2
+# Copyright John Maddock 2005.
+# Use, modification and distribution are subject to the
+# Boost Software License, Version 1.0. (See accompanying file
+# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# this rule enumerates through all the sources and invokes
+# the run rule for each source, the result is a list of all
+# the run rules, which we can pass on to the test_suite rule:
+
+rule test_all
+{
+ local all_rules = ;
+
+ for local fileb in [ glob *.cpp ]
+ {
+ all_rules += [ run $(fileb) /boost/timer//boost_timer /boost/system//boost_system /boost/thread//boost_thread
+ : # additional args
+ : # test-files
+ : # requirements
+ ] ;
+ }
+
+ return $(all_rules) ;
+}
+
+test-suite container_test : [ test_all r ] ;
Added: trunk/libs/container/bench/bench_static_vector.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/container/bench/bench_static_vector.cpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -0,0 +1,147 @@
+// benchmark based on: http://cpp-next.com/archive/2010/10/howards-stl-move-semantics-benchmark/
+//
+// @file bench_static_vector.cpp
+// @date Aug 14, 2011
+// @author Andrew Hundt <ATHundt_at_[hidden]>
+//
+// (C) 2011-2012 Andrew Hundt <ATHundt_at_[hidden]>
+// (C) 2013 Ion Gaztanaga
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// @brief varray_benchmark.cpp compares the performance of boost::container::varray to boost::container::vector
+
+#include "varray.hpp"
+#include "boost/container/vector.hpp"
+#include "boost/container/static_vector.hpp"
+#include "../test/movable_int.hpp"
+#include <vector>
+#include <iostream>
+#include <boost/timer/timer.hpp>
+#include <set>
+#include <algorithm>
+#include <exception>
+
+using boost::timer::cpu_timer;
+using boost::timer::cpu_times;
+using boost::timer::nanosecond_type;
+
+#ifdef NDEBUG
+static const std::size_t N = 1000;
+#else
+static const std::size_t N = 100;
+#endif
+
+#define BENCH_SIMPLE_CONSTRUCTION
+//#define BENCH_TRIVIAL_TYPE
+
+#ifdef BENCH_TRIVIAL_TYPE
+typedef std::size_t basic_type_t;
+#else
+typedef boost::container::test::copyable_int basic_type_t;
+#endif
+
+template<typename T>
+T &get_set(std::size_t)
+{
+ #ifdef BENCH_SIMPLE_CONSTRUCTION
+ T &t = *new T(N);
+ for (std::size_t i = 0; i < N; ++i)
+ t[i] = basic_type_t(std::rand());
+ #else
+ T &t = *new T;
+ t.reserve(N);
+ for (std::size_t i = 0; i < N; ++i)
+ t.push_back(basic_type_t(std::rand()));
+ #endif
+ return t;
+}
+
+template<typename T>
+T &generate()
+{
+ T &v = *new T;
+ v.reserve(N);
+
+ for (std::size_t i = 0; i < N; ++i){
+ typename T::reference r = get_set<typename T::value_type>(i);
+ v.push_back(boost::move(r));
+ delete &r;
+ }
+ return v;
+}
+
+template<typename T>
+cpu_times time_it()
+{
+ cpu_timer sortTime,rotateTime,destructionTime;
+ sortTime.stop();rotateTime.stop();destructionTime.stop();
+ cpu_timer totalTime, constructTime;
+ std::srand (0);
+ for(std::size_t i = 0; i< N; ++i){
+
+ constructTime.resume();
+ {
+ T &v = generate<T>();
+ constructTime.stop();
+ sortTime.resume();
+ std::sort(v.begin(), v.end());
+ sortTime.stop();
+ rotateTime.resume();
+ std::rotate(v.begin(), v.begin() + v.size()/2, v.end());
+ rotateTime.stop();
+
+ destructionTime.resume();
+ delete &v;
+ }
+ destructionTime.stop();
+ }
+ totalTime.stop();
+ std::cout << " construction took " << boost::timer::format(constructTime.elapsed());
+ std::cout << " sort took " << boost::timer::format(sortTime.elapsed());
+ std::cout << " rotate took " << boost::timer::format(rotateTime.elapsed());
+ std::cout << " destruction took " << boost::timer::format(destructionTime.elapsed());
+ std::cout << " Total time = " << boost::timer::format(totalTime.elapsed()) << std::endl;
+ return totalTime.elapsed();
+}
+
+void compare_times(cpu_times time_numerator, cpu_times time_denominator){
+ std::cout
+ << "\n wall = " << ((double)time_numerator.wall/(double)time_denominator.wall)
+ << "\n user = " << ((double)time_numerator.user/(double)time_denominator.user)
+ << "\n system = " << ((double)time_numerator.system/(double)time_denominator.system)
+ << "\n (user+system) = " << ((double)(time_numerator.system+time_numerator.user)/(double)(time_denominator.system+time_denominator.user)) << "\n\n";
+}
+
+int main()
+{
+ try {
+ std::cout << "N = " << N << "\n\n";
+
+ std::cout << "varray benchmark:\n";
+ cpu_times time_varray = time_it<boost::container::varray<boost::container::varray<basic_type_t,N>,N > >();
+
+ std::cout << "boost::container::static_vector benchmark\n";
+ cpu_times time_boost_static_vector = time_it<boost::container::static_vector<boost::container::static_vector<basic_type_t,N>,N > >();
+
+ std::cout << "boost::container::vector benchmark\n";
+ cpu_times time_boost_vector = time_it<boost::container::vector<boost::container::vector<basic_type_t> > >();
+
+ std::cout << "std::vector benchmark\n";
+ cpu_times time_standard_vector = time_it<std::vector<std::vector<basic_type_t> > >();
+
+ std::cout << "varray/boost::container::vector total time comparison:";
+ compare_times(time_varray, time_boost_vector);
+
+ std::cout << "varray/boost::container::static_vector total time comparison:";
+ compare_times(time_varray, time_boost_static_vector);
+
+ std::cout << "varray/std::vector total time comparison:";
+ compare_times(time_varray,time_standard_vector);
+ }catch(std::exception e){
+ std::cout << e.what();
+ }
+ return 1;
+}
Added: trunk/libs/container/bench/detail/varray.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/container/bench/detail/varray.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -0,0 +1,2274 @@
+// Boost.Container varray
+//
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2013 Andrew Hundt.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTAINER_DETAIL_VARRAY_HPP
+#define BOOST_CONTAINER_DETAIL_VARRAY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/detail/preprocessor.hpp>
+
+#include "varray_util.hpp"
+#include "varray_concept.hpp"
+#include <boost/iterator/iterator_concepts.hpp>
+
+#ifndef BOOST_NO_EXCEPTIONS
+#include <stdexcept>
+#endif // BOOST_NO_EXCEPTIONS
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/swap.hpp>
+#include <boost/integer.hpp>
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/type_traits/is_unsigned.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+
+// TODO - use std::reverse_iterator and std::iterator_traits
+// instead Boost.Iterator to remove dependency?
+// or boost/detail/iterator.hpp ?
+#include <boost/iterator/reverse_iterator.hpp>
+
+/**
+ * @defgroup varray_non_member varray non-member functions
+ */
+
+namespace boost { namespace container { namespace container_detail {
+
+// Forward declaration
+template <typename Value, std::size_t Capacity, typename Strategy>
+class varray;
+
+namespace strategy {
+
+// TODO: Improve error messages
+// possibly include N in the strategy, and provide size as an optoinal allocate_failed parameter?
+// Example of current error with reserve(4) when capacity is 3:
+// "boost/container/varray.hpp(66): size can't exceed the capacity"
+// Could say
+// "cannot reserve(4) due to fixed capacity of 3 elements"
+
+//! @brief The default strategy.
+//!
+//! @tparam Value Type of element stored in the container.
+template <typename Value>
+struct def
+{
+ typedef Value value_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef Value* pointer;
+ typedef const Value* const_pointer;
+ typedef Value& reference;
+ typedef const Value& const_reference;
+
+ static void allocate_failed()
+ {
+ BOOST_ASSERT_MSG(false, "size can't exceed the capacity");
+ }
+};
+
+//! @brief The strategy adapting info from passed Allocator.
+//!
+//! This strategy defines the same types that are defined in the Allocator.
+//!
+//! @tparam Allocator The Allocator which will be adapted.
+template <typename Allocator>
+struct allocator_adaptor
+{
+ typedef typename Allocator::value_type value_type;
+ typedef typename Allocator::size_type size_type;
+ typedef typename Allocator::difference_type difference_type;
+ typedef typename Allocator::pointer pointer;
+ typedef typename Allocator::const_pointer const_pointer;
+ typedef typename Allocator::reference reference;
+ typedef typename Allocator::const_reference const_reference;
+
+ static void allocate_failed()
+ {
+ BOOST_ASSERT_MSG(false, "size can't exceed the capacity");
+ }
+};
+
+} // namespace strategy
+
+struct varray_error_handler
+{
+ template <typename V, std::size_t Capacity, typename S>
+ static void check_capacity(varray<V, Capacity, S> const&, std::size_t s)
+ {
+ if ( Capacity < s )
+ S::allocate_failed();
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_at(varray<V, C, S> const& v,
+ typename varray<V, C, S>::size_type i)
+ {
+ (void)v;
+ (void)i;
+// TODO - use BOOST_THROW_EXCEPTION here?
+#ifndef BOOST_NO_EXCEPTIONS
+ if ( v.size() <= i )
+ throw std::out_of_range("index out of bounds");
+#else // BOOST_NO_EXCEPTIONS
+ BOOST_ASSERT_MSG(i < v.size(), "index out of bounds");
+#endif // BOOST_NO_EXCEPTIONS
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_operator_brackets(varray<V, C, S> const& v,
+ typename varray<V, C, S>::size_type i)
+ {
+ (void)v;
+ (void)i;
+ BOOST_ASSERT_MSG(i < v.size(), "index out of bounds");
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_empty(varray<V, C, S> const& v)
+ {
+ (void)v;
+ BOOST_ASSERT_MSG(0 < v.size(), "the container is empty");
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_iterator_end_neq(varray<V, C, S> const& v,
+ typename varray<V, C, S>::const_iterator position)
+ {
+ (void)v;
+ (void)position;
+ BOOST_ASSERT_MSG(v.begin() <= position && position < v.end(), "iterator out of bounds");
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_iterator_end_eq(varray<V, C, S> const& v,
+ typename varray<V, C, S>::const_iterator position)
+ {
+ (void)v;
+ (void)position;
+ BOOST_ASSERT_MSG(v.begin() <= position && position <= v.end(), "iterator out of bounds");
+ }
+};
+
+template <typename Value, std::size_t Capacity, typename Strategy>
+struct varray_traits
+{
+ typedef typename Strategy::value_type value_type;
+ typedef typename Strategy::size_type size_type;
+ typedef typename Strategy::difference_type difference_type;
+ typedef typename Strategy::pointer pointer;
+ typedef typename Strategy::const_pointer const_pointer;
+ typedef typename Strategy::reference reference;
+ typedef typename Strategy::const_reference const_reference;
+
+ typedef varray_error_handler error_handler;
+
+ typedef boost::false_type use_memop_in_swap_and_move;
+ typedef boost::false_type use_optimized_swap;
+ typedef boost::false_type disable_trivial_init;
+};
+
+/**
+ * @brief A variable-size array container with fixed capacity.
+ *
+ * varray is a sequence container like boost::container::vector with contiguous storage that can
+ * change in size, along with the static allocation, low overhead, and fixed capacity of boost::array.
+ *
+ * A varray is a sequence that supports random access to elements, constant time insertion and
+ * removal of elements at the end, and linear time insertion and removal of elements at the beginning or
+ * in the middle. The number of elements in a varray may vary dynamically up to a fixed capacity
+ * because elements are stored within the object itself similarly to an array. However, objects are
+ * initialized as they are inserted into varray unlike C arrays or std::array which must construct
+ * all elements on instantiation. The behavior of varray enables the use of statically allocated
+ * elements in cases with complex object lifetime requirements that would otherwise not be trivially
+ * possible.
+ *
+ * @par Error Handling
+ * Insertion beyond the capacity and out of bounds errors result in undefined behavior unless
+ * otherwise specified. In this respect if size() == capacity(), then varray::push_back()
+ * behaves like std::vector pop_front() if size() == empty(). The reason for this difference
+ * is because unlike vectors, varray does not perform allocation.
+ *
+ * @par Advanced Usage
+ * Error handling behavior can be modified to more closely match std::vector exception behavior
+ * when exceeding bounds by providing an alternate Strategy and varray_traits instantiation.
+ *
+ * @tparam Value The type of element that will be stored.
+ * @tparam Capacity The maximum number of elements varray can store, fixed at compile time.
+ * @tparam Strategy Defines the public typedefs and error handlers,
+ * implements StaticVectorStrategy and has some similarities
+ * to an Allocator.
+ */
+template <typename Value, std::size_t Capacity, typename Strategy = strategy::def<Value> >
+class varray
+{
+ typedef container_detail::varray_traits<
+ Value, Capacity, Strategy
+ > vt;
+
+ typedef typename vt::error_handler errh;
+
+ BOOST_MPL_ASSERT_MSG(
+ ( boost::is_unsigned<typename vt::size_type>::value &&
+ sizeof(typename boost::uint_value_t<Capacity>::least) <= sizeof(typename vt::size_type) ),
+ SIZE_TYPE_IS_TOO_SMALL_FOR_SPECIFIED_CAPACITY,
+ (varray)
+ );
+
+ BOOST_CONCEPT_ASSERT((concept::VArrayStrategy<Strategy>));
+
+ typedef boost::aligned_storage<
+ sizeof(Value[Capacity]),
+ boost::alignment_of<Value[Capacity]>::value
+ > aligned_storage_type;
+
+ template <typename V, std::size_t C, typename S>
+ friend class varray;
+
+ BOOST_COPYABLE_AND_MOVABLE(varray)
+
+#ifdef BOOST_NO_RVALUE_REFERENCES
+public:
+ template <std::size_t C, typename S>
+ varray & operator=(varray<Value, C, S> & sv)
+ {
+ typedef varray<Value, C, S> other;
+ this->operator=(static_cast<const ::boost::rv<other> &>(const_cast<const other &>(sv)));
+ return *this;
+ }
+#endif
+
+public:
+ //! @brief The type of elements stored in the container.
+ typedef typename vt::value_type value_type;
+ //! @brief The unsigned integral type used by the container.
+ typedef typename vt::size_type size_type;
+ //! @brief The pointers difference type.
+ typedef typename vt::difference_type difference_type;
+ //! @brief The pointer type.
+ typedef typename vt::pointer pointer;
+ //! @brief The const pointer type.
+ typedef typename vt::const_pointer const_pointer;
+ //! @brief The value reference type.
+ typedef typename vt::reference reference;
+ //! @brief The value const reference type.
+ typedef typename vt::const_reference const_reference;
+
+ //! @brief The iterator type.
+ typedef pointer iterator;
+ //! @brief The const iterator type.
+ typedef const_pointer const_iterator;
+ //! @brief The reverse iterator type.
+ typedef boost::reverse_iterator<iterator> reverse_iterator;
+ //! @brief The const reverse iterator.
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ //! @brief The type of a strategy used by the varray.
+ typedef Strategy strategy_type;
+
+ //! @brief Constructs an empty varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ varray()
+ : m_size(0)
+ {}
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a varray containing count default constructed Values.
+ //!
+ //! @param count The number of values which will be contained in the container.
+ //!
+ //! @par Throws
+ //! If Value's default constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ explicit varray(size_type count)
+ : m_size(0)
+ {
+ this->resize(count); // may throw
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a varray containing count copies of value.
+ //!
+ //! @param count The number of copies of a values that will be contained in the container.
+ //! @param value The value which will be used to copy construct values.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(size_type count, value_type const& value)
+ : m_size(0)
+ {
+ this->resize(count, value); // may throw
+ }
+
+ //! @pre
+ //! @li <tt>distance(first, last) <= capacity()</tt>
+ //! @li Iterator must meet the \c ForwardTraversalIterator concept.
+ //!
+ //! @brief Constructs a varray containing copy of a range <tt>[first, last)</tt>.
+ //!
+ //! @param first The iterator to the first element in range.
+ //! @param last The iterator to the one after the last element in range.
+ //!
+ //! @par Throws
+ //! If Value's constructor taking a dereferenced Iterator throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ varray(Iterator first, Iterator last)
+ : m_size(0)
+ {
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
+
+ this->assign(first, last); // may throw
+ }
+
+ //! @brief Constructs a copy of other varray.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(varray const& other)
+ : m_size(other.size())
+ {
+ namespace sv = varray_detail;
+ sv::uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>.
+ //!
+ //! @brief Constructs a copy of other varray.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C, typename S>
+ varray(varray<value_type, C, S> const& other)
+ : m_size(other.size())
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+
+ namespace sv = varray_detail;
+ sv::uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw
+ }
+
+ //! @brief Copy assigns Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray & operator=(BOOST_COPY_ASSIGN_REF(varray) other)
+ {
+ this->assign(other.begin(), other.end()); // may throw
+
+ return *this;
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Copy assigns Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C, typename S>
+// TEMPORARY WORKAROUND
+#if defined(BOOST_NO_RVALUE_REFERENCES)
+ varray & operator=(::boost::rv< varray<value_type, C, S> > const& other)
+#else
+ varray & operator=(varray<value_type, C, S> const& other)
+#endif
+ {
+ this->assign(other.begin(), other.end()); // may throw
+
+ return *this;
+ }
+
+ //! @brief Move constructor. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(BOOST_RV_REF(varray) other)
+ {
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ this->move_ctor_dispatch(other, use_memop_in_swap_and_move());
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Move constructor. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move is false_type - default.
+ //! @endinternal
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C, typename S>
+ varray(BOOST_RV_REF_3_TEMPL_ARGS(varray, value_type, C, S) other)
+ : m_size(other.m_size)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ this->move_ctor_dispatch(other, use_memop_in_swap_and_move());
+ }
+
+ //! @brief Move assignment. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray & operator=(BOOST_RV_REF(varray) other)
+ {
+ if ( &other == this )
+ return *this;
+
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ this->move_assign_dispatch(other, use_memop_in_swap_and_move());
+
+ return *this;
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Move assignment. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
+ //! @endinternal
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C, typename S>
+ varray & operator=(BOOST_RV_REF_3_TEMPL_ARGS(varray, value_type, C, S) other)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ this->move_assign_dispatch(other, use_memop_in_swap_and_move());
+
+ return *this;
+ }
+
+ //! @brief Destructor. Destroys Values stored in this container.
+ //!
+ //! @par Throws
+ //! Nothing
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ ~varray()
+ {
+ namespace sv = varray_detail;
+ sv::destroy(this->begin(), this->end());
+ }
+
+ //! @brief Swaps contents of the other varray and this one.
+ //!
+ //! @param other The varray which content will be swapped with this one's content.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default.
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void swap(varray & other)
+ {
+ typedef typename
+ vt::use_optimized_swap use_optimized_swap;
+
+ this->swap_dispatch(other, use_optimized_swap());
+ }
+
+ //! @pre <tt>other.size() <= capacity() && size() <= other.capacity()</tt>
+ //!
+ //! @brief Swaps contents of the other varray and this one.
+ //!
+ //! @param other The varray which content will be swapped with this one's content.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default.
+ //! @endinternal
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C, typename S>
+ void swap(varray<value_type, C, S> & other)
+ {
+ errh::check_capacity(*this, other.size());
+ errh::check_capacity(other, this->size());
+
+ typedef typename
+ vt::use_optimized_swap use_optimized_swap;
+
+ this->swap_dispatch(other, use_optimized_swap());
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are default constructed.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //!
+ //! @par Throws
+ //! If Value's default constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void resize(size_type count)
+ {
+ namespace sv = varray_detail;
+ typedef typename vt::disable_trivial_init dti;
+
+ if ( count < m_size )
+ {
+ sv::destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ sv::uninitialized_fill(this->end(), this->begin() + count, dti()); // may throw
+ }
+ m_size = count; // update end
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are copy constructed from value.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void resize(size_type count, value_type const& value)
+ {
+ if ( count < m_size )
+ {
+ namespace sv = varray_detail;
+ sv::destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
+ }
+ m_size = count; // update end
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief This call has no effect because the Capacity of this container is constant.
+ //!
+ //! @param count The number of elements which the container should be able to contain.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void reserve(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Adds a copy of value at the end.
+ //!
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void push_back(value_type const& value)
+ {
+ typedef typename vt::disable_trivial_init dti;
+
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ namespace sv = varray_detail;
+ sv::construct(dti(), this->end(), value); // may throw
+ ++m_size; // update end
+ }
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Moves value to the end.
+ //!
+ //! @param value The value to move construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's move constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void push_back(BOOST_RV_REF(value_type) value)
+ {
+ typedef typename vt::disable_trivial_init dti;
+
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ namespace sv = varray_detail;
+ sv::construct(dti(), this->end(), ::boost::move(value)); // may throw
+ ++m_size; // update end
+ }
+
+ //! @pre <tt>!empty()</tt>
+ //!
+ //! @brief Destroys last value and decreases the size.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void pop_back()
+ {
+ errh::check_empty(*this);
+
+ namespace sv = varray_detail;
+ sv::destroy(this->end() - 1);
+ --m_size; // update end
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a copy of element at position.
+ //!
+ //! @param position The position at which the new value will be inserted.
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! @li If Value's copy constructor or copy assignment throws
+ //! @li If Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ iterator insert(iterator position, value_type const& value)
+ {
+ return this->priv_insert(position, value);
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a move-constructed element at position.
+ //!
+ //! @param position The position at which the new value will be inserted.
+ //! @param value The value used to move construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ iterator insert(iterator position, BOOST_RV_REF(value_type) value)
+ {
+ return this->priv_insert(position, boost::move(value));
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() + count <= capacity()</tt>
+ //!
+ //! @brief Inserts a count copies of value at position.
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param count The number of new elements which will be inserted.
+ //! @param value The value used to copy construct new elements.
+ //!
+ //! @par Throws
+ //! @li If Value's copy constructor or copy assignment throws.
+ //! @li If Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator insert(iterator position, size_type count, value_type const& value)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ if ( position == this->end() )
+ {
+ std::uninitialized_fill(position, position + count, value); // may throw
+ m_size += count; // update end
+ }
+ else
+ {
+ namespace sv = varray_detail;
+
+ difference_type to_move = std::distance(position, this->end());
+
+ // TODO - should following lines check for exception and revert to the old size?
+
+ if ( count < static_cast<size_type>(to_move) )
+ {
+ sv::uninitialized_move(this->end() - count, this->end(), this->end()); // may throw
+ m_size += count; // update end
+ sv::move_backward(position, position + to_move - count, this->end() - count); // may throw
+ std::fill_n(position, count, value); // may throw
+ }
+ else
+ {
+ std::uninitialized_fill(this->end(), position + count, value); // may throw
+ m_size += count - to_move; // update end
+ sv::uninitialized_move(position, position + to_move, position + count); // may throw
+ m_size += to_move; // update end
+ std::fill_n(position, to_move, value); // may throw
+ }
+ }
+
+ return position;
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>distance(first, last) <= capacity()</tt>
+ //! @li \c Iterator must meet the \c ForwardTraversalIterator concept.
+ //!
+ //! @brief Inserts a copy of a range <tt>[first, last)</tt> at position.
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param first The iterator to the first element of a range used to construct new elements.
+ //! @param last The iterator to the one after the last element of a range used to construct new elements.
+ //!
+ //! @par Throws
+ //! @li If Value's constructor and assignment taking a dereferenced \c Iterator.
+ //! @li If Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ iterator insert(iterator position, Iterator first, Iterator last)
+ {
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
+
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ this->insert_dispatch(position, first, last, traversal());
+
+ return position;
+ }
+
+ //! @pre \c position must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>
+ //!
+ //! @brief Erases Value from position.
+ //!
+ //! @param position The position of the element which will be erased from the container.
+ //!
+ //! @par Throws
+ //! If Value's move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator erase(iterator position)
+ {
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_neq(*this, position);
+
+ //TODO - add empty check?
+ //errh::check_empty(*this);
+
+ sv::move(position + 1, this->end(), position); // may throw
+ sv::destroy(this->end() - 1);
+ --m_size;
+
+ return position;
+ }
+
+ //! @pre
+ //! @li \c first and \c last must define a valid range
+ //! @li iterators must be in range <tt>[begin(), end()]</tt>
+ //!
+ //! @brief Erases Values from a range <tt>[first, last)</tt>.
+ //!
+ //! @param first The position of the first element of a range which will be erased from the container.
+ //! @param last The position of the one after the last element of a range which will be erased from the container.
+ //!
+ //! @par Throws
+ //! If Value's move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator erase(iterator first, iterator last)
+ {
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_eq(*this, first);
+ errh::check_iterator_end_eq(*this, last);
+
+ difference_type n = std::distance(first, last);
+
+ //TODO - add invalid range check?
+ //BOOST_ASSERT_MSG(0 <= n, "invalid range");
+ //TODO - add this->size() check?
+ //BOOST_ASSERT_MSG(n <= this->size(), "invalid range");
+
+ sv::move(last, this->end(), first); // may throw
+ sv::destroy(this->end() - n, this->end());
+ m_size -= n;
+
+ return first;
+ }
+
+ //! @pre <tt>distance(first, last) <= capacity()</tt>
+ //!
+ //! @brief Assigns a range <tt>[first, last)</tt> of Values to this container.
+ //!
+ //! @param first The iterator to the first element of a range used to construct new content of this container.
+ //! @param last The iterator to the one after the last element of a range used to construct new content of this container.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last)
+ {
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
+
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ this->assign_dispatch(first, last, traversal()); // may throw
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Assigns a count copies of value to this container.
+ //!
+ //! @param count The new number of elements which will be container in the container.
+ //! @param value The value which will be used to copy construct the new content.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void assign(size_type count, value_type const& value)
+ {
+ if ( count < m_size )
+ {
+ namespace sv = varray_detail;
+
+ std::fill_n(this->begin(), count, value); // may throw
+ sv::destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ std::fill_n(this->begin(), m_size, value); // may throw
+ std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
+ }
+ m_size = count; // update end
+ }
+
+#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
+#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a Value constructed with
+ //! \c std::forward<Args>(args)... in the end of the container.
+ //!
+ //! @param args The arguments of the constructor of the new element which will be created at the end of the container.
+ //!
+ //! @par Throws
+ //! If in-place constructor throws or Value's move constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ template<class ...Args>
+ void emplace_back(BOOST_FWD_REF(Args) ...args)
+ {
+ typedef typename vt::disable_trivial_init dti;
+
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ namespace sv = varray_detail;
+ sv::construct(dti(), this->end(), ::boost::forward<Args>(args)...); // may throw
+ ++m_size; // update end
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a Value constructed with
+ //! \c std::forward<Args>(args)... before position
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param args The arguments of the constructor of the new element.
+ //!
+ //! @par Throws
+ //! If in-place constructor throws or if Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ template<class ...Args>
+ iterator emplace(iterator position, BOOST_FWD_REF(Args) ...args)
+ {
+ typedef typename vt::disable_trivial_init dti;
+
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ if ( position == this->end() )
+ {
+ sv::construct(dti(), position, ::boost::forward<Args>(args)...); // may throw
+ ++m_size; // update end
+ }
+ else
+ {
+ // TODO - should following lines check for exception and revert to the old size?
+
+ // TODO - should move be used only if it's nonthrowing?
+ value_type & r = *(this->end() - 1);
+ sv::construct(dti(), this->end(), boost::move(r)); // may throw
+ ++m_size; // update end
+ sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw
+
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> temp_storage;
+ value_type * val_p = static_cast<value_type *>(temp_storage.address());
+ sv::construct(dti(), val_p, ::boost::forward<Args>(args)...); // may throw
+ sv::scoped_destructor<value_type> d(val_p);
+ sv::assign(position, ::boost::move(*val_p)); // may throw
+ }
+
+ return position;
+ }
+
+#else // BOOST_CONTAINER_PERFECT_FORWARDING || BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ typedef typename vt::disable_trivial_init dti; \
+ \
+ errh::check_capacity(*this, m_size + 1); /*may throw*/\
+ \
+ namespace sv = varray_detail; \
+ sv::construct(dti(), this->end() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ ++m_size; /*update end*/ \
+ } \
+ //
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(iterator position BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ typedef typename vt::disable_trivial_init dti; \
+ namespace sv = varray_detail; \
+ \
+ errh::check_iterator_end_eq(*this, position); \
+ errh::check_capacity(*this, m_size + 1); /*may throw*/\
+ \
+ if ( position == this->end() ) \
+ { \
+ sv::construct(dti(), position BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ ++m_size; /*update end*/ \
+ } \
+ else \
+ { \
+ /* TODO - should following lines check for exception and revert to the old size? */ \
+ /* TODO - should move be used only if it's nonthrowing? */ \
+ \
+ value_type & r = *(this->end() - 1); \
+ sv::construct(dti(), this->end(), boost::move(r)); /*may throw*/\
+ ++m_size; /*update end*/ \
+ sv::move_backward(position, this->end() - 2, this->end() - 1); /*may throw*/\
+ \
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> temp_storage; \
+ value_type * val_p = static_cast<value_type *>(temp_storage.address()); \
+ sv::construct(dti(), val_p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ sv::scoped_destructor<value_type> d(val_p); \
+ sv::assign(position, ::boost::move(*val_p)); /*may throw*/\
+ } \
+ \
+ return position; \
+ } \
+ //
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+#endif // BOOST_CONTAINER_PERFECT_FORWARDING || BOOST_CONTAINER_DOXYGEN_INVOKED
+#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
+
+ //! @brief Removes all elements from the container.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void clear()
+ {
+ namespace sv = varray_detail;
+ sv::destroy(this->begin(), this->end());
+ m_size = 0; // update end
+ }
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! \c std::out_of_range exception by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference at(size_type i)
+ {
+ errh::check_at(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns const reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return const reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! \c std::out_of_range exception by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference at(size_type i) const
+ {
+ errh::check_at(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference operator[](size_type i)
+ {
+ // TODO: Remove bounds check? std::vector and std::array operator[] don't check.
+ errh::check_operator_brackets(*this, i);
+ return *(this->begin() + i);
+ }
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns const reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return const reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference operator[](size_type i) const
+ {
+ errh::check_operator_brackets(*this, i);
+ return *(this->begin() + i);
+ }
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns reference to the first element.
+ //!
+ //! @return reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference front()
+ {
+ errh::check_empty(*this);
+ return *(this->begin());
+ }
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns const reference to the first element.
+ //!
+ //! @return const reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference front() const
+ {
+ errh::check_empty(*this);
+ return *(this->begin());
+ }
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns reference to the last element.
+ //!
+ //! @return reference to the last element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference back()
+ {
+ errh::check_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns const reference to the first element.
+ //!
+ //! @return const reference to the last element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference back() const
+ {
+ errh::check_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ //! @brief Pointer such that <tt>[data(), data() + size())</tt> is a valid range.
+ //! For a non-empty vector <tt>data() == &front()</tt>.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ Value * data()
+ {
+ return boost::addressof(*(this->ptr()));
+ }
+
+ //! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
+ //! For a non-empty vector <tt>data() == &front()</tt>.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const Value * data() const
+ {
+ return boost::addressof(*(this->ptr()));
+ }
+
+
+ //! @brief Returns iterator to the first element.
+ //!
+ //! @return iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator begin() { return this->ptr(); }
+
+ //! @brief Returns const iterator to the first element.
+ //!
+ //! @return const_iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator begin() const { return this->ptr(); }
+
+ //! @brief Returns const iterator to the first element.
+ //!
+ //! @return const_iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator cbegin() const { return this->ptr(); }
+
+ //! @brief Returns iterator to the one after the last element.
+ //!
+ //! @return iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator end() { return this->begin() + m_size; }
+
+ //! @brief Returns const iterator to the one after the last element.
+ //!
+ //! @return const_iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator end() const { return this->begin() + m_size; }
+
+ //! @brief Returns const iterator to the one after the last element.
+ //!
+ //! @return const_iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator cend() const { return this->cbegin() + m_size; }
+
+ //! @brief Returns reverse iterator to the first element of the reversed container.
+ //!
+ //! @return reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reverse_iterator rbegin() { return reverse_iterator(this->end()); }
+
+ //! @brief Returns const reverse iterator to the first element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
+
+ //! @brief Returns const reverse iterator to the first element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
+
+ //! @brief Returns reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reverse_iterator rend() { return reverse_iterator(this->begin()); }
+
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
+
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type capacity() { return Capacity; }
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type max_size() { return Capacity; }
+
+ //! @brief Returns the number of stored elements.
+ //!
+ //! @return Number of elements contained in the container.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ size_type size() const { return m_size; }
+
+ //! @brief Queries if the container contains elements.
+ //!
+ //! @return true if the number of elements contained in the
+ //! container is equal to 0.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ bool empty() const { return 0 == m_size; }
+
+private:
+
+ // @par Throws
+ // Nothing.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C, typename S>
+ void move_ctor_dispatch(varray<value_type, C, S> & other, boost::true_type /*use_memop*/)
+ {
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size);
+ m_size = other.m_size;
+ }
+
+ // @par Throws
+ // @li If boost::has_nothrow_move<Value>::value is true and Value's move constructor throws
+ // @li If boost::has_nothrow_move<Value>::value is false and Value's copy constructor throws.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C, typename S>
+ void move_ctor_dispatch(varray<value_type, C, S> & other, boost::false_type /*use_memop*/)
+ {
+ namespace sv = varray_detail;
+ sv::uninitialized_move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw
+ m_size = other.m_size;
+ }
+
+ // @par Throws
+ // Nothing.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C, typename S>
+ void move_assign_dispatch(varray<value_type, C, S> & other, boost::true_type /*use_memop*/)
+ {
+ this->clear();
+
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size);
+ boost::swap(m_size, other.m_size);
+ }
+
+ // @par Throws
+ // @li If boost::has_nothrow_move<Value>::value is true and Value's move constructor or move assignment throws
+ // @li If boost::has_nothrow_move<Value>::value is false and Value's copy constructor or move assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C, typename S>
+ void move_assign_dispatch(varray<value_type, C, S> & other, boost::false_type /*use_memop*/)
+ {
+ namespace sv = varray_detail;
+ if ( m_size <= static_cast<size_type>(other.size()) )
+ {
+ sv::move_if_noexcept(other.begin(), other.begin() + m_size, this->begin()); // may throw
+ // TODO - perform uninitialized_copy first?
+ sv::uninitialized_move_if_noexcept(other.begin() + m_size, other.end(), this->end()); // may throw
+ }
+ else
+ {
+ sv::move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw
+ sv::destroy(this->begin() + other.size(), this->end());
+ }
+ m_size = other.size(); // update end
+ }
+
+ // @par Throws
+ // Nothing.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C, typename S>
+ void swap_dispatch(varray<value_type, C, S> & other, boost::true_type const& /*use_optimized_swap*/)
+ {
+ typedef typename
+ boost::mpl::if_c<
+ Capacity < C,
+ aligned_storage_type,
+ typename varray<value_type, C, S>::aligned_storage_type
+ >::type
+ storage_type;
+
+ storage_type temp;
+ Value * temp_ptr = reinterpret_cast<Value*>(temp.address());
+
+ ::memcpy(temp_ptr, this->data(), sizeof(Value) * this->size());
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.size());
+ ::memcpy(other.data(), temp_ptr, sizeof(Value) * this->size());
+
+ boost::swap(m_size, other.m_size);
+ }
+
+ // @par Throws
+ // If Value's move constructor or move assignment throws
+ // but only if use_memop_in_swap_and_move is false_type - default.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C, typename S>
+ void swap_dispatch(varray<value_type, C, S> & other, boost::false_type const& /*use_optimized_swap*/)
+ {
+ namespace sv = varray_detail;
+
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ if ( this->size() < other.size() )
+ swap_dispatch_impl(this->begin(), this->end(), other.begin(), other.end(), use_memop_in_swap_and_move()); // may throw
+ else
+ swap_dispatch_impl(other.begin(), other.end(), this->begin(), this->end(), use_memop_in_swap_and_move()); // may throw
+ boost::swap(m_size, other.m_size);
+ }
+
+ // @par Throws
+ // Nothing.
+ // @par Complexity
+ // Linear O(N).
+ void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::true_type const& /*use_memop*/)
+ {
+ //BOOST_ASSERT_MSG(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la));
+
+ namespace sv = varray_detail;
+ for (; first_sm != last_sm ; ++first_sm, ++first_la)
+ {
+ boost::aligned_storage<
+ sizeof(value_type),
+ boost::alignment_of<value_type>::value
+ > temp_storage;
+ value_type * temp_ptr = reinterpret_cast<value_type*>(temp_storage.address());
+
+ ::memcpy(temp_ptr, boost::addressof(*first_sm), sizeof(value_type));
+ ::memcpy(boost::addressof(*first_sm), boost::addressof(*first_la), sizeof(value_type));
+ ::memcpy(boost::addressof(*first_la), temp_ptr, sizeof(value_type));
+ }
+
+ ::memcpy(first_sm, first_la, sizeof(value_type) * std::distance(first_la, last_la));
+ }
+
+ // @par Throws
+ // If Value's move constructor or move assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::false_type const& /*use_memop*/)
+ {
+ //BOOST_ASSERT_MSG(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la));
+
+ namespace sv = varray_detail;
+ for (; first_sm != last_sm ; ++first_sm, ++first_la)
+ {
+ //boost::swap(*first_sm, *first_la); // may throw
+ value_type temp(boost::move(*first_sm)); // may throw
+ *first_sm = boost::move(*first_la); // may throw
+ *first_la = boost::move(temp); // may throw
+ }
+ sv::uninitialized_move(first_la, last_la, first_sm); // may throw
+ sv::destroy(first_la, last_la);
+ }
+
+ // insert
+
+ // @par Throws
+ // If Value's move constructor or move assignment throws
+ // or if Value's copy assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename V>
+ iterator priv_insert(iterator position, V & value)
+ {
+ typedef typename vt::disable_trivial_init dti;
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ if ( position == this->end() )
+ {
+ sv::construct(dti(), position, value); // may throw
+ ++m_size; // update end
+ }
+ else
+ {
+ // TODO - should following lines check for exception and revert to the old size?
+
+ // TODO - should move be used only if it's nonthrowing?
+ value_type & r = *(this->end() - 1);
+ sv::construct(dti(), this->end(), boost::move(r)); // may throw
+ ++m_size; // update end
+ sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw
+ sv::assign(position, value); // may throw
+ }
+
+ return position;
+ }
+
+ // insert
+
+ // @par Throws
+ // If Value's move constructor, move assignment throws
+ // or if Value's copy constructor or copy assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator>
+ void insert_dispatch(iterator position, Iterator first, Iterator last, boost::random_access_traversal_tag const&)
+ {
+ BOOST_CONCEPT_ASSERT((boost_concepts::RandomAccessTraversal<Iterator>)); // Make sure you passed a RandomAccessIterator
+
+ errh::check_iterator_end_eq(*this, position);
+
+ typename boost::iterator_difference<Iterator>::type
+ count = std::distance(first, last);
+
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ if ( position == this->end() )
+ {
+ namespace sv = varray_detail;
+
+ sv::uninitialized_copy(first, last, position); // may throw
+ m_size += count; // update end
+ }
+ else
+ {
+ this->insert_in_the_middle(position, first, last, count); // may throw
+ }
+ }
+
+ // @par Throws
+ // If Value's move constructor, move assignment throws
+ // or if Value's copy constructor or copy assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator, typename Traversal>
+ void insert_dispatch(iterator position, Iterator first, Iterator last, Traversal const& /*not_random_access*/)
+ {
+ errh::check_iterator_end_eq(*this, position);
+
+ if ( position == this->end() )
+ {
+ namespace sv = varray_detail;
+
+ std::ptrdiff_t d = std::distance(position, this->begin() + Capacity);
+ std::size_t count = sv::uninitialized_copy_s(first, last, position, d); // may throw
+
+ errh::check_capacity(*this, count <= static_cast<std::size_t>(d) ? m_size + count : Capacity + 1); // may throw
+
+ m_size += count;
+ }
+ else
+ {
+ typename boost::iterator_difference<Iterator>::type
+ count = std::distance(first, last);
+
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ this->insert_in_the_middle(position, first, last, count); // may throw
+ }
+ }
+
+ // @par Throws
+ // If Value's move constructor, move assignment throws
+ // or if Value's copy constructor or copy assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator>
+ void insert_in_the_middle(iterator position, Iterator first, Iterator last, difference_type count)
+ {
+ namespace sv = varray_detail;
+
+ difference_type to_move = std::distance(position, this->end());
+
+ // TODO - should following lines check for exception and revert to the old size?
+
+ if ( count < to_move )
+ {
+ sv::uninitialized_move(this->end() - count, this->end(), this->end()); // may throw
+ m_size += count; // update end
+ sv::move_backward(position, position + to_move - count, this->end() - count); // may throw
+ sv::copy(first, last, position); // may throw
+ }
+ else
+ {
+ Iterator middle_iter = first;
+ std::advance(middle_iter, to_move);
+
+ sv::uninitialized_copy(middle_iter, last, this->end()); // may throw
+ m_size += count - to_move; // update end
+ sv::uninitialized_move(position, position + to_move, position + count); // may throw
+ m_size += to_move; // update end
+ sv::copy(first, middle_iter, position); // may throw
+ }
+ }
+
+ // assign
+
+ // @par Throws
+ // If Value's constructor or assignment taking dereferenced Iterator throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator>
+ void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const& /*not_random_access*/)
+ {
+ namespace sv = varray_detail;
+
+ typename boost::iterator_difference<Iterator>::type
+ s = std::distance(first, last);
+
+ errh::check_capacity(*this, s); // may throw
+
+ if ( m_size <= static_cast<size_type>(s) )
+ {
+ sv::copy(first, first + m_size, this->begin()); // may throw
+ // TODO - perform uninitialized_copy first?
+ sv::uninitialized_copy(first + m_size, last, this->end()); // may throw
+ }
+ else
+ {
+ sv::copy(first, last, this->begin()); // may throw
+ sv::destroy(this->begin() + s, this->end());
+ }
+ m_size = s; // update end
+ }
+
+ // @par Throws
+ // If Value's constructor or assignment taking dereferenced Iterator throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator, typename Traversal>
+ void assign_dispatch(Iterator first, Iterator last, Traversal const& /*not_random_access*/)
+ {
+ namespace sv = varray_detail;
+
+ size_type s = 0;
+ iterator it = this->begin();
+
+ for ( ; it != this->end() && first != last ; ++it, ++first, ++s )
+ *it = *first; // may throw
+
+ sv::destroy(it, this->end());
+
+ std::ptrdiff_t d = std::distance(it, this->begin() + Capacity);
+ std::size_t count = sv::uninitialized_copy_s(first, last, it, d); // may throw
+ s += count;
+
+ errh::check_capacity(*this, count <= static_cast<std::size_t>(d) ? s : Capacity + 1); // may throw
+
+ m_size = s; // update end
+ }
+
+ pointer ptr()
+ {
+ return pointer(static_cast<Value*>(m_storage.address()));
+ }
+
+ const_pointer ptr() const
+ {
+ return const_pointer(static_cast<const Value*>(m_storage.address()));
+ }
+
+ size_type m_size;
+ aligned_storage_type m_storage;
+};
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template<typename Value, typename Strategy>
+class varray<Value, 0, Strategy>
+{
+ typedef varray_traits<
+ Value, 0, Strategy
+ > vt;
+
+ typedef typename vt::size_type stored_size_type;
+ typedef typename vt::error_handler errh;
+
+public:
+ typedef typename vt::value_type value_type;
+ typedef stored_size_type size_type;
+ typedef typename vt::difference_type difference_type;
+ typedef typename vt::pointer pointer;
+ typedef typename vt::const_pointer const_pointer;
+ typedef typename vt::reference reference;
+ typedef typename vt::const_reference const_reference;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef boost::reverse_iterator<iterator> reverse_iterator;
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ // nothrow
+ varray() {}
+
+ // strong
+ explicit varray(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ varray(size_type count, value_type const&)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ varray(varray const& other)
+ {
+ //errh::check_capacity(*this, count);
+ }
+
+ // strong
+ template <size_t C, typename S>
+ varray(varray<value_type, C, S> const& other)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+ }
+
+ // strong
+ template <typename Iterator>
+ varray(Iterator first, Iterator last)
+ {
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ varray & operator=(varray const& other)
+ {
+ //errh::check_capacity(*this, other.size());
+ return *this;
+ }
+
+ // basic
+ template <size_t C, typename S>
+ varray & operator=(varray<value_type, C, S> const& other)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+ return *this;
+ }
+
+ // nothrow
+ ~varray() {}
+
+ // strong
+ void resize(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ void resize(size_type count, value_type const&)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+
+ // nothrow
+ void reserve(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ void push_back(value_type const&)
+ {
+ errh::check_capacity(*this, 1); // may throw
+ }
+
+ // nothrow
+ void pop_back()
+ {
+ errh::check_empty(*this);
+ }
+
+ // basic
+ void insert(iterator position, value_type const&)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, 1); // may throw
+ }
+
+ // basic
+ void insert(iterator position, size_type count, value_type const&)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // basic
+ template <typename Iterator>
+ void insert(iterator, Iterator first, Iterator last)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ void erase(iterator position)
+ {
+ errh::check_iterator_end_neq(*this, position);
+ }
+
+ // basic
+ void erase(iterator first, iterator last)
+ {
+ errh::check_iterator_end_eq(*this, first);
+ errh::check_iterator_end_eq(*this, last);
+
+ //BOOST_ASSERT_MSG(0 <= n, "invalid range");
+ }
+
+ // basic
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ void assign(size_type count, value_type const&)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // nothrow
+ void clear() {}
+
+ // strong
+ reference at(size_type i)
+ {
+ errh::check_at(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ // strong
+ const_reference at(size_type i) const
+ {
+ errh::check_at(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ reference operator[](size_type i)
+ {
+ errh::check_operator_brackets(*this, i);
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ const_reference operator[](size_type i) const
+ {
+ errh::check_operator_brackets(*this, i);
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ reference front()
+ {
+ errh::check_empty(*this);
+ return *(this->begin());
+ }
+
+ // nothrow
+ const_reference front() const
+ {
+ errh::check_empty(*this);
+ return *(this->begin());
+ }
+
+ // nothrow
+ reference back()
+ {
+ errh::check_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ // nothrow
+ const_reference back() const
+ {
+ errh::check_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ // nothrow
+ Value * data() { return boost::addressof(*(this->ptr())); }
+ const Value * data() const { return boost::addressof(*(this->ptr())); }
+
+ // nothrow
+ iterator begin() { return this->ptr(); }
+ const_iterator begin() const { return this->ptr(); }
+ const_iterator cbegin() const { return this->ptr(); }
+ iterator end() { return this->begin(); }
+ const_iterator end() const { return this->begin(); }
+ const_iterator cend() const { return this->cbegin(); }
+ // nothrow
+ reverse_iterator rbegin() { return reverse_iterator(this->end()); }
+ const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
+ const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
+ reverse_iterator rend() { return reverse_iterator(this->begin()); }
+ const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
+ const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
+
+ // nothrow
+ size_type capacity() const { return 0; }
+ size_type max_size() const { return 0; }
+ size_type size() const { return 0; }
+ bool empty() const { return true; }
+
+private:
+
+ pointer ptr()
+ {
+ return pointer(reinterpret_cast<Value*>(this));
+ }
+
+ const_pointer ptr() const
+ {
+ return const_pointer(reinterpret_cast<const Value*>(this));
+ }
+};
+
+#endif // !BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! @brief Checks if contents of two varrays are equal.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if containers have the same size and elements in both containers are equal.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
+bool operator== (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
+{
+ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());
+}
+
+//! @brief Checks if contents of two varrays are not equal.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if containers have different size or elements in both containers are not equal.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
+bool operator!= (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
+{
+ return !(x==y);
+}
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if x compares lexicographically less than y.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
+bool operator< (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
+{
+ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if y compares lexicographically less than x.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
+bool operator> (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
+{
+ return y<x;
+}
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if y don't compare lexicographically less than x.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
+bool operator<= (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
+{
+ return !(y<x);
+}
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if x don't compare lexicographically less than y.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
+bool operator>= (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
+{
+ return !(x<y);
+}
+
+//! @brief Swaps contents of two varrays.
+//!
+//! This function calls varray::swap().
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
+inline void swap(varray<V, C1, S1> & x, varray<V, C2, S2> & y)
+{
+ x.swap(y);
+}
+
+}}} // namespace boost::container::container_detail
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_DETAIL_VARRAY_HPP
Added: trunk/libs/container/bench/detail/varray_concept.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/container/bench/detail/varray_concept.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -0,0 +1,60 @@
+// Boost.Container varray
+//
+// Copyright (c) 2012-2013 Andrew Hundt.
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTAINER_VARRAY_CONCEPT_HPP
+#define BOOST_CONTAINER_VARRAY_CONCEPT_HPP
+
+#include <boost/concept_check.hpp>
+
+namespace boost { namespace container { namespace container_detail { namespace concept {
+
+/**
+ * VArrayStrategyConcept
+ *
+ * \brief Checks strategy for varray<Value,Capacity,Strategy>, which has similarities to std::Allocator
+ * \ingroup varray
+ */
+template<typename Strategy>
+struct VArrayStrategy {
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // typedefs are the same as in std::Allocator
+ typedef typename Strategy::value_type value_type;
+ typedef typename Strategy::size_type size_type;
+ typedef typename Strategy::difference_type difference_type;
+ typedef typename Strategy::pointer pointer;
+ typedef typename Strategy::const_pointer const_pointer;
+ typedef typename Strategy::reference reference;
+ typedef typename Strategy::const_reference const_reference;
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy const* str = 0;
+
+ // must implement allocate_failed
+ str->allocate_failed();
+
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(VArrayStrategy)
+ {
+ check_methods::apply();
+ }
+
+#endif
+};
+
+}}}} // namespace boost::container::container_detail::concept
+
+#endif //BOOST_CONTAINER_VARRAY_CONCEPT_HPP
Added: trunk/libs/container/bench/detail/varray_util.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/container/bench/detail/varray_util.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -0,0 +1,712 @@
+// Boost.Container
+//
+// varray details
+//
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2013 Andrew Hundt.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
+#define BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
+
+#include <cstddef>
+#include <cstring>
+#include <memory>
+#include <limits>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/int.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+//#include <boost/type_traits/has_nothrow_constructor.hpp>
+//#include <boost/type_traits/has_nothrow_copy.hpp>
+//#include <boost/type_traits/has_nothrow_assign.hpp>
+//#include <boost/type_traits/has_nothrow_destructor.hpp>
+
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/config.hpp>
+#include <boost/move/move.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+// TODO - move vectors iterators optimization to the other, optional file instead of checking defines?
+
+#if defined(BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
+#include <vector>
+#include <boost/container/vector.hpp>
+#endif // BOOST_CONTAINER_VARRAY_ENABLE_ITERATORS_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
+
+namespace boost { namespace container { namespace varray_detail {
+
+template <typename I>
+struct are_elements_contiguous : boost::is_pointer<I>
+{};
+
+#if defined(BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
+
+template <typename Pointer>
+struct are_elements_contiguous<
+ boost::container::container_detail::vector_const_iterator<Pointer>
+> : boost::true_type
+{};
+
+template <typename Pointer>
+struct are_elements_contiguous<
+ boost::container::container_detail::vector_iterator<Pointer>
+> : boost::true_type
+{};
+
+#if defined(BOOST_DINKUMWARE_STDLIB)
+
+template <typename T>
+struct are_elements_contiguous<
+ std::_Vector_const_iterator<T>
+> : boost::true_type
+{};
+
+template <typename T>
+struct are_elements_contiguous<
+ std::_Vector_iterator<T>
+> : boost::true_type
+{};
+
+#elif defined(BOOST_GNU_STDLIB)
+
+template <typename P, typename T, typename A>
+struct are_elements_contiguous<
+ __gnu_cxx::__normal_iterator<P, std::vector<T, A> >
+> : boost::true_type
+{};
+
+#elif defined(_LIBCPP_VERSION)
+
+// TODO - test it first
+//template <typename P>
+//struct are_elements_contiguous<
+// __wrap_iter<P>
+//> : boost::true_type
+//{};
+
+#else // OTHER_STDLIB
+
+// TODO - add other iterators implementations
+
+#endif // STDLIB
+
+#endif // BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
+
+}}} // namespace boost::container::varray_detail
+
+namespace boost { namespace container { namespace varray_detail {
+
+template <typename I, typename O>
+struct are_corresponding :
+ ::boost::mpl::and_<
+ ::boost::is_same<
+ ::boost::remove_const<
+ typename ::boost::iterator_value<I>::type
+ >,
+ ::boost::remove_const<
+ typename ::boost::iterator_value<O>::type
+ >
+ >,
+ are_elements_contiguous<I>,
+ are_elements_contiguous<O>
+ >
+{};
+
+template <typename I, typename V>
+struct is_corresponding_value :
+ ::boost::is_same<
+ ::boost::remove_const<
+ typename ::boost::iterator_value<I>::type
+ >,
+ ::boost::remove_const<V>
+ >
+{};
+
+// destroy(I, I)
+
+template <typename I>
+void destroy_dispatch(I /*first*/, I /*last*/,
+ boost::true_type const& /*has_trivial_destructor*/)
+{}
+
+template <typename I>
+void destroy_dispatch(I first, I last,
+ boost::false_type const& /*has_trivial_destructor*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ for ( ; first != last ; ++first )
+ first->~value_type();
+}
+
+template <typename I>
+void destroy(I first, I last)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ destroy_dispatch(first, last, has_trivial_destructor<value_type>());
+}
+
+// destroy(I)
+
+template <typename I>
+void destroy_dispatch(I /*pos*/,
+ boost::true_type const& /*has_trivial_destructor*/)
+{}
+
+template <typename I>
+void destroy_dispatch(I pos,
+ boost::false_type const& /*has_trivial_destructor*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ pos->~value_type();
+}
+
+template <typename I>
+void destroy(I pos)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ destroy_dispatch(pos, has_trivial_destructor<value_type>());
+}
+
+// copy(I, I, O)
+
+template <typename I, typename O>
+inline O copy_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<true> const& /*use_memmove*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);
+
+ ::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
+ return dst + d;
+}
+
+template <typename I, typename O>
+inline O copy_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<false> const& /*use_memmove*/)
+{
+ return std::copy(first, last, dst); // may throw
+}
+
+template <typename I, typename O>
+inline O copy(I first, I last, O dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<I, O>,
+ ::boost::has_trivial_assign<
+ typename ::boost::iterator_value<O>::type
+ >
+ >::type
+ use_memmove;
+
+ return copy_dispatch(first, last, dst, use_memmove()); // may throw
+}
+
+// uninitialized_copy(I, I, O)
+
+template <typename I, typename O>
+inline
+O uninitialized_copy_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);
+
+ ::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
+ return dst + d;
+}
+
+template <typename I, typename F>
+inline
+F uninitialized_copy_dispatch(I first, I last, F dst,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ return std::uninitialized_copy(first, last, dst); // may throw
+}
+
+template <typename I, typename F>
+inline
+F uninitialized_copy(I first, I last, F dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<I, F>,
+ ::boost::has_trivial_copy<
+ typename ::boost::iterator_value<F>::type
+ >
+ >::type
+ use_memcpy;
+
+ return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
+}
+
+// uninitialized_move(I, I, O)
+
+template <typename I, typename O>
+inline
+O uninitialized_move_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);
+
+ ::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
+ return dst + d;
+}
+
+template <typename I, typename O>
+inline
+O uninitialized_move_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ //return boost::uninitialized_move(first, last, dst); // may throw
+
+ O o = dst;
+
+ BOOST_TRY
+ {
+ typedef typename std::iterator_traits<O>::value_type value_type;
+ for (; first != last; ++first, ++o )
+ new (boost::addressof(*o)) value_type(boost::move(*first));
+ }
+ BOOST_CATCH(...)
+ {
+ destroy(dst, o);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ return dst;
+}
+
+template <typename I, typename O>
+inline
+O uninitialized_move(I first, I last, O dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<I, O>,
+ ::boost::has_trivial_copy<
+ typename ::boost::iterator_value<O>::type
+ >
+ >::type
+ use_memcpy;
+
+ return uninitialized_move_dispatch(first, last, dst, use_memcpy()); // may throw
+}
+
+// TODO - move uses memmove - implement 2nd version using memcpy?
+
+// move(I, I, O)
+
+template <typename I, typename O>
+inline
+O move_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<true> const& /*use_memmove*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);
+
+ ::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
+ return dst + d;
+}
+
+template <typename I, typename O>
+inline
+O move_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<false> const& /*use_memmove*/)
+{
+ return boost::move(first, last, dst); // may throw
+}
+
+template <typename I, typename O>
+inline
+O move(I first, I last, O dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<I, O>,
+ ::boost::has_trivial_assign<
+ typename ::boost::iterator_value<O>::type
+ >
+ >::type
+ use_memmove;
+
+ return move_dispatch(first, last, dst, use_memmove()); // may throw
+}
+
+// move_backward(BDI, BDI, BDO)
+
+template <typename BDI, typename BDO>
+inline
+BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
+ boost::mpl::bool_<true> const& /*use_memmove*/)
+{
+ typedef typename boost::iterator_value<BDI>::type value_type;
+ typename boost::iterator_difference<BDI>::type d = std::distance(first, last);
+
+ BDO foo(dst - d);
+ ::memmove(boost::addressof(*foo), boost::addressof(*first), sizeof(value_type) * d);
+ return foo;
+}
+
+template <typename BDI, typename BDO>
+inline
+BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
+ boost::mpl::bool_<false> const& /*use_memmove*/)
+{
+ return boost::move_backward(first, last, dst); // may throw
+}
+
+template <typename BDI, typename BDO>
+inline
+BDO move_backward(BDI first, BDI last, BDO dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<BDI, BDO>,
+ ::boost::has_trivial_assign<
+ typename ::boost::iterator_value<BDO>::type
+ >
+ >::type
+ use_memmove;
+
+ return move_backward_dispatch(first, last, dst, use_memmove()); // may throw
+}
+
+template <typename T>
+struct has_nothrow_move : public
+ ::boost::mpl::or_<
+ boost::mpl::bool_<
+ ::boost::has_nothrow_move<
+ typename ::boost::remove_const<T>::type
+ >::value
+ >,
+ boost::mpl::bool_<
+ ::boost::has_nothrow_move<T>::value
+ >
+ >
+{};
+
+// uninitialized_move_if_noexcept(I, I, O)
+
+template <typename I, typename O>
+inline
+O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)
+{ return uninitialized_move(first, last, dst); }
+
+template <typename I, typename O>
+inline
+O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)
+{ return uninitialized_copy(first, last, dst); }
+
+template <typename I, typename O>
+inline
+O uninitialized_move_if_noexcept(I first, I last, O dst)
+{
+ typedef typename has_nothrow_move<
+ typename ::boost::iterator_value<O>::type
+ >::type use_move;
+
+ return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
+}
+
+// move_if_noexcept(I, I, O)
+
+template <typename I, typename O>
+inline
+O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)
+{ return move(first, last, dst); }
+
+template <typename I, typename O>
+inline
+O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)
+{ return copy(first, last, dst); }
+
+template <typename I, typename O>
+inline
+O move_if_noexcept(I first, I last, O dst)
+{
+ typedef typename has_nothrow_move<
+ typename ::boost::iterator_value<O>::type
+ >::type use_move;
+
+ return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
+}
+
+// uninitialized_fill(I, I)
+
+template <typename I>
+inline
+void uninitialized_fill_dispatch(I first, I last,
+ boost::true_type const& /*has_trivial_constructor*/,
+ boost::true_type const& /*disable_trivial_init*/)
+{}
+
+template <typename I>
+inline
+void uninitialized_fill_dispatch(I first, I last,
+ boost::true_type const& /*has_trivial_constructor*/,
+ boost::false_type const& /*disable_trivial_init*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ for ( ; first != last ; ++first )
+ new (boost::addressof(*first)) value_type();
+}
+
+template <typename I, typename DisableTrivialInit>
+inline
+void uninitialized_fill_dispatch(I first, I last,
+ boost::false_type const& /*has_trivial_constructor*/,
+ DisableTrivialInit const& /*not_used*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ I it = first;
+
+ BOOST_TRY
+ {
+ for ( ; it != last ; ++it )
+ new (boost::addressof(*it)) value_type(); // may throw
+ }
+ BOOST_CATCH(...)
+ {
+ destroy(first, it);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+}
+
+template <typename I, typename DisableTrivialInit>
+inline
+void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ uninitialized_fill_dispatch(first, last, boost::has_trivial_constructor<value_type>(), disable_trivial_init); // may throw
+}
+
+// construct(I)
+
+template <typename I>
+inline
+void construct_dispatch(boost::mpl::bool_<true> const& /*dont_init*/, I pos)
+{}
+
+template <typename I>
+inline
+void construct_dispatch(boost::mpl::bool_<false> const& /*dont_init*/, I pos)
+{
+ typedef typename ::boost::iterator_value<I>::type value_type;
+ new (static_cast<void*>(::boost::addressof(*pos))) value_type(); // may throw
+}
+
+template <typename DisableTrivialInit, typename I>
+inline
+void construct(DisableTrivialInit const&, I pos)
+{
+ typedef typename ::boost::iterator_value<I>::type value_type;
+ typedef typename ::boost::mpl::and_<
+ boost::has_trivial_constructor<value_type>,
+ DisableTrivialInit
+ >::type dont_init;
+
+ construct_dispatch(dont_init(), pos); // may throw
+}
+
+// construct(I, V)
+
+template <typename I, typename V>
+inline
+void construct_dispatch(I pos, V const& v,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
+}
+
+template <typename I, typename P>
+inline
+void construct_dispatch(I pos, P const& p,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(p); // may throw
+}
+
+template <typename DisableTrivialInit, typename I, typename P>
+inline
+void construct(DisableTrivialInit const&,
+ I pos, P const& p)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ is_corresponding_value<I, P>,
+ ::boost::has_trivial_copy<P>
+ >::type
+ use_memcpy;
+
+ construct_dispatch(pos, p, use_memcpy()); // may throw
+}
+
+// Needed by push_back(V &&)
+
+template <typename DisableTrivialInit, typename I, typename P>
+inline
+void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ is_corresponding_value<I, P>,
+ ::boost::has_trivial_copy<P>
+ >::type
+ use_memcpy;
+
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(::boost::move(p)); // may throw
+}
+
+// Needed by emplace_back() and emplace()
+
+#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+
+template <typename DisableTrivialInit, typename I, class ...Args>
+inline
+void construct(DisableTrivialInit const&,
+ I pos,
+ BOOST_FWD_REF(Args) ...args)
+{
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw
+}
+
+#else // !BOOST_NO_VARIADIC_TEMPLATES
+
+// BOOST_NO_RVALUE_REFERENCES -> P0 const& p0
+// !BOOST_NO_RVALUE_REFERENCES -> P0 && p0
+// which means that version with one parameter may take V const& v
+
+#define BOOST_PP_LOCAL_MACRO(n) \
+template <typename DisableTrivialInit, typename I, typename P BOOST_PP_ENUM_TRAILING_PARAMS(n, typename P) > \
+inline \
+void construct(DisableTrivialInit const&, \
+ I pos, \
+ BOOST_CONTAINER_PP_PARAM(P, p) \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+{ \
+ typedef typename boost::iterator_value<I>::type V; \
+ new \
+ (static_cast<void*>(boost::addressof(*pos))) \
+ V(p, BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); /*may throw*/ \
+} \
+//
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+#include BOOST_PP_LOCAL_ITERATE()
+
+#endif // !BOOST_NO_VARIADIC_TEMPLATES
+#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
+
+// assign(I, V)
+
+template <typename I, typename V>
+inline
+void assign_dispatch(I pos, V const& v,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
+}
+
+template <typename I, typename V>
+inline
+void assign_dispatch(I pos, V const& v,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ *pos = v; // may throw
+}
+
+template <typename I, typename V>
+inline
+void assign(I pos, V const& v)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ is_corresponding_value<I, V>,
+ ::boost::has_trivial_assign<V>
+ >::type
+ use_memcpy;
+
+ assign_dispatch(pos, v, use_memcpy()); // may throw
+}
+
+template <typename I, typename V>
+inline
+void assign(I pos, BOOST_RV_REF(V) v)
+{
+ *pos = boost::move(v); // may throw
+}
+
+
+// uninitialized_copy_s
+
+template <typename I, typename F>
+inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count)
+{
+ std::size_t count = 0;
+ F it = dest;
+
+ BOOST_TRY
+ {
+ for ( ; first != last ; ++it, ++first, ++count )
+ {
+ if ( max_count <= count )
+ return (std::numeric_limits<std::size_t>::max)();
+
+ // dummy 0 as DisableTrivialInit
+ construct(0, it, *first); // may throw
+ }
+ }
+ BOOST_CATCH(...)
+ {
+ destroy(dest, it);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ return count;
+}
+
+// scoped_destructor
+
+template<class T>
+class scoped_destructor
+{
+public:
+ scoped_destructor(T * ptr) : m_ptr(ptr) {}
+
+ ~scoped_destructor()
+ {
+ if(m_ptr)
+ destroy(m_ptr);
+ }
+
+ void release() { m_ptr = 0; }
+
+private:
+ T * m_ptr;
+};
+
+}}} // namespace boost::container::varray_detail
+
+#endif // BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
Added: trunk/libs/container/bench/varray.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/container/bench/varray.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -0,0 +1,994 @@
+// Boost.Container varray
+//
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2013 Andrew Hundt.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTAINER_VARRAY_HPP
+#define BOOST_CONTAINER_VARRAY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+
+#include "detail/varray.hpp"
+
+namespace boost { namespace container {
+
+/**
+ * @defgroup varray_non_member varray non-member functions
+ */
+
+/**
+ * @brief A variable-size array container with fixed capacity.
+ *
+ * varray is a sequence container like boost::container::vector with contiguous storage that can
+ * change in size, along with the static allocation, low overhead, and fixed capacity of boost::array.
+ *
+ * A varray is a sequence that supports random access to elements, constant time insertion and
+ * removal of elements at the end, and linear time insertion and removal of elements at the beginning or
+ * in the middle. The number of elements in a varray may vary dynamically up to a fixed capacity
+ * because elements are stored within the object itself similarly to an array. However, objects are
+ * initialized as they are inserted into varray unlike C arrays or std::array which must construct
+ * all elements on instantiation. The behavior of varray enables the use of statically allocated
+ * elements in cases with complex object lifetime requirements that would otherwise not be trivially
+ * possible.
+ *
+ * @par Error Handling
+ * Insertion beyond the capacity and out of bounds errors result in undefined behavior.
+ * The reason for this is because unlike vectors, varray does not perform allocation.
+ *
+ * @tparam Value The type of element that will be stored.
+ * @tparam Capacity The maximum number of elements varray can store, fixed at compile time.
+ */
+template <typename Value, std::size_t Capacity>
+class varray
+ : public container_detail::varray<Value, Capacity>
+{
+ typedef container_detail::varray<Value, Capacity> base_t;
+
+ BOOST_COPYABLE_AND_MOVABLE(varray)
+
+public:
+ //! @brief The type of elements stored in the container.
+ typedef typename base_t::value_type value_type;
+ //! @brief The unsigned integral type used by the container.
+ typedef typename base_t::size_type size_type;
+ //! @brief The pointers difference type.
+ typedef typename base_t::difference_type difference_type;
+ //! @brief The pointer type.
+ typedef typename base_t::pointer pointer;
+ //! @brief The const pointer type.
+ typedef typename base_t::const_pointer const_pointer;
+ //! @brief The value reference type.
+ typedef typename base_t::reference reference;
+ //! @brief The value const reference type.
+ typedef typename base_t::const_reference const_reference;
+ //! @brief The iterator type.
+ typedef typename base_t::iterator iterator;
+ //! @brief The const iterator type.
+ typedef typename base_t::const_iterator const_iterator;
+ //! @brief The reverse iterator type.
+ typedef typename base_t::reverse_iterator reverse_iterator;
+ //! @brief The const reverse iterator.
+ typedef typename base_t::const_reverse_iterator const_reverse_iterator;
+
+ //! @brief Constructs an empty varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ varray()
+ : base_t()
+ {}
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a varray containing count default constructed Values.
+ //!
+ //! @param count The number of values which will be contained in the container.
+ //!
+ //! @par Throws
+ //! If Value's default constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ explicit varray(size_type count)
+ : base_t(count)
+ {}
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a varray containing count copies of value.
+ //!
+ //! @param count The number of copies of a values that will be contained in the container.
+ //! @param value The value which will be used to copy construct values.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(size_type count, value_type const& value)
+ : base_t(count, value)
+ {}
+
+ //! @pre
+ //! @li <tt>distance(first, last) <= capacity()</tt>
+ //! @li Iterator must meet the \c ForwardTraversalIterator concept.
+ //!
+ //! @brief Constructs a varray containing copy of a range <tt>[first, last)</tt>.
+ //!
+ //! @param first The iterator to the first element in range.
+ //! @param last The iterator to the one after the last element in range.
+ //!
+ //! @par Throws
+ //! If Value's constructor taking a dereferenced Iterator throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ varray(Iterator first, Iterator last)
+ : base_t(first, last)
+ {}
+
+ //! @brief Constructs a copy of other varray.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(varray const& other)
+ : base_t(other)
+ {}
+
+ //! @pre <tt>other.size() <= capacity()</tt>.
+ //!
+ //! @brief Constructs a copy of other varray.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ varray(varray<value_type, C> const& other) : base_t(other) {}
+
+ //! @brief Copy assigns Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray & operator=(BOOST_COPY_ASSIGN_REF(varray) other)
+ {
+ base_t::operator=(static_cast<base_t const&>(other));
+ return *this;
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Copy assigns Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+// TEMPORARY WORKAROUND
+#if defined(BOOST_NO_RVALUE_REFERENCES)
+ varray & operator=(::boost::rv< varray<value_type, C> > const& other)
+#else
+ varray & operator=(varray<value_type, C> const& other)
+#endif
+ {
+ base_t::operator=(static_cast<varray<value_type, C> const&>(other));
+ return *this;
+ }
+
+ //! @brief Move constructor. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(BOOST_RV_REF(varray) other)
+ : base_t(boost::move(static_cast<base_t&>(other)))
+ {}
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Move constructor. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ varray(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other)
+ : base_t(boost::move(static_cast<container_detail::varray<value_type, C>&>(other)))
+ {}
+
+ //! @brief Move assignment. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray & operator=(BOOST_RV_REF(varray) other)
+ {
+ base_t::operator=(boost::move(static_cast<base_t&>(other)));
+ return *this;
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Move assignment. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ varray & operator=(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other)
+ {
+ base_t::operator=(boost::move(static_cast<container_detail::varray<value_type, C>&>(other)));
+ return *this;
+ }
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! @brief Destructor. Destroys Values stored in this container.
+ //!
+ //! @par Throws
+ //! Nothing
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ ~varray();
+
+ //! @brief Swaps contents of the other varray and this one.
+ //!
+ //! @param other The varray which content will be swapped with this one's content.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void swap(varray & other);
+
+ //! @pre <tt>other.size() <= capacity() && size() <= other.capacity()</tt>
+ //!
+ //! @brief Swaps contents of the other varray and this one.
+ //!
+ //! @param other The varray which content will be swapped with this one's content.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ void swap(varray<value_type, C> & other);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are default constructed.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //!
+ //! @par Throws
+ //! If Value's default constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void resize(size_type count);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are copy constructed from value.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void resize(size_type count, value_type const& value);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief This call has no effect because the Capacity of this container is constant.
+ //!
+ //! @param count The number of elements which the container should be able to contain.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void reserve(size_type count);
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Adds a copy of value at the end.
+ //!
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void push_back(value_type const& value);
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Moves value to the end.
+ //!
+ //! @param value The value to move construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's move constructor throws.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void push_back(BOOST_RV_REF(value_type) value);
+
+ //! @pre <tt>!empty()</tt>
+ //!
+ //! @brief Destroys last value and decreases the size.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void pop_back();
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a copy of element at position.
+ //!
+ //! @param position The position at which the new value will be inserted.
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! @li If Value's copy constructor or copy assignment throws
+ //! @li If Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ iterator insert(iterator position, value_type const& value);
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a move-constructed element at position.
+ //!
+ //! @param position The position at which the new value will be inserted.
+ //! @param value The value used to move construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ iterator insert(iterator position, BOOST_RV_REF(value_type) value);
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() + count <= capacity()</tt>
+ //!
+ //! @brief Inserts a count copies of value at position.
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param count The number of new elements which will be inserted.
+ //! @param value The value used to copy construct new elements.
+ //!
+ //! @par Throws
+ //! @li If Value's copy constructor or copy assignment throws.
+ //! @li If Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator insert(iterator position, size_type count, value_type const& value);
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>distance(first, last) <= capacity()</tt>
+ //! @li \c Iterator must meet the \c ForwardTraversalIterator concept.
+ //!
+ //! @brief Inserts a copy of a range <tt>[first, last)</tt> at position.
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param first The iterator to the first element of a range used to construct new elements.
+ //! @param last The iterator to the one after the last element of a range used to construct new elements.
+ //!
+ //! @par Throws
+ //! @li If Value's constructor and assignment taking a dereferenced \c Iterator.
+ //! @li If Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ iterator insert(iterator position, Iterator first, Iterator last);
+
+ //! @pre \c position must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>
+ //!
+ //! @brief Erases Value from position.
+ //!
+ //! @param position The position of the element which will be erased from the container.
+ //!
+ //! @par Throws
+ //! If Value's move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator erase(iterator position);
+
+ //! @pre
+ //! @li \c first and \c last must define a valid range
+ //! @li iterators must be in range <tt>[begin(), end()]</tt>
+ //!
+ //! @brief Erases Values from a range <tt>[first, last)</tt>.
+ //!
+ //! @param first The position of the first element of a range which will be erased from the container.
+ //! @param last The position of the one after the last element of a range which will be erased from the container.
+ //!
+ //! @par Throws
+ //! If Value's move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator erase(iterator first, iterator last);
+
+ //! @pre <tt>distance(first, last) <= capacity()</tt>
+ //!
+ //! @brief Assigns a range <tt>[first, last)</tt> of Values to this container.
+ //!
+ //! @param first The iterator to the first element of a range used to construct new content of this container.
+ //! @param last The iterator to the one after the last element of a range used to construct new content of this container.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Assigns a count copies of value to this container.
+ //!
+ //! @param count The new number of elements which will be container in the container.
+ //! @param value The value which will be used to copy construct the new content.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void assign(size_type count, value_type const& value);
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a Value constructed with
+ //! \c std::forward<Args>(args)... in the end of the container.
+ //!
+ //! @param args The arguments of the constructor of the new element which will be created at the end of the container.
+ //!
+ //! @par Throws
+ //! If in-place constructor throws or Value's move constructor throws.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ template<class ...Args>
+ void emplace_back(Args &&...args);
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a Value constructed with
+ //! \c std::forward<Args>(args)... before position
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param args The arguments of the constructor of the new element.
+ //!
+ //! @par Throws
+ //! If in-place constructor throws or if Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ template<class ...Args>
+ iterator emplace(iterator position, Args &&...args);
+
+ //! @brief Removes all elements from the container.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void clear();
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! \c std::out_of_range exception by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference at(size_type i);
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns const reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return const reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! \c std::out_of_range exception by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference at(size_type i) const;
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference operator[](size_type i);
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns const reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return const reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference operator[](size_type i) const;
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns reference to the first element.
+ //!
+ //! @return reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference front();
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns const reference to the first element.
+ //!
+ //! @return const reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference front() const;
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns reference to the last element.
+ //!
+ //! @return reference to the last element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference back();
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns const reference to the first element.
+ //!
+ //! @return const reference to the last element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference back() const;
+
+ //! @brief Pointer such that <tt>[data(), data() + size())</tt> is a valid range.
+ //! For a non-empty vector <tt>data() == &front()</tt>.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ Value * data();
+
+ //! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
+ //! For a non-empty vector <tt>data() == &front()</tt>.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const Value * data() const;
+
+ //! @brief Returns iterator to the first element.
+ //!
+ //! @return iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator begin();
+
+ //! @brief Returns const iterator to the first element.
+ //!
+ //! @return const_iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator begin() const;
+
+ //! @brief Returns const iterator to the first element.
+ //!
+ //! @return const_iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator cbegin() const;
+
+ //! @brief Returns iterator to the one after the last element.
+ //!
+ //! @return iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator end();
+
+ //! @brief Returns const iterator to the one after the last element.
+ //!
+ //! @return const_iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator end() const;
+
+ //! @brief Returns const iterator to the one after the last element.
+ //!
+ //! @return const_iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator cend() const;
+
+ //! @brief Returns reverse iterator to the first element of the reversed container.
+ //!
+ //! @return reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reverse_iterator rbegin();
+
+ //! @brief Returns const reverse iterator to the first element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator rbegin() const;
+
+ //! @brief Returns const reverse iterator to the first element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator crbegin() const;
+
+ //! @brief Returns reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reverse_iterator rend();
+
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator rend() const;
+
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator crend() const;
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type capacity();
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type max_size();
+
+ //! @brief Returns the number of stored elements.
+ //!
+ //! @return Number of elements contained in the container.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ size_type size() const;
+
+ //! @brief Queries if the container contains elements.
+ //!
+ //! @return true if the number of elements contained in the
+ //! container is equal to 0.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ bool empty() const;
+
+#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
+
+};
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! @brief Checks if contents of two varrays are equal.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if containers have the same size and elements in both containers are equal.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator== (varray<V, C1> const& x, varray<V, C2> const& y);
+
+//! @brief Checks if contents of two varrays are not equal.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if containers have different size or elements in both containers are not equal.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator!= (varray<V, C1> const& x, varray<V, C2> const& y);
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if x compares lexicographically less than y.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator< (varray<V, C1> const& x, varray<V, C2> const& y);
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if y compares lexicographically less than x.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator> (varray<V, C1> const& x, varray<V, C2> const& y);
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if y don't compare lexicographically less than x.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator<= (varray<V, C1> const& x, varray<V, C2> const& y);
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if x don't compare lexicographically less than y.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator>= (varray<V, C1> const& x, varray<V, C2> const& y);
+
+//! @brief Swaps contents of two varrays.
+//!
+//! This function calls varray::swap().
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+inline void swap(varray<V, C1> & x, varray<V, C2> & y);
+
+#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}} // namespace boost::container
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_VARRAY_HPP
Modified: trunk/libs/container/doc/container.qbk
==============================================================================
--- trunk/libs/container/doc/container.qbk (original)
+++ trunk/libs/container/doc/container.qbk 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -663,7 +663,8 @@
* Support for `BOOST_NO_EXCEPTIONS` [@https://svn.boost.org/trac/boost/ticket/7227 #7227].
* Fixed bugs [@https://svn.boost.org/trac/boost/ticket/7921 #7921],
- [@https://svn.boost.org/trac/boost/ticket/7969 #7969].
+ [@https://svn.boost.org/trac/boost/ticket/7969 #7969],
+ [@https://svn.boost.org/trac/boost/ticket/8118 #8118].
[endsect]
Modified: trunk/libs/container/proj/vc7ide/container.sln
==============================================================================
--- trunk/libs/container/proj/vc7ide/container.sln (original)
+++ trunk/libs/container/proj/vc7ide/container.sln 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -59,6 +59,14 @@
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "static_vector_test", "static_vector_test.vcproj", "{58E1C1C3-096A-84FE-4FA2-D6BA79201C02}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_static_vector", "bench_static_vector.vcproj", "{58E1C1C3-096A-84FE-4FA2-D6BA79201C02}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
@@ -127,6 +135,14 @@
{5A8D91E0-FA57-284F-84FE-D3A6BA792002}.Debug.Build.0 = Debug|Win32
{5A8D91E0-FA57-284F-84FE-D3A6BA792002}.Release.ActiveCfg = Release|Win32
{5A8D91E0-FA57-284F-84FE-D3A6BA792002}.Release.Build.0 = Release|Win32
+ {58E1C1C3-096A-84FE-4FA2-D6BA79201C02}.Debug.ActiveCfg = Debug|Win32
+ {58E1C1C3-096A-84FE-4FA2-D6BA79201C02}.Debug.Build.0 = Debug|Win32
+ {58E1C1C3-096A-84F0-4FA2-D6BA79201C02}.Release.ActiveCfg = Release|Win32
+ {58E1C1C3-096A-84F0-4FA2-D6BA79201C02}.Release.Build.0 = Release|Win32
+ {58E1C1C3-096A-84F1-4FA2-D6BA79201C02}.Debug.ActiveCfg = Debug|Win32
+ {58E1C1C3-096A-84F1-4FA2-D6BA79201C02}.Debug.Build.0 = Debug|Win32
+ {58E1C1C3-096A-84F2-4FA2-D6BA79201C02}.Release.ActiveCfg = Release|Win32
+ {58E1C1C3-096A-84F2-4FA2-D6BA79201C02}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
Modified: trunk/libs/container/proj/vc7ide/container.vcproj
==============================================================================
--- trunk/libs/container/proj/vc7ide/container.vcproj (original)
+++ trunk/libs/container/proj/vc7ide/container.vcproj 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -173,6 +173,9 @@
RelativePath="..\..\test\set_test.hpp">
</File>
<File
+ RelativePath="..\..\test\static_vector_test.hpp">
+ </File>
+ <File
RelativePath="..\..\test\util.hpp">
</File>
<File
@@ -222,6 +225,9 @@
RelativePath="..\..\..\..\boost\container\stable_vector.hpp">
</File>
<File
+ RelativePath="..\..\..\..\boost\container\static_vector.hpp">
+ </File>
+ <File
RelativePath="..\..\..\..\boost\container\string.hpp">
</File>
<File
@@ -325,6 +331,26 @@
</File>
</Filter>
</Filter>
+ <Filter
+ Name="bench"
+ Filter="">
+ <File
+ RelativePath="..\..\bench\varray.hpp">
+ </File>
+ <Filter
+ Name="detail"
+ Filter="">
+ <File
+ RelativePath="..\..\bench\detail\varray.hpp">
+ </File>
+ <File
+ RelativePath="..\..\bench\detail\varray_concept.hpp">
+ </File>
+ <File
+ RelativePath="..\..\bench\detail\varray_util.hpp">
+ </File>
+ </Filter>
+ </Filter>
</Files>
<Globals>
</Globals>
Modified: trunk/libs/container/test/Jamfile.v2
==============================================================================
--- trunk/libs/container/test/Jamfile.v2 (original)
+++ trunk/libs/container/test/Jamfile.v2 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -21,7 +21,7 @@
for local fileb in [ glob *.cpp ]
{
- all_rules += [ run $(fileb)
+ all_rules += [ run $(fileb) /boost/timer//boost_timer /boost/system//boost_system /boost/thread//boost_thread
: # additional args
: # test-files
: # requirements
Deleted: trunk/libs/container/test/movable.hpp
==============================================================================
--- trunk/libs/container/test/movable.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
+++ (empty file)
@@ -1,92 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// See http://www.boost.org/libs/move for documentation.
-//
-//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_MOVE_TEST_MOVABLE_HPP
-#define BOOST_MOVE_TEST_MOVABLE_HPP
-
-//[movable_definition
-//header file "movable.hpp"
-#include <boost/move/move.hpp>
-
-//A movable class
-class movable
-{
- BOOST_MOVABLE_BUT_NOT_COPYABLE(movable)
- int value_;
-
-public:
- movable() : value_(1){}
-
- //Move constructor and assignment
- movable(BOOST_RV_REF(movable) m)
- { value_ = m.value_; m.value_ = 0; }
-
- movable & operator=(BOOST_RV_REF(movable) m)
- { value_ = m.value_; m.value_ = 0; return *this; }
-
- bool moved() const //Observer
- { return value_ == 0; }
-};
-
-
-class copy_movable
-{
- BOOST_COPYABLE_AND_MOVABLE(copy_movable)
- int value_;
-
-public:
- copy_movable(int value = 1) : value_(value){}
-
- //Move constructor and assignment
- copy_movable(BOOST_RV_REF(copy_movable) m)
- { value_ = m.value_; m.value_ = 0; }
-
- copy_movable(const copy_movable &m)
- { value_ = m.value_; }
-
- copy_movable & operator=(BOOST_RV_REF(copy_movable) m)
- { value_ = m.value_; m.value_ = 0; return *this; }
-
- copy_movable & operator=(BOOST_COPY_ASSIGN_REF(copy_movable) m)
- { value_ = m.value_; return *this; }
-
- bool moved() const //Observer
- { return value_ == 0; }
-
- bool operator==(const copy_movable& m) const
- { return value_ == m.value_; }
-};
-
-struct copy_movable_wrapper
-{
- copy_movable cm;
-};
-
-copy_movable produce()
-{ return copy_movable(); }
-
-namespace boost{
-
-template<>
-struct has_nothrow_move<movable>
-{
- static const bool value = true;
-};
-
-template<>
-struct has_nothrow_move<copy_movable>
-{
- static const bool value = true;
-};
-
-} //namespace boost{
-//]
-
-#endif //BOOST_MOVE_TEST_MOVABLE_HPP
Modified: trunk/libs/container/test/movable_int.hpp
==============================================================================
--- trunk/libs/container/test/movable_int.hpp (original)
+++ trunk/libs/container/test/movable_int.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -53,23 +53,26 @@
movable_int & operator= (int i)
{ this->m_int = i; return *this; }
- bool operator ==(const movable_int &mi) const
- { return this->m_int == mi.m_int; }
+ ~movable_int()
+ { this->m_int = 0; }
- bool operator !=(const movable_int &mi) const
- { return this->m_int != mi.m_int; }
+ friend bool operator ==(const movable_int &l, const movable_int &r)
+ { return l.m_int == r.m_int; }
- bool operator <(const movable_int &mi) const
- { return this->m_int < mi.m_int; }
+ friend bool operator !=(const movable_int &l, const movable_int &r)
+ { return l.m_int != r.m_int; }
- bool operator <=(const movable_int &mi) const
- { return this->m_int <= mi.m_int; }
+ friend bool operator <(const movable_int &l, const movable_int &r)
+ { return l.m_int < r.m_int; }
- bool operator >=(const movable_int &mi) const
- { return this->m_int >= mi.m_int; }
+ friend bool operator <=(const movable_int &l, const movable_int &r)
+ { return l.m_int <= r.m_int; }
- bool operator >(const movable_int &mi) const
- { return this->m_int > mi.m_int; }
+ friend bool operator >=(const movable_int &l, const movable_int &r)
+ { return l.m_int >= r.m_int; }
+
+ friend bool operator >(const movable_int &l, const movable_int &r)
+ { return l.m_int > r.m_int; }
int get_int() const
{ return m_int; }
@@ -84,6 +87,9 @@
int m_int;
};
+inline movable_int produce_movable_int()
+{ return movable_int(); }
+
template<class E, class T>
std::basic_ostream<E, T> & operator<<
(std::basic_ostream<E, T> & os, movable_int const & p)
@@ -93,7 +99,6 @@
return os;
}
-
template<>
struct is_copyable<movable_int>
{
@@ -121,6 +126,9 @@
: m_int(mmi.m_int)
{ mmi.m_int = 0; }
+ ~movable_and_copyable_int()
+ { this->m_int = 0; }
+
movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi)
{ this->m_int = mi.m_int; return *this; }
@@ -130,23 +138,23 @@
movable_and_copyable_int & operator= (int i)
{ this->m_int = i; return *this; }
- bool operator ==(const movable_and_copyable_int &mi) const
- { return this->m_int == mi.m_int; }
+ friend bool operator ==(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int == r.m_int; }
- bool operator !=(const movable_and_copyable_int &mi) const
- { return this->m_int != mi.m_int; }
+ friend bool operator !=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int != r.m_int; }
- bool operator <(const movable_and_copyable_int &mi) const
- { return this->m_int < mi.m_int; }
+ friend bool operator <(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int < r.m_int; }
- bool operator <=(const movable_and_copyable_int &mi) const
- { return this->m_int <= mi.m_int; }
+ friend bool operator <=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int <= r.m_int; }
- bool operator >=(const movable_and_copyable_int &mi) const
- { return this->m_int >= mi.m_int; }
+ friend bool operator >=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int >= r.m_int; }
- bool operator >(const movable_and_copyable_int &mi) const
- { return this->m_int > mi.m_int; }
+ friend bool operator >(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int > r.m_int; }
int get_int() const
{ return m_int; }
@@ -161,6 +169,9 @@
int m_int;
};
+inline movable_and_copyable_int produce_movable_and_copyable_int()
+{ return movable_and_copyable_int(); }
+
template<class E, class T>
std::basic_ostream<E, T> & operator<<
(std::basic_ostream<E, T> & os, movable_and_copyable_int const & p)
@@ -194,23 +205,29 @@
copyable_int & operator= (int i)
{ this->m_int = i; return *this; }
- bool operator ==(const copyable_int &mi) const
- { return this->m_int == mi.m_int; }
+ copyable_int & operator= (const copyable_int &ci)
+ { this->m_int = ci.m_int; return *this; }
- bool operator !=(const copyable_int &mi) const
- { return this->m_int != mi.m_int; }
+ ~copyable_int()
+ { this->m_int = 0; }
- bool operator <(const copyable_int &mi) const
- { return this->m_int < mi.m_int; }
+ friend bool operator ==(const copyable_int &l, const copyable_int &r)
+ { return l.m_int == r.m_int; }
- bool operator <=(const copyable_int &mi) const
- { return this->m_int <= mi.m_int; }
+ friend bool operator !=(const copyable_int &l, const copyable_int &r)
+ { return l.m_int != r.m_int; }
- bool operator >=(const copyable_int &mi) const
- { return this->m_int >= mi.m_int; }
+ friend bool operator <(const copyable_int &l, const copyable_int &r)
+ { return l.m_int < r.m_int; }
- bool operator >(const copyable_int &mi) const
- { return this->m_int > mi.m_int; }
+ friend bool operator <=(const copyable_int &l, const copyable_int &r)
+ { return l.m_int <= r.m_int; }
+
+ friend bool operator >=(const copyable_int &l, const copyable_int &r)
+ { return l.m_int >= r.m_int; }
+
+ friend bool operator >(const copyable_int &l, const copyable_int &r)
+ { return l.m_int > r.m_int; }
int get_int() const
{ return m_int; }
@@ -225,6 +242,9 @@
int m_int;
};
+inline copyable_int produce_copyable_int()
+{ return copyable_int(); }
+
template<class E, class T>
std::basic_ostream<E, T> & operator<<
(std::basic_ostream<E, T> & os, copyable_int const & p)
@@ -254,6 +274,9 @@
: m_int(a)
{}
+ ~non_copymovable_int()
+ { m_int = 0; }
+
bool operator ==(const non_copymovable_int &mi) const
{ return this->m_int == mi.m_int; }
Modified: trunk/libs/container/test/static_vector_test.cpp
==============================================================================
--- trunk/libs/container/test/static_vector_test.cpp (original)
+++ trunk/libs/container/test/static_vector_test.cpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -19,31 +19,35 @@
//so write our own macro
inline void throw_failed_impl(char const * excep, char const * file, int line, char const * function)
{
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): Exception '" << excep << "' not thrown in function '"
- << function << "'" << std::endl;
- ++boost::detail::test_errors();
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): Exception '" << excep << "' not thrown in function '"
+ << function << "'" << std::endl;
+ ++boost::detail::test_errors();
}
} //namespace detail {
} //namespace container {
} //namespace boost {
-#define BOOST_TEST_THROW( S, E ) \
- try { \
- S; \
- ::boost::container::test::throw_failed_impl \
- (#E, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
- } \
- catch( E const&) { \
- } \
+#define BOOST_TEST_THROW( S, E ) \
+ try { \
+ S; \
+ ::boost::container::test::throw_failed_impl \
+ (#E, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
+ } \
+ catch(E const&) { \
+ } \
+ catch(...) { \
+ ::boost::container::test::throw_failed_impl \
+ (#E, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
+ } \
//
// TODO: Disable parts of the unit test that should not run when BOOST_NO_EXCEPTIONS
// if exceptions are enabled there must be a user defined throw_exception function
#ifdef BOOST_NO_EXCEPTIONS
namespace boost {
- void throw_exception(std::exception const & e){}; // user defined
+ void throw_exception(std::exception const & e){}; // user defined
} // namespace boost
#endif // BOOST_NO_EXCEPTIONS
@@ -69,735 +73,734 @@
template <typename T, size_t N>
void test_ctor_ndc()
{
- static_vector<T, N> s;
- BOOST_TEST_EQ(s.size() , 0u);
- BOOST_TEST(s.capacity() == N);
+ static_vector<T, N> s;
+ BOOST_TEST_EQ(s.size() , 0u);
+ BOOST_TEST(s.capacity() == N);
#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW( s.at(0u), std::out_of_range );
+ BOOST_TEST_THROW( s.at(0u), std::out_of_range );
#endif // BOOST_NO_EXCEPTIONS
}
template <typename T, size_t N>
void test_ctor_nc(size_t n)
{
- static_vector<T, N> s(n);
- BOOST_TEST(s.size() == n);
- BOOST_TEST(s.capacity() == N);
-#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW( s.at(n), std::out_of_range );
-#endif // BOOST_NO_EXCEPTIONS
- if ( 1 < n )
- {
- T val10(10);
- s[0] = val10;
- BOOST_TEST(T(10) == s[0]);
- BOOST_TEST(T(10) == s.at(0));
- T val20(20);
- s.at(1) = val20;
- BOOST_TEST(T(20) == s[1]);
- BOOST_TEST(T(20) == s.at(1));
- }
+ static_vector<T, N> s(n);
+ BOOST_TEST(s.size() == n);
+ BOOST_TEST(s.capacity() == N);
+#ifndef BOOST_NO_EXCEPTIONS
+ BOOST_TEST_THROW( s.at(n), std::out_of_range );
+#endif // BOOST_NO_EXCEPTIONS
+ if ( 1 < n )
+ {
+ T val10(10);
+ s[0] = val10;
+ BOOST_TEST(T(10) == s[0]);
+ BOOST_TEST(T(10) == s.at(0));
+ T val20(20);
+ s.at(1) = val20;
+ BOOST_TEST(T(20) == s[1]);
+ BOOST_TEST(T(20) == s.at(1));
+ }
}
template <typename T, size_t N>
void test_ctor_nd(size_t n, T const& v)
{
- static_vector<T, N> s(n, v);
- BOOST_TEST(s.size() == n);
- BOOST_TEST(s.capacity() == N);
-#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW( s.at(n), std::out_of_range );
-#endif // BOOST_NO_EXCEPTIONS
- if ( 1 < n )
- {
- BOOST_TEST(v == s[0]);
- BOOST_TEST(v == s.at(0));
- BOOST_TEST(v == s[1]);
- BOOST_TEST(v == s.at(1));
- s[0] = T(10);
- BOOST_TEST(T(10) == s[0]);
- BOOST_TEST(T(10) == s.at(0));
- s.at(1) = T(20);
- BOOST_TEST(T(20) == s[1]);
- BOOST_TEST(T(20) == s.at(1));
- }
+ static_vector<T, N> s(n, v);
+ BOOST_TEST(s.size() == n);
+ BOOST_TEST(s.capacity() == N);
+#ifndef BOOST_NO_EXCEPTIONS
+ BOOST_TEST_THROW( s.at(n), std::out_of_range );
+#endif // BOOST_NO_EXCEPTIONS
+ if ( 1 < n )
+ {
+ BOOST_TEST(v == s[0]);
+ BOOST_TEST(v == s.at(0));
+ BOOST_TEST(v == s[1]);
+ BOOST_TEST(v == s.at(1));
+ s[0] = T(10);
+ BOOST_TEST(T(10) == s[0]);
+ BOOST_TEST(T(10) == s.at(0));
+ s.at(1) = T(20);
+ BOOST_TEST(T(20) == s[1]);
+ BOOST_TEST(T(20) == s.at(1));
+ }
}
template <typename T, size_t N>
void test_resize_nc(size_t n)
{
- static_vector<T, N> s;
+ static_vector<T, N> s;
- s.resize(n);
- BOOST_TEST(s.size() == n);
- BOOST_TEST(s.capacity() == N);
-#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW( s.at(n), std::out_of_range );
-#endif // BOOST_NO_EXCEPTIONS
- if ( 1 < n )
- {
- T val10(10);
- s[0] = val10;
- BOOST_TEST(T(10) == s[0]);
- BOOST_TEST(T(10) == s.at(0));
- T val20(20);
- s.at(1) = val20;
- BOOST_TEST(T(20) == s[1]);
- BOOST_TEST(T(20) == s.at(1));
- }
+ s.resize(n);
+ BOOST_TEST(s.size() == n);
+ BOOST_TEST(s.capacity() == N);
+#ifndef BOOST_NO_EXCEPTIONS
+ BOOST_TEST_THROW( s.at(n), std::out_of_range );
+#endif // BOOST_NO_EXCEPTIONS
+ if ( 1 < n )
+ {
+ T val10(10);
+ s[0] = val10;
+ BOOST_TEST(T(10) == s[0]);
+ BOOST_TEST(T(10) == s.at(0));
+ T val20(20);
+ s.at(1) = val20;
+ BOOST_TEST(T(20) == s[1]);
+ BOOST_TEST(T(20) == s.at(1));
+ }
}
template <typename T, size_t N>
void test_resize_nd(size_t n, T const& v)
{
- static_vector<T, N> s;
+ static_vector<T, N> s;
- s.resize(n, v);
- BOOST_TEST(s.size() == n);
- BOOST_TEST(s.capacity() == N);
-#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW( s.at(n), std::out_of_range );
-#endif // BOOST_NO_EXCEPTIONS
- if ( 1 < n )
- {
- BOOST_TEST(v == s[0]);
- BOOST_TEST(v == s.at(0));
- BOOST_TEST(v == s[1]);
- BOOST_TEST(v == s.at(1));
- s[0] = T(10);
- BOOST_TEST(T(10) == s[0]);
- BOOST_TEST(T(10) == s.at(0));
- s.at(1) = T(20);
- BOOST_TEST(T(20) == s[1]);
- BOOST_TEST(T(20) == s.at(1));
- }
+ s.resize(n, v);
+ BOOST_TEST(s.size() == n);
+ BOOST_TEST(s.capacity() == N);
+#ifndef BOOST_NO_EXCEPTIONS
+ BOOST_TEST_THROW( s.at(n), std::out_of_range );
+#endif // BOOST_NO_EXCEPTIONS
+ if ( 1 < n )
+ {
+ BOOST_TEST(v == s[0]);
+ BOOST_TEST(v == s.at(0));
+ BOOST_TEST(v == s[1]);
+ BOOST_TEST(v == s.at(1));
+ s[0] = T(10);
+ BOOST_TEST(T(10) == s[0]);
+ BOOST_TEST(T(10) == s.at(0));
+ s.at(1) = T(20);
+ BOOST_TEST(T(20) == s[1]);
+ BOOST_TEST(T(20) == s.at(1));
+ }
}
template <typename T, size_t N>
void test_push_back_nd()
{
- static_vector<T, N> s;
+ static_vector<T, N> s;
- BOOST_TEST(s.size() == 0);
+ BOOST_TEST(s.size() == 0);
#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW( s.at(0), std::out_of_range );
+ BOOST_TEST_THROW( s.at(0), std::out_of_range );
#endif // BOOST_NO_EXCEPTIONS
- for ( size_t i = 0 ; i < N ; ++i )
- {
- T t(i);
- s.push_back(t);
- BOOST_TEST(s.size() == i + 1);
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ T t(i);
+ s.push_back(t);
+ BOOST_TEST(s.size() == i + 1);
#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW( s.at(i + 1), std::out_of_range );
+ BOOST_TEST_THROW( s.at(i + 1), std::out_of_range );
#endif // BOOST_NO_EXCEPTIONS
- BOOST_TEST(T(i) == s.at(i));
- BOOST_TEST(T(i) == s[i]);
- BOOST_TEST(T(i) == s.back());
- BOOST_TEST(T(0) == s.front());
- BOOST_TEST(T(i) == *(s.data() + i));
- }
+ BOOST_TEST(T(i) == s.at(i));
+ BOOST_TEST(T(i) == s[i]);
+ BOOST_TEST(T(i) == s.back());
+ BOOST_TEST(T(0) == s.front());
+ BOOST_TEST(T(i) == *(s.data() + i));
+ }
}
template <typename T, size_t N>
void test_pop_back_nd()
{
- static_vector<T, N> s;
+ static_vector<T, N> s;
- for ( size_t i = 0 ; i < N ; ++i )
- {
- T t(i);
- s.push_back(t);
- }
-
- for ( size_t i = N ; i > 1 ; --i )
- {
- s.pop_back();
- BOOST_TEST(s.size() == i - 1);
-#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW( s.at(i - 1), std::out_of_range );
-#endif // BOOST_NO_EXCEPTIONS
- BOOST_TEST(T(i - 2) == s.at(i - 2));
- BOOST_TEST(T(i - 2) == s[i - 2]);
- BOOST_TEST(T(i - 2) == s.back());
- BOOST_TEST(T(0) == s.front());
- }
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ T t(i);
+ s.push_back(t);
+ }
+
+ for ( size_t i = N ; i > 1 ; --i )
+ {
+ s.pop_back();
+ BOOST_TEST(s.size() == i - 1);
+#ifndef BOOST_NO_EXCEPTIONS
+ BOOST_TEST_THROW( s.at(i - 1), std::out_of_range );
+#endif // BOOST_NO_EXCEPTIONS
+ BOOST_TEST(T(i - 2) == s.at(i - 2));
+ BOOST_TEST(T(i - 2) == s[i - 2]);
+ BOOST_TEST(T(i - 2) == s.back());
+ BOOST_TEST(T(0) == s.front());
+ }
}
template <typename It1, typename It2>
void test_compare_ranges(It1 first1, It1 last1, It2 first2, It2 last2)
{
- BOOST_TEST(std::distance(first1, last1) == std::distance(first2, last2));
- for ( ; first1 != last1 && first2 != last2 ; ++first1, ++first2 )
- BOOST_TEST(*first1 == *first2);
+ BOOST_TEST(std::distance(first1, last1) == std::distance(first2, last2));
+ for ( ; first1 != last1 && first2 != last2 ; ++first1, ++first2 )
+ BOOST_TEST(*first1 == *first2);
}
template <typename T, size_t N, typename C>
void test_copy_and_assign(C const& c)
{
- {
- static_vector<T, N> s(c.begin(), c.end());
- BOOST_TEST(s.size() == c.size());
- test_compare_ranges(s.begin(), s.end(), c.begin(), c.end());
- }
- {
- static_vector<T, N> s;
- BOOST_TEST(0 == s.size());
- s.assign(c.begin(), c.end());
- BOOST_TEST(s.size() == c.size());
- test_compare_ranges(s.begin(), s.end(), c.begin(), c.end());
- }
+ {
+ static_vector<T, N> s(c.begin(), c.end());
+ BOOST_TEST(s.size() == c.size());
+ test_compare_ranges(s.begin(), s.end(), c.begin(), c.end());
+ }
+ {
+ static_vector<T, N> s;
+ BOOST_TEST(0 == s.size());
+ s.assign(c.begin(), c.end());
+ BOOST_TEST(s.size() == c.size());
+ test_compare_ranges(s.begin(), s.end(), c.begin(), c.end());
+ }
}
template <typename T, size_t N>
void test_copy_and_assign_nd(T const& val)
{
- static_vector<T, N> s;
- std::vector<T> v;
- std::list<T> l;
-
- for ( size_t i = 0 ; i < N ; ++i )
- {
- T t(i);
- s.push_back(t);
- v.push_back(t);
- l.push_back(t);
- }
- // copy ctor
- {
- static_vector<T, N> s1(s);
- BOOST_TEST(s.size() == s1.size());
- test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
- }
- // copy assignment
- {
- static_vector<T, N> s1;
- BOOST_TEST(0 == s1.size());
- s1 = s;
- BOOST_TEST(s.size() == s1.size());
- test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
- }
-
- // ctor(Iter, Iter) and assign(Iter, Iter)
- test_copy_and_assign<T, N>(s);
- test_copy_and_assign<T, N>(v);
- test_copy_and_assign<T, N>(l);
-
- // assign(N, V)
- {
- static_vector<T, N> s1(s);
- test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
- std::vector<T> a(N, val);
- s1.assign(N, val);
- test_compare_ranges(a.begin(), a.end(), s1.begin(), s1.end());
- }
+ static_vector<T, N> s;
+ std::vector<T> v;
+ std::list<T> l;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ T t(i);
+ s.push_back(t);
+ v.push_back(t);
+ l.push_back(t);
+ }
+ // copy ctor
+ {
+ static_vector<T, N> s1(s);
+ BOOST_TEST(s.size() == s1.size());
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ }
+ // copy assignment
+ {
+ static_vector<T, N> s1;
+ BOOST_TEST(0 == s1.size());
+ s1 = s;
+ BOOST_TEST(s.size() == s1.size());
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ }
+
+ // ctor(Iter, Iter) and assign(Iter, Iter)
+ test_copy_and_assign<T, N>(s);
+ test_copy_and_assign<T, N>(v);
+ test_copy_and_assign<T, N>(l);
+
+ // assign(N, V)
+ {
+ static_vector<T, N> s1(s);
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ std::vector<T> a(N, val);
+ s1.assign(N, val);
+ test_compare_ranges(a.begin(), a.end(), s1.begin(), s1.end());
+ }
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
- stable_vector<T> bsv(s.begin(), s.end());
- vector<T> bv(s.begin(), s.end());
- test_copy_and_assign<T, N>(bsv);
- test_copy_and_assign<T, N>(bv);
+ stable_vector<T> bsv(s.begin(), s.end());
+ vector<T> bv(s.begin(), s.end());
+ test_copy_and_assign<T, N>(bsv);
+ test_copy_and_assign<T, N>(bv);
#endif
}
template <typename T, size_t N>
void test_iterators_nd()
{
- static_vector<T, N> s;
- std::vector<T> v;
+ static_vector<T, N> s;
+ std::vector<T> v;
- for ( size_t i = 0 ; i < N ; ++i )
- {
- s.push_back(T(i));
- v.push_back(T(i));
- }
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ s.push_back(T(i));
+ v.push_back(T(i));
+ }
- test_compare_ranges(s.begin(), s.end(), v.begin(), v.end());
- test_compare_ranges(s.rbegin(), s.rend(), v.rbegin(), v.rend());
+ test_compare_ranges(s.begin(), s.end(), v.begin(), v.end());
+ test_compare_ranges(s.rbegin(), s.rend(), v.rbegin(), v.rend());
- s.assign(v.rbegin(), v.rend());
+ s.assign(v.rbegin(), v.rend());
- test_compare_ranges(s.begin(), s.end(), v.rbegin(), v.rend());
- test_compare_ranges(s.rbegin(), s.rend(), v.begin(), v.end());
+ test_compare_ranges(s.begin(), s.end(), v.rbegin(), v.rend());
+ test_compare_ranges(s.rbegin(), s.rend(), v.begin(), v.end());
}
template <typename T, size_t N>
void test_erase_nd()
{
- static_vector<T, N> s;
- typedef typename static_vector<T, N>::iterator It;
+ static_vector<T, N> s;
+ typedef typename static_vector<T, N>::iterator It;
- for ( size_t i = 0 ; i < N ; ++i )
- s.push_back(T(i));
+ for ( size_t i = 0 ; i < N ; ++i )
+ s.push_back(T(i));
- // erase(pos)
- {
- for ( size_t i = 0 ; i < N ; ++i )
- {
- static_vector<T, N> s1(s);
- It it = s1.erase(s1.begin() + i);
- BOOST_TEST(s1.begin() + i == it);
- BOOST_TEST(s1.size() == N - 1);
- for ( size_t j = 0 ; j < i ; ++j )
- BOOST_TEST(s1[j] == T(j));
- for ( size_t j = i+1 ; j < N ; ++j )
- BOOST_TEST(s1[j-1] == T(j));
- }
- }
- // erase(first, last)
- {
- size_t n = N/3;
- for ( size_t i = 0 ; i <= N ; ++i )
- {
- static_vector<T, N> s1(s);
- size_t removed = i + n < N ? n : N - i;
- It it = s1.erase(s1.begin() + i, s1.begin() + i + removed);
- BOOST_TEST(s1.begin() + i == it);
- BOOST_TEST(s1.size() == N - removed);
- for ( size_t j = 0 ; j < i ; ++j )
- BOOST_TEST(s1[j] == T(j));
- for ( size_t j = i+n ; j < N ; ++j )
- BOOST_TEST(s1[j-n] == T(j));
- }
- }
+ // erase(pos)
+ {
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ It it = s1.erase(s1.begin() + i);
+ BOOST_TEST(s1.begin() + i == it);
+ BOOST_TEST(s1.size() == N - 1);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ for ( size_t j = i+1 ; j < N ; ++j )
+ BOOST_TEST(s1[j-1] == T(j));
+ }
+ }
+ // erase(first, last)
+ {
+ size_t n = N/3;
+ for ( size_t i = 0 ; i <= N ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ size_t removed = i + n < N ? n : N - i;
+ It it = s1.erase(s1.begin() + i, s1.begin() + i + removed);
+ BOOST_TEST(s1.begin() + i == it);
+ BOOST_TEST(s1.size() == N - removed);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ for ( size_t j = i+n ; j < N ; ++j )
+ BOOST_TEST(s1[j-n] == T(j));
+ }
+ }
}
template <typename T, size_t N, typename SV, typename C>
void test_insert(SV const& s, C const& c)
{
- size_t h = N/2;
- size_t n = size_t(h/1.5f);
+ size_t h = N/2;
+ size_t n = size_t(h/1.5f);
- for ( size_t i = 0 ; i <= h ; ++i )
- {
- static_vector<T, N> s1(s);
-
- typename C::const_iterator it = c.begin();
- std::advance(it, n);
- typename static_vector<T, N>::iterator
- it1 = s1.insert(s1.begin() + i, c.begin(), it);
-
- BOOST_TEST(s1.begin() + i == it1);
- BOOST_TEST(s1.size() == h+n);
- for ( size_t j = 0 ; j < i ; ++j )
- BOOST_TEST(s1[j] == T(j));
- for ( size_t j = 0 ; j < n ; ++j )
- BOOST_TEST(s1[j+i] == T(100 + j));
- for ( size_t j = 0 ; j < h-i ; ++j )
- BOOST_TEST(s1[j+i+n] == T(j+i));
- }
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+
+ typename C::const_iterator it = c.begin();
+ std::advance(it, n);
+ typename static_vector<T, N>::iterator
+ it1 = s1.insert(s1.begin() + i, c.begin(), it);
+
+ BOOST_TEST(s1.begin() + i == it1);
+ BOOST_TEST(s1.size() == h+n);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ for ( size_t j = 0 ; j < n ; ++j )
+ BOOST_TEST(s1[j+i] == T(100 + j));
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_TEST(s1[j+i+n] == T(j+i));
+ }
}
template <typename T, size_t N>
void test_insert_nd(T const& val)
{
- size_t h = N/2;
+ size_t h = N/2;
- static_vector<T, N> s, ss;
- std::vector<T> v;
- std::list<T> l;
-
- typedef typename static_vector<T, N>::iterator It;
-
- for ( size_t i = 0 ; i < h ; ++i )
- {
- s.push_back(T(i));
- ss.push_back(T(100 + i));
- v.push_back(T(100 + i));
- l.push_back(T(100 + i));
- }
-
- // insert(pos, val)
- {
- for ( size_t i = 0 ; i <= h ; ++i )
- {
- static_vector<T, N> s1(s);
- It it = s1.insert(s1.begin() + i, val);
- BOOST_TEST(s1.begin() + i == it);
- BOOST_TEST(s1.size() == h+1);
- for ( size_t j = 0 ; j < i ; ++j )
- BOOST_TEST(s1[j] == T(j));
- BOOST_TEST(s1[i] == val);
- for ( size_t j = 0 ; j < h-i ; ++j )
- BOOST_TEST(s1[j+i+1] == T(j+i));
- }
- }
- // insert(pos, n, val)
- {
- size_t n = size_t(h/1.5f);
- for ( size_t i = 0 ; i <= h ; ++i )
- {
- static_vector<T, N> s1(s);
- It it = s1.insert(s1.begin() + i, n, val);
- BOOST_TEST(s1.begin() + i == it);
- BOOST_TEST(s1.size() == h+n);
- for ( size_t j = 0 ; j < i ; ++j )
- BOOST_TEST(s1[j] == T(j));
- for ( size_t j = 0 ; j < n ; ++j )
- BOOST_TEST(s1[j+i] == val);
- for ( size_t j = 0 ; j < h-i ; ++j )
- BOOST_TEST(s1[j+i+n] == T(j+i));
- }
- }
- // insert(pos, first, last)
- test_insert<T, N>(s, ss);
- test_insert<T, N>(s, v);
- test_insert<T, N>(s, l);
+ static_vector<T, N> s, ss;
+ std::vector<T> v;
+ std::list<T> l;
+
+ typedef typename static_vector<T, N>::iterator It;
+
+ for ( size_t i = 0 ; i < h ; ++i )
+ {
+ s.push_back(T(i));
+ ss.push_back(T(100 + i));
+ v.push_back(T(100 + i));
+ l.push_back(T(100 + i));
+ }
+
+ // insert(pos, val)
+ {
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ It it = s1.insert(s1.begin() + i, val);
+ BOOST_TEST(s1.begin() + i == it);
+ BOOST_TEST(s1.size() == h+1);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ BOOST_TEST(s1[i] == val);
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_TEST(s1[j+i+1] == T(j+i));
+ }
+ }
+ // insert(pos, n, val)
+ {
+ size_t n = size_t(h/1.5f);
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ It it = s1.insert(s1.begin() + i, n, val);
+ BOOST_TEST(s1.begin() + i == it);
+ BOOST_TEST(s1.size() == h+n);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ for ( size_t j = 0 ; j < n ; ++j )
+ BOOST_TEST(s1[j+i] == val);
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_TEST(s1[j+i+n] == T(j+i));
+ }
+ }
+ // insert(pos, first, last)
+ test_insert<T, N>(s, ss);
+ test_insert<T, N>(s, v);
+ test_insert<T, N>(s, l);
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
- stable_vector<T> bsv(ss.begin(), ss.end());
- vector<T> bv(ss.begin(), ss.end());
- test_insert<T, N>(s, bv);
- test_insert<T, N>(s, bsv);
+ stable_vector<T> bsv(ss.begin(), ss.end());
+ vector<T> bv(ss.begin(), ss.end());
+ test_insert<T, N>(s, bv);
+ test_insert<T, N>(s, bsv);
#endif
}
template <typename T>
void test_capacity_0_nd()
{
- static_vector<T, 10> v(5u, T(0));
+ static_vector<T, 10> v(5u, T(0));
- static_vector<T, 0 > s;
- BOOST_TEST(s.size() == 0);
- BOOST_TEST(s.capacity() == 0);
-#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW(s.at(0), std::out_of_range);
- BOOST_TEST_THROW(s.resize(5u, T(0)), std::bad_alloc);
- BOOST_TEST_THROW(s.push_back(T(0)), std::bad_alloc);
- BOOST_TEST_THROW(s.insert(s.end(), T(0)), std::bad_alloc);
- BOOST_TEST_THROW(s.insert(s.end(), 5u, T(0)), std::bad_alloc);
- BOOST_TEST_THROW(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
- BOOST_TEST_THROW(s.assign(v.begin(), v.end()), std::bad_alloc);
- BOOST_TEST_THROW(s.assign(5u, T(0)), std::bad_alloc);
- try{
- static_vector<T, 0> s2(v.begin(), v.end());
- BOOST_TEST(false);
- }catch(std::bad_alloc &){}
- try{
- static_vector<T, 0> s1(5u, T(0));
- BOOST_TEST(false);
- }catch(std::bad_alloc &){}
+ static_vector<T, 0 > s;
+ BOOST_TEST(s.size() == 0);
+ BOOST_TEST(s.capacity() == 0);
+#ifndef BOOST_NO_EXCEPTIONS
+ BOOST_TEST_THROW(s.at(0), std::out_of_range);
+ BOOST_TEST_THROW(s.resize(5u, T(0)), std::bad_alloc);
+ BOOST_TEST_THROW(s.push_back(T(0)), std::bad_alloc);
+ BOOST_TEST_THROW(s.insert(s.end(), T(0)), std::bad_alloc);
+ BOOST_TEST_THROW(s.insert(s.end(), 5u, T(0)), std::bad_alloc);
+ BOOST_TEST_THROW(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROW(s.assign(v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROW(s.assign(5u, T(0)), std::bad_alloc);
+ try{
+ static_vector<T, 0> s2(v.begin(), v.end());
+ BOOST_TEST(false);
+ }catch(std::bad_alloc &){}
+ try{
+ static_vector<T, 0> s1(5u, T(0));
+ BOOST_TEST(false);
+ }catch(std::bad_alloc &){}
#endif // BOOST_NO_EXCEPTIONS
}
template <typename T, size_t N>
void test_exceptions_nd()
{
- static_vector<T, N> v(N, T(0));
- static_vector<T, N/2> s(N/2, T(0));
+ static_vector<T, N> v(N, T(0));
+ static_vector<T, N/2> s(N/2, T(0));
#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW(s.resize(N, T(0)), std::bad_alloc);
- BOOST_TEST_THROW(s.push_back(T(0)), std::bad_alloc);
- BOOST_TEST_THROW(s.insert(s.end(), T(0)), std::bad_alloc);
- BOOST_TEST_THROW(s.insert(s.end(), N, T(0)), std::bad_alloc);
- BOOST_TEST_THROW(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
- BOOST_TEST_THROW(s.assign(v.begin(), v.end()), std::bad_alloc);
- BOOST_TEST_THROW(s.assign(N, T(0)), std::bad_alloc);
- try{
- static_vector<T, N/2> s2(v.begin(), v.end());
- BOOST_TEST(false);
- }catch(std::bad_alloc &){}
- try{
- static_vector<T, N/2> s1(N, T(0));
- BOOST_TEST(false);
- }catch(std::bad_alloc &){}
+ BOOST_TEST_THROW(s.resize(N, T(0)), std::bad_alloc);
+ BOOST_TEST_THROW(s.push_back(T(0)), std::bad_alloc);
+ BOOST_TEST_THROW(s.insert(s.end(), T(0)), std::bad_alloc);
+ BOOST_TEST_THROW(s.insert(s.end(), N, T(0)), std::bad_alloc);
+ BOOST_TEST_THROW(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROW(s.assign(v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROW(s.assign(N, T(0)), std::bad_alloc);
+ try{
+ static_vector<T, N/2> s2(v.begin(), v.end());
+ BOOST_TEST(false);
+ }catch(std::bad_alloc &){}
+ try{
+ static_vector<T, N/2> s1(N, T(0));
+ BOOST_TEST(false);
+ }catch(std::bad_alloc &){}
#endif // BOOST_NO_EXCEPTIONS
}
template <typename T, size_t N>
void test_swap_and_move_nd()
{
- {
- static_vector<T, N> v1, v2, v3, v4;
- static_vector<T, N> s1, s2;
- static_vector<T, N> s4;
-
- for (size_t i = 0 ; i < N ; ++i )
- {
- v1.push_back(T(i));
- v2.push_back(T(i));
- v3.push_back(T(i));
- v4.push_back(T(i));
- }
- for (size_t i = 0 ; i < N/2 ; ++i )
- {
- s1.push_back(T(100 + i));
- s2.push_back(T(100 + i));
- s4.push_back(T(100 + i));
- }
-
- s1.swap(v1);
- s2 = boost::move(v2);
- static_vector<T, N> s3(boost::move(v3));
- s4.swap(v4);
-
- BOOST_TEST(v1.size() == N/2);
- BOOST_TEST(s1.size() == N);
- //iG moving does not imply emptying source
- //BOOST_TEST(v2.size() == 0);
- BOOST_TEST(s2.size() == N);
- //iG moving does not imply emptying source
- //BOOST_TEST(v3.size() == 0);
- BOOST_TEST(s3.size() == N);
- BOOST_TEST(v4.size() == N/2);
- BOOST_TEST(s4.size() == N);
- for (size_t i = 0 ; i < N/2 ; ++i )
- {
- BOOST_TEST(v1[i] == T(100 + i));
- BOOST_TEST(v4[i] == T(100 + i));
- }
- for (size_t i = 0 ; i < N ; ++i )
- {
- BOOST_TEST(s1[i] == T(i));
- BOOST_TEST(s2[i] == T(i));
- BOOST_TEST(s3[i] == T(i));
- BOOST_TEST(s4[i] == T(i));
- }
- }
- {
- static_vector<T, N> v1, v2, v3;
- static_vector<T, N/2> s1, s2;
-
- for (size_t i = 0 ; i < N/2 ; ++i )
- {
- v1.push_back(T(i));
- v2.push_back(T(i));
- v3.push_back(T(i));
- }
- for (size_t i = 0 ; i < N/3 ; ++i )
- {
- s1.push_back(T(100 + i));
- s2.push_back(T(100 + i));
- }
-
- s1.swap(v1);
- s2 = boost::move(v2);
- static_vector<T, N/2> s3(boost::move(v3));
-
- BOOST_TEST(v1.size() == N/3);
- BOOST_TEST(s1.size() == N/2);
- //iG moving does not imply emptying source
- //BOOST_TEST(v2.size() == 0);
- BOOST_TEST(s2.size() == N/2);
- //iG moving does not imply emptying source
- //BOOST_TEST(v3.size() == 0);
- BOOST_TEST(s3.size() == N/2);
- for (size_t i = 0 ; i < N/3 ; ++i )
- BOOST_TEST(v1[i] == T(100 + i));
- for (size_t i = 0 ; i < N/2 ; ++i )
- {
- BOOST_TEST(s1[i] == T(i));
- BOOST_TEST(s2[i] == T(i));
- BOOST_TEST(s3[i] == T(i));
- }
- }
- {
- static_vector<T, N> v(N, T(0));
- static_vector<T, N/2> s(N/2, T(1));
-#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW(s.swap(v), std::bad_alloc);
- v.resize(N, T(0));
- BOOST_TEST_THROW(s = boost::move(v), std::bad_alloc);
- v.resize(N, T(0));
- try {
- static_vector<T, N/2> s2(boost::move(v));
- BOOST_TEST(false);
- } catch (std::bad_alloc &) {}
+ {
+ static_vector<T, N> v1, v2, v3, v4;
+ static_vector<T, N> s1, s2;
+ static_vector<T, N> s4;
+
+ for (size_t i = 0 ; i < N ; ++i )
+ {
+ v1.push_back(T(i));
+ v2.push_back(T(i));
+ v3.push_back(T(i));
+ v4.push_back(T(i));
+ }
+ for (size_t i = 0 ; i < N/2 ; ++i )
+ {
+ s1.push_back(T(100 + i));
+ s2.push_back(T(100 + i));
+ s4.push_back(T(100 + i));
+ }
+
+ s1.swap(v1);
+ s2 = boost::move(v2);
+ static_vector<T, N> s3(boost::move(v3));
+ s4.swap(v4);
+
+ BOOST_TEST(v1.size() == N/2);
+ BOOST_TEST(s1.size() == N);
+ //iG moving does not imply emptying source
+ //BOOST_TEST(v2.size() == 0);
+ BOOST_TEST(s2.size() == N);
+ //iG moving does not imply emptying source
+ //BOOST_TEST(v3.size() == 0);
+ BOOST_TEST(s3.size() == N);
+ BOOST_TEST(v4.size() == N/2);
+ BOOST_TEST(s4.size() == N);
+ for (size_t i = 0 ; i < N/2 ; ++i )
+ {
+ BOOST_TEST(v1[i] == T(100 + i));
+ BOOST_TEST(v4[i] == T(100 + i));
+ }
+ for (size_t i = 0 ; i < N ; ++i )
+ {
+ BOOST_TEST(s1[i] == T(i));
+ BOOST_TEST(s2[i] == T(i));
+ BOOST_TEST(s3[i] == T(i));
+ BOOST_TEST(s4[i] == T(i));
+ }
+ }
+ {
+ static_vector<T, N> v1, v2, v3;
+ static_vector<T, N/2> s1, s2;
+
+ for (size_t i = 0 ; i < N/2 ; ++i )
+ {
+ v1.push_back(T(i));
+ v2.push_back(T(i));
+ v3.push_back(T(i));
+ }
+ for (size_t i = 0 ; i < N/3 ; ++i )
+ {
+ s1.push_back(T(100 + i));
+ s2.push_back(T(100 + i));
+ }
+
+ s1.swap(v1);
+ s2 = boost::move(v2);
+ static_vector<T, N/2> s3(boost::move(v3));
+
+ BOOST_TEST(v1.size() == N/3);
+ BOOST_TEST(s1.size() == N/2);
+ //iG moving does not imply emptying source
+ //BOOST_TEST(v2.size() == 0);
+ BOOST_TEST(s2.size() == N/2);
+ //iG moving does not imply emptying source
+ //BOOST_TEST(v3.size() == 0);
+ BOOST_TEST(s3.size() == N/2);
+ for (size_t i = 0 ; i < N/3 ; ++i )
+ BOOST_TEST(v1[i] == T(100 + i));
+ for (size_t i = 0 ; i < N/2 ; ++i )
+ {
+ BOOST_TEST(s1[i] == T(i));
+ BOOST_TEST(s2[i] == T(i));
+ BOOST_TEST(s3[i] == T(i));
+ }
+ }
+ {
+ typedef static_vector<T, N/2> small_vector_t;
+ static_vector<T, N> v(N, T(0));
+ small_vector_t s(N/2, T(1));
+#ifndef BOOST_NO_EXCEPTIONS
+ BOOST_TEST_THROW(s.swap(v), std::bad_alloc);
+ v.resize(N, T(0));
+ BOOST_TEST_THROW(s = boost::move(v), std::bad_alloc);
+ v.resize(N, T(0));
+ BOOST_TEST_THROW(small_vector_t s2(boost::move(v)), std::bad_alloc);
#endif // BOOST_NO_EXCEPTIONS
- }
+ }
}
template <typename T, size_t N>
void test_emplace_0p()
{
- //emplace_back()
- {
- static_vector<T, N> v;
-
- for (int i = 0 ; i < int(N) ; ++i )
- v.emplace_back();
- BOOST_TEST(v.size() == N);
+ //emplace_back()
+ {
+ static_vector<T, N> v;
+
+ for (int i = 0 ; i < int(N) ; ++i )
+ v.emplace_back();
+ BOOST_TEST(v.size() == N);
#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW(v.emplace_back(), std::bad_alloc);
+ BOOST_TEST_THROW(v.emplace_back(), std::bad_alloc);
#endif
- }
+ }
}
template <typename T, size_t N>
void test_emplace_2p()
{
- //emplace_back(pos, int, int)
- {
- static_vector<T, N> v;
-
- for (int i = 0 ; i < int(N) ; ++i )
- v.emplace_back(i, 100 + i);
- BOOST_TEST(v.size() == N);
+ //emplace_back(pos, int, int)
+ {
+ static_vector<T, N> v;
+
+ for (int i = 0 ; i < int(N) ; ++i )
+ v.emplace_back(i, 100 + i);
+ BOOST_TEST(v.size() == N);
#ifndef BOOST_NO_EXCEPTIONS
- BOOST_TEST_THROW(v.emplace_back(N, 100 + N), std::bad_alloc);
+ BOOST_TEST_THROW(v.emplace_back(N, 100 + N), std::bad_alloc);
#endif
- BOOST_TEST(v.size() == N);
- for (int i = 0 ; i < int(N) ; ++i )
- BOOST_TEST(v[i] == T(i, 100 + i));
- }
-
- // emplace(pos, int, int)
- {
- typedef typename static_vector<T, N>::iterator It;
-
- int h = N / 2;
-
- static_vector<T, N> v;
- for ( int i = 0 ; i < h ; ++i )
- v.emplace_back(i, 100 + i);
-
- for ( int i = 0 ; i <= h ; ++i )
- {
- static_vector<T, N> vv(v);
- It it = vv.emplace(vv.begin() + i, i+100, i+200);
- BOOST_TEST(vv.begin() + i == it);
- BOOST_TEST(vv.size() == size_t(h+1));
- for ( int j = 0 ; j < i ; ++j )
- BOOST_TEST(vv[j] == T(j, j+100));
- BOOST_TEST(vv[i] == T(i+100, i+200));
- for ( int j = 0 ; j < h-i ; ++j )
- BOOST_TEST(vv[j+i+1] == T(j+i, j+i+100));
- }
- }
+ BOOST_TEST(v.size() == N);
+ for (int i = 0 ; i < int(N) ; ++i )
+ BOOST_TEST(v[i] == T(i, 100 + i));
+ }
+
+ // emplace(pos, int, int)
+ {
+ typedef typename static_vector<T, N>::iterator It;
+
+ int h = N / 2;
+
+ static_vector<T, N> v;
+ for ( int i = 0 ; i < h ; ++i )
+ v.emplace_back(i, 100 + i);
+
+ for ( int i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> vv(v);
+ It it = vv.emplace(vv.begin() + i, i+100, i+200);
+ BOOST_TEST(vv.begin() + i == it);
+ BOOST_TEST(vv.size() == size_t(h+1));
+ for ( int j = 0 ; j < i ; ++j )
+ BOOST_TEST(vv[j] == T(j, j+100));
+ BOOST_TEST(vv[i] == T(i+100, i+200));
+ for ( int j = 0 ; j < h-i ; ++j )
+ BOOST_TEST(vv[j+i+1] == T(j+i, j+i+100));
+ }
+ }
}
template <typename T, size_t N>
void test_sv_elem(T const& t)
{
- typedef static_vector<T, N> V;
+ typedef static_vector<T, N> V;
- static_vector<V, N> v;
+ static_vector<V, N> v;
- v.push_back(V(N/2, t));
- V vvv(N/2, t);
- v.push_back(boost::move(vvv));
- v.insert(v.begin(), V(N/2, t));
- v.insert(v.end(), V(N/2, t));
- v.emplace_back(N/2, t);
+ v.push_back(V(N/2, t));
+ V vvv(N/2, t);
+ v.push_back(boost::move(vvv));
+ v.insert(v.begin(), V(N/2, t));
+ v.insert(v.end(), V(N/2, t));
+ v.emplace_back(N/2, t);
}
int main(int, char* [])
{
- BOOST_TEST(counting_value::count() == 0);
-
- test_ctor_ndc<int, 10>();
- test_ctor_ndc<value_ndc, 10>();
- test_ctor_ndc<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
- test_ctor_ndc<shptr_value, 10>();
- test_ctor_ndc<copy_movable, 10>();
-
- test_ctor_nc<int, 10>(5);
- test_ctor_nc<value_nc, 10>(5);
- test_ctor_nc<counting_value, 10>(5);
- BOOST_TEST(counting_value::count() == 0);
- test_ctor_nc<shptr_value, 10>(5);
- test_ctor_nc<copy_movable, 10>(5);
-
- test_ctor_nd<int, 10>(5, 1);
- test_ctor_nd<value_nd, 10>(5, value_nd(1));
- test_ctor_nd<counting_value, 10>(5, counting_value(1));
- BOOST_TEST(counting_value::count() == 0);
- test_ctor_nd<shptr_value, 10>(5, shptr_value(1));
- test_ctor_nd<copy_movable, 10>(5, produce());
-
- test_resize_nc<int, 10>(5);
- test_resize_nc<value_nc, 10>(5);
- test_resize_nc<counting_value, 10>(5);
- BOOST_TEST(counting_value::count() == 0);
- test_resize_nc<shptr_value, 10>(5);
- test_resize_nc<copy_movable, 10>(5);
-
- test_resize_nd<int, 10>(5, 1);
- test_resize_nd<value_nd, 10>(5, value_nd(1));
- test_resize_nd<counting_value, 10>(5, counting_value(1));
- BOOST_TEST(counting_value::count() == 0);
- test_resize_nd<shptr_value, 10>(5, shptr_value(1));
- test_resize_nd<copy_movable, 10>(5, produce());
-
- test_push_back_nd<int, 10>();
- test_push_back_nd<value_nd, 10>();
- test_push_back_nd<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
- test_push_back_nd<shptr_value, 10>();
- test_push_back_nd<copy_movable, 10>();
-
- test_pop_back_nd<int, 10>();
- test_pop_back_nd<value_nd, 10>();
- test_pop_back_nd<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
- test_pop_back_nd<shptr_value, 10>();
- test_pop_back_nd<copy_movable, 10>();
-
- test_copy_and_assign_nd<int, 10>(1);
- test_copy_and_assign_nd<value_nd, 10>(value_nd(1));
- test_copy_and_assign_nd<counting_value, 10>(counting_value(1));
- BOOST_TEST(counting_value::count() == 0);
- test_copy_and_assign_nd<shptr_value, 10>(shptr_value(1));
- test_copy_and_assign_nd<copy_movable, 10>(produce());
-
- test_iterators_nd<int, 10>();
- test_iterators_nd<value_nd, 10>();
- test_iterators_nd<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
- test_iterators_nd<shptr_value, 10>();
- test_iterators_nd<copy_movable, 10>();
-
- test_erase_nd<int, 10>();
- test_erase_nd<value_nd, 10>();
- test_erase_nd<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
- test_erase_nd<shptr_value, 10>();
- test_erase_nd<copy_movable, 10>();
-
- test_insert_nd<int, 10>(50);
- test_insert_nd<value_nd, 10>(value_nd(50));
- test_insert_nd<counting_value, 10>(counting_value(50));
- BOOST_TEST(counting_value::count() == 0);
- test_insert_nd<shptr_value, 10>(shptr_value(50));
- test_insert_nd<copy_movable, 10>(produce());
-
- test_capacity_0_nd<int>();
- test_capacity_0_nd<value_nd>();
- test_capacity_0_nd<counting_value>();
- BOOST_TEST(counting_value::count() == 0);
- test_capacity_0_nd<shptr_value>();
- test_capacity_0_nd<copy_movable>();
-
- test_exceptions_nd<int, 10>();
- test_exceptions_nd<value_nd, 10>();
- test_exceptions_nd<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
- test_exceptions_nd<shptr_value, 10>();
- test_exceptions_nd<copy_movable, 10>();
-
- test_swap_and_move_nd<int, 10>();
- test_swap_and_move_nd<value_nd, 10>();
- test_swap_and_move_nd<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
- test_swap_and_move_nd<shptr_value, 10>();
- test_swap_and_move_nd<copy_movable, 10>();
-
- test_emplace_0p<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
-
- test_emplace_2p<counting_value, 10>();
- BOOST_TEST(counting_value::count() == 0);
-
- test_sv_elem<int, 10>(50);
- test_sv_elem<value_nd, 10>(value_nd(50));
- test_sv_elem<counting_value, 10>(counting_value(50));
- BOOST_TEST(counting_value::count() == 0);
- test_sv_elem<shptr_value, 10>(shptr_value(50));
- test_sv_elem<copy_movable, 10>(copy_movable(50));
-
- return boost::report_errors();
+ using boost::container::test::movable_and_copyable_int;
+ using boost::container::test::produce_movable_and_copyable_int;
+ BOOST_TEST(counting_value::count() == 0);
+
+ test_ctor_ndc<int, 10>();
+ test_ctor_ndc<value_ndc, 10>();
+ test_ctor_ndc<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_ctor_ndc<shptr_value, 10>();
+ test_ctor_ndc<movable_and_copyable_int, 10>();
+
+ test_ctor_nc<int, 10>(5);
+ test_ctor_nc<value_nc, 10>(5);
+ test_ctor_nc<counting_value, 10>(5);
+ BOOST_TEST(counting_value::count() == 0);
+ test_ctor_nc<shptr_value, 10>(5);
+ test_ctor_nc<movable_and_copyable_int, 10>(5);
+
+ test_ctor_nd<int, 10>(5, 1);
+ test_ctor_nd<value_nd, 10>(5, value_nd(1));
+ test_ctor_nd<counting_value, 10>(5, counting_value(1));
+ BOOST_TEST(counting_value::count() == 0);
+ test_ctor_nd<shptr_value, 10>(5, shptr_value(1));
+ test_ctor_nd<movable_and_copyable_int, 10>(5, produce_movable_and_copyable_int());
+
+ test_resize_nc<int, 10>(5);
+ test_resize_nc<value_nc, 10>(5);
+ test_resize_nc<counting_value, 10>(5);
+ BOOST_TEST(counting_value::count() == 0);
+ test_resize_nc<shptr_value, 10>(5);
+ test_resize_nc<movable_and_copyable_int, 10>(5);
+
+ test_resize_nd<int, 10>(5, 1);
+ test_resize_nd<value_nd, 10>(5, value_nd(1));
+ test_resize_nd<counting_value, 10>(5, counting_value(1));
+ BOOST_TEST(counting_value::count() == 0);
+ test_resize_nd<shptr_value, 10>(5, shptr_value(1));
+ test_resize_nd<movable_and_copyable_int, 10>(5, produce_movable_and_copyable_int());
+
+ test_push_back_nd<int, 10>();
+ test_push_back_nd<value_nd, 10>();
+ test_push_back_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_push_back_nd<shptr_value, 10>();
+ test_push_back_nd<movable_and_copyable_int, 10>();
+
+ test_pop_back_nd<int, 10>();
+ test_pop_back_nd<value_nd, 10>();
+ test_pop_back_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_pop_back_nd<shptr_value, 10>();
+ test_pop_back_nd<movable_and_copyable_int, 10>();
+
+ test_copy_and_assign_nd<int, 10>(1);
+ test_copy_and_assign_nd<value_nd, 10>(value_nd(1));
+ test_copy_and_assign_nd<counting_value, 10>(counting_value(1));
+ BOOST_TEST(counting_value::count() == 0);
+ test_copy_and_assign_nd<shptr_value, 10>(shptr_value(1));
+ test_copy_and_assign_nd<movable_and_copyable_int, 10>(produce_movable_and_copyable_int());
+
+ test_iterators_nd<int, 10>();
+ test_iterators_nd<value_nd, 10>();
+ test_iterators_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_iterators_nd<shptr_value, 10>();
+ test_iterators_nd<movable_and_copyable_int, 10>();
+
+ test_erase_nd<int, 10>();
+ test_erase_nd<value_nd, 10>();
+ test_erase_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_erase_nd<shptr_value, 10>();
+ test_erase_nd<movable_and_copyable_int, 10>();
+
+ test_insert_nd<int, 10>(50);
+ test_insert_nd<value_nd, 10>(value_nd(50));
+ test_insert_nd<counting_value, 10>(counting_value(50));
+ BOOST_TEST(counting_value::count() == 0);
+ test_insert_nd<shptr_value, 10>(shptr_value(50));
+ test_insert_nd<movable_and_copyable_int, 10>(produce_movable_and_copyable_int());
+
+ test_capacity_0_nd<int>();
+ test_capacity_0_nd<value_nd>();
+ test_capacity_0_nd<counting_value>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_capacity_0_nd<shptr_value>();
+ test_capacity_0_nd<movable_and_copyable_int>();
+
+ test_exceptions_nd<int, 10>();
+ test_exceptions_nd<value_nd, 10>();
+ test_exceptions_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_exceptions_nd<shptr_value, 10>();
+ test_exceptions_nd<movable_and_copyable_int, 10>();
+
+ test_swap_and_move_nd<int, 10>();
+ test_swap_and_move_nd<value_nd, 10>();
+ test_swap_and_move_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_swap_and_move_nd<shptr_value, 10>();
+ test_swap_and_move_nd<movable_and_copyable_int, 10>();
+
+ test_emplace_0p<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+
+ test_emplace_2p<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+
+ test_sv_elem<int, 10>(50);
+ test_sv_elem<value_nd, 10>(value_nd(50));
+ test_sv_elem<counting_value, 10>(counting_value(50));
+ BOOST_TEST(counting_value::count() == 0);
+ test_sv_elem<shptr_value, 10>(shptr_value(50));
+ test_sv_elem<movable_and_copyable_int, 10>(movable_and_copyable_int(50));
+ return boost::report_errors();
}
#include <boost/container/detail/config_end.hpp>
Modified: trunk/libs/container/test/static_vector_test.hpp
==============================================================================
--- trunk/libs/container/test/static_vector_test.hpp (original)
+++ trunk/libs/container/test/static_vector_test.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -14,7 +14,7 @@
#include <boost/container/static_vector.hpp>
#include <boost/shared_ptr.hpp>
-#include "movable.hpp"
+#include "movable_int.hpp"
using namespace boost::container;
Modified: trunk/libs/container/test/vector_test.hpp
==============================================================================
--- trunk/libs/container/test/vector_test.hpp (original)
+++ trunk/libs/container/test/vector_test.hpp 2013-02-24 08:13:36 EST (Sun, 24 Feb 2013)
@@ -216,7 +216,12 @@
stdvector->push_back(int(1));
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
}
- { //push_back with enough capacity
+
+ { //test back()
+ const IntType test_this(1);
+ if(test_this != boostvector->back()) return 1;
+ }
+ { //pop_back with enough capacity
boostvector->pop_back();
boostvector->pop_back();
stdvector->pop_back();
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk