Added options to static_vector: throw_on_overflow/alignment

This commit is contained in:
Ion Gaztañaga
2019-05-09 13:25:50 +02:00
parent e23c57337f
commit 5d96b11fe0
7 changed files with 336 additions and 218 deletions
+1 -1
View File
@@ -106,7 +106,7 @@ template <class T
,class Allocator = void >
class stable_vector;
template <class T, std::size_t Capacity>
template <class T, std::size_t Capacity, class Options = void>
class static_vector;
template <class T, class Allocator = void >
@@ -195,17 +195,17 @@ struct insert_move_proxy
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
explicit insert_move_proxy(value_type &v)
BOOST_CONTAINER_FORCEINLINE explicit insert_move_proxy(value_type &v)
: v_(v)
{}
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
}
void copy_n_and_update(Allocator &, Iterator p, size_type n) const
BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p = ::boost::move(v_);
@@ -19,6 +19,7 @@
#endif
#include <boost/container/allocator_traits.hpp>
#include <boost/container/container_fwd.hpp>
namespace boost {
@@ -49,27 +50,6 @@ namespace dtl {
typedef Cont<U> type;
};
//for small_vector,static_vector
template <template <class, std::size_t, class, class...> class Cont, typename V, std::size_t N, typename A, class... An, class U>
struct container_rebind<Cont<V, N, A, An...>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, An...> type;
};
//Needed for non-conforming compilers like GCC 4.3
template <template <class, std::size_t, class> class Cont, typename V, std::size_t N, typename A, class U>
struct container_rebind<Cont<V, N, A>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type> type;
};
template <template <class, std::size_t> class Cont, typename V, std::size_t N, class U>
struct container_rebind<Cont<V, N>, U>
{
typedef Cont<U, N> type;
};
#else //C++03 compilers
template <template <class> class Cont //0arg
@@ -160,97 +140,22 @@ namespace dtl {
typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
};
//For small_vector/static_vector
template <template <class, std::size_t> class Cont //0arg
, typename V, std::size_t N
, class U>
struct container_rebind<Cont<V, N>, U>
{
typedef Cont<U, N> type;
};
template <template <class, std::size_t, class> class Cont //0arg
, typename V, std::size_t N, typename A
, class U>
struct container_rebind<Cont<V, N, A>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type> type;
};
template <template <class, std::size_t, class, class> class Cont //1arg
, typename V, std::size_t N, typename A, class P0
, class U>
struct container_rebind<Cont<V, N, A, P0>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0> type;
};
template <template <class, std::size_t, class, class, class> class Cont //2arg
, typename V, std::size_t N, typename A, class P0, class P1
, class U>
struct container_rebind<Cont<V, N, A, P0, P1>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1> type;
};
template <template <class, std::size_t, class, class, class, class> class Cont //3arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
};
template <template <class, std::size_t, class, class, class, class, class> class Cont //4arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
};
template <template <class, std::size_t, class, class, class, class, class, class> class Cont //5arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
};
template <template <class, std::size_t, class, class, class, class, class, class, class> class Cont //6arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
};
template <template <class, std::size_t, class, class, class, class, class, class, class, class> class Cont //7arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
};
template <template <class, std::size_t, class, class, class, class, class, class, class, class, class> class Cont //8arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
};
template <template <class, std::size_t, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
{
typedef Cont<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
};
#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
//for small_vector,static_vector
template <typename V, std::size_t N, typename A, class U>
struct container_rebind<small_vector<V, N, A>, U>
{
typedef small_vector<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type> type;
};
template <typename V, std::size_t N, typename O, class U>
struct container_rebind<static_vector<V, N, O>, U>
{
typedef static_vector<U, N, O> type;
};
} //namespace dtl {
} //namespace container {
} //namespace boost {
+131
View File
@@ -253,6 +253,137 @@ using vector_options_t = typename boost::container::vector_options<Options...>::
#endif
////////////////////////////////////////////////////////////////
//
//
// OPTIONS FOR SMALL-VECTOR CONTAINER
//
//
////////////////////////////////////////////////////////////////
//! This option specifies the desired alignment for the value_type stored
//! in the container.
//! A value zero represents the natural alignment.
//!
//!\tparam Alignment An unsigned integer value. Must be power of two.
BOOST_INTRUSIVE_OPTION_CONSTANT(alignment, std::size_t, Alignment, alignment)
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template<class GrowthType, std::size_t Alignment>
struct small_vector_opt
{
typedef GrowthType growth_factor_type;
static const std::size_t alignment = Alignment;
};
typedef small_vector_opt<void, 0u> small_vector_null_opt;
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! Helper metafunction to combine options into a single type to be used
//! by \c boost::container::small_vector.
//! Supported options are: \c boost::container::growth_factor and \c boost::container::alignment
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
#endif
struct small_vector_options
{
/// @cond
typedef typename ::boost::intrusive::pack_options
< small_vector_null_opt,
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
>::type packed_options;
typedef small_vector_opt< typename packed_options::growth_factor_type
, packed_options::alignment> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
//! Helper alias metafunction to combine options into a single type to be used
//! by \c boost::container::small_vector.
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
template<class ...Options>
using small_vector_options_t = typename boost::container::small_vector_options<Options...>::type;
#endif
////////////////////////////////////////////////////////////////
//
//
// OPTIONS FOR STATIC-VECTOR CONTAINER
//
//
////////////////////////////////////////////////////////////////
//!This option specifies if the container will throw if in
//!the static capacity is not sufficient to hold the required
//!values. If false is specified, insufficient capacity will
//!lead to BOOST_ASSERT, and if this assertion returns, to undefined behaviour,
//!which potentially can lead to better static_vector performance.
//!The default value is true.
//!
//!\tparam ThrowOnExhaustion A boolean value. True if throw is required.
BOOST_INTRUSIVE_OPTION_CONSTANT(throw_on_overflow, bool, ThrowOnOverflow, throw_on_overflow)
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template<bool ThrowOnOverflow, std::size_t Alignment>
struct static_vector_opt
{
static const bool throw_on_overflow = ThrowOnOverflow;
static const std::size_t alignment = Alignment;
};
typedef static_vector_opt<true, 0u> static_vector_null_opt;
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! Helper metafunction to combine options into a single type to be used
//! by \c boost::container::static_vector.
//! Supported options are: \c boost::container::throw_on_overflow and \c boost::container::alignment
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
#endif
struct static_vector_options
{
/// @cond
typedef typename ::boost::intrusive::pack_options
< static_vector_null_opt,
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
>::type packed_options;
typedef static_vector_opt< packed_options::throw_on_overflow
, packed_options::alignment> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
//! Helper alias metafunction to combine options into a single type to be used
//! by \c boost::container::static_vector.
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
template<class ...Options>
using static_vector_options_t = typename boost::container::static_vector_options<Options...>::type;
#endif
////////////////////////////////////////////////////////////////
//
//
+129 -84
View File
@@ -35,9 +35,21 @@ namespace boost { namespace container {
namespace dtl {
template<class T, std::size_t N>
template<class T, std::size_t N, std::size_t Alignment, bool ThrowOnOverflow>
class static_storage_allocator
{
typedef bool_<ThrowOnOverflow> throw_on_overflow_t;
static BOOST_NORETURN BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow(true_type)
{
(throw_bad_alloc)();
}
static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow(false_type)
{
BOOST_ASSERT_MSG(false, "ERROR: static vector capacity overflow");
}
public:
typedef T value_type;
@@ -61,6 +73,11 @@ class static_storage_allocator
std::size_t max_size() const
{ return N; }
static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
{
(on_capacity_overflow)(throw_on_overflow_t());
}
typedef boost::container::dtl::version_type<static_storage_allocator, 0> version;
BOOST_CONTAINER_FORCEINLINE friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
@@ -70,9 +87,36 @@ class static_storage_allocator
{ return true; }
private:
typename dtl::aligned_storage<sizeof(T)*N, dtl::alignment_of<T>::value>::type storage;
BOOST_STATIC_ASSERT_MSG(!Alignment || (Alignment & (Alignment-1)) == 0, "Alignment option must be zero or power of two");
static const std::size_t final_alignment = Alignment ? Alignment : dtl::alignment_of<T>::value;
typename dtl::aligned_storage<sizeof(T)*N, final_alignment>::type storage;
};
template<class Options>
struct get_static_vector_opt
{
typedef Options type;
};
template<>
struct get_static_vector_opt<void>
{
typedef static_vector_null_opt type;
};
template <typename T, std::size_t Capacity, class Options>
struct get_static_vector_allocator
{
typedef typename get_static_vector_opt<Options>::type options_t;
typedef dtl::static_storage_allocator
< T
, Capacity
, options_t::alignment
, options_t::throw_on_overflow
> type;
};
} //namespace dtl {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -99,22 +143,23 @@ class static_storage_allocator
//! std::out_of_range is thrown if out of bounds access is performed in <code>at()</code> if exceptions are
//! enabled, throw_out_of_range() if not enabled.
//!
//!@tparam Value The type of element that will be stored.
//!@tparam T The type of element that will be stored.
//!@tparam Capacity The maximum number of elements static_vector can store, fixed at compile time.
template <typename Value, std::size_t Capacity>
template <typename T, std::size_t Capacity, class Options BOOST_CONTAINER_DOCONLY(= void) >
class static_vector
: public vector<Value, dtl::static_storage_allocator<Value, Capacity> >
: public vector<T, typename dtl::get_static_vector_allocator< T, Capacity, Options>::type>
{
public:
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef vector<Value, dtl::static_storage_allocator<Value, Capacity> > base_t;
typedef typename dtl::get_static_vector_allocator< T, Capacity, Options>::type allocator_type;
typedef vector<T, allocator_type > base_t;
BOOST_COPYABLE_AND_MOVABLE(static_vector)
template<class U, std::size_t OtherCapacity>
template<class U, std::size_t OtherCapacity, class OtherOptions>
friend class static_vector;
public:
typedef dtl::static_storage_allocator<Value, Capacity> allocator_type;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -162,7 +207,7 @@ public:
//! @param count The number of values which will be contained in the container.
//!
//! @par Throws
//! If Value's value initialization throws.
//! If T's value initialization throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -177,7 +222,7 @@ public:
//! @param count The number of values which will be contained in the container.
//!
//! @par Throws
//! If Value's default initialization throws.
//! If T's default initialization throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -196,7 +241,7 @@ public:
//! @param value The value which will be used to copy construct values.
//!
//! @par Throws
//! If Value's copy constructor throws.
//! If T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -214,7 +259,7 @@ public:
//! @param last The iterator to the one after the last element in range.
//!
//! @par Throws
//! If Value's constructor taking a dereferenced Iterator throws.
//! If T's constructor taking a dereferenced Iterator throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -232,7 +277,7 @@ public:
//! @param il std::initializer_list with values to initialize vector.
//!
//! @par Throws
//! If Value's constructor taking a dereferenced std::initializer_list throws.
//! If T's constructor taking a dereferenced std::initializer_list throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -246,7 +291,7 @@ public:
//! @param other The static_vector which content will be copied to this one.
//!
//! @par Throws
//! If Value's copy constructor throws.
//! If T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -274,12 +319,12 @@ public:
//! @param other The static_vector which content will be copied to this one.
//!
//! @par Throws
//! If Value's copy constructor throws.
//! If T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
BOOST_CONTAINER_FORCEINLINE static_vector(static_vector<value_type, C> const& other)
template <std::size_t C, class O>
BOOST_CONTAINER_FORCEINLINE static_vector(static_vector<T, C, O> const& other)
: base_t(other)
{}
@@ -288,8 +333,8 @@ public:
//! @param other The static_vector which content will be moved to this one.
//!
//! @par Throws
//! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
//! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
//! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor throws.
//! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -305,14 +350,14 @@ public:
//! @param other The static_vector which content will be moved to this one.
//!
//! @par Throws
//! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
//! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
//! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor throws.
//! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
: base_t(BOOST_MOVE_BASE(typename static_vector<value_type BOOST_MOVE_I C>::base_t, other))
template <std::size_t C, class O>
BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF_BEG static_vector<T, C, O> BOOST_RV_REF_END other)
: base_t(BOOST_MOVE_BASE(typename static_vector<T BOOST_MOVE_I C>::base_t, other))
{}
//! @brief Copy assigns Values stored in the other static_vector to this one.
@@ -320,7 +365,7 @@ public:
//! @param other The static_vector which content will be copied to this one.
//!
//! @par Throws
//! If Value's copy constructor or copy assignment throws.
//! If T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -335,7 +380,7 @@ public:
//! @param il The std::initializer_list which content will be copied to this one.
//!
//! @par Throws
//! If Value's copy constructor or copy assignment throws.
//! If T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -350,15 +395,15 @@ public:
//! @param other The static_vector which content will be copied to this one.
//!
//! @par Throws
//! If Value's copy constructor or copy assignment throws.
//! If T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
BOOST_CONTAINER_FORCEINLINE static_vector & operator=(static_vector<value_type, C> const& other)
template <std::size_t C, class O>
BOOST_CONTAINER_FORCEINLINE static_vector & operator=(static_vector<T, C, O> const& other)
{
return static_cast<static_vector&>(base_t::operator=
(static_cast<typename static_vector<value_type, C>::base_t const&>(other)));
(static_cast<typename static_vector<T, C, O>::base_t const&>(other)));
}
//! @brief Move assignment. Moves Values stored in the other static_vector to this one.
@@ -366,8 +411,8 @@ public:
//! @param other The static_vector which content will be moved to this one.
//!
//! @par Throws
//! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
//! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
//! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor or move assignment throws.
//! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -384,16 +429,16 @@ public:
//! @param other The static_vector which content will be moved to this one.
//!
//! @par Throws
//! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
//! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
//! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor or move assignment throws.
//! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
template <std::size_t C, class O>
BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF_BEG static_vector<T, C, O> BOOST_RV_REF_END other)
{
return static_cast<static_vector&>(base_t::operator=
(BOOST_MOVE_BASE(typename static_vector<value_type BOOST_MOVE_I C>::base_t, other)));
(BOOST_MOVE_BASE(typename static_vector<T BOOST_MOVE_I C>::base_t, other)));
}
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -412,8 +457,8 @@ public:
//! @param other The static_vector which content will be swapped with this one's content.
//!
//! @par Throws
//! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
//! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
//! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor or move assignment throws,
//! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor or copy assignment throws,
//!
//! @par Complexity
//! Linear O(N).
@@ -426,13 +471,13 @@ public:
//! @param other The static_vector which content will be swapped with this one's content.
//!
//! @par Throws
//! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
//! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
//! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor or move assignment throws,
//! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor or copy assignment throws,
//!
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
void swap(static_vector<value_type, C> & other);
template <std::size_t C, class O>
void swap(static_vector<T, C, O> & other);
//! @pre <tt>count <= capacity()</tt>
//!
@@ -442,7 +487,7 @@ public:
//! @param count The number of elements which will be stored in the container.
//!
//! @par Throws
//! If Value's value initialization throws.
//! If T's value initialization throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -456,7 +501,7 @@ public:
//! @param count The number of elements which will be stored in the container.
//!
//! @par Throws
//! If Value's default initialization throws.
//! If T's default initialization throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -474,7 +519,7 @@ public:
//! @param value The value used to copy construct the new element.
//!
//! @par Throws
//! If Value's copy constructor throws.
//! If T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -500,7 +545,7 @@ public:
//! @param value The value used to copy construct the new element.
//!
//! @par Throws
//! If Value's copy constructor throws.
//! If T's copy constructor throws.
//!
//! @par Complexity
//! Constant O(1).
@@ -513,7 +558,7 @@ public:
//! @param value The value to move construct the new element.
//!
//! @par Throws
//! If Value's move constructor throws.
//! If T's move constructor throws.
//!
//! @par Complexity
//! Constant O(1).
@@ -540,8 +585,8 @@ public:
//! @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.
//! @li If T's copy constructor or copy assignment throws
//! @li If T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Constant or linear.
@@ -557,7 +602,7 @@ public:
//! @param value The value used to move construct the new element.
//!
//! @par Throws
//! If Value's move constructor or move assignment throws.
//! If T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Constant or linear.
@@ -574,8 +619,8 @@ public:
//! @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.
//! @li If T's copy constructor or copy assignment throws.
//! @li If T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -593,8 +638,8 @@ public:
//! @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.
//! @li If T's constructor and assignment taking a dereferenced \c Iterator.
//! @li If T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -611,7 +656,7 @@ public:
//! @param il The std::initializer_list which contains elements that will be inserted.
//!
//! @par Throws
//! @li If Value's constructor and assignment taking a dereferenced std::initializer_list iterator.
//! @li If T's constructor and assignment taking a dereferenced std::initializer_list iterator.
//!
//! @par Complexity
//! Linear O(N).
@@ -619,12 +664,12 @@ public:
//! @pre \c p must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>
//!
//! @brief Erases Value from p.
//! @brief Erases T from p.
//!
//! @param p The position of the element which will be erased from the container.
//!
//! @par Throws
//! If Value's move assignment throws.
//! If T's move assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -640,7 +685,7 @@ public:
//! @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.
//! If T's move assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -654,7 +699,7 @@ public:
//! @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,
//! If T's copy constructor or copy assignment throws,
//!
//! @par Complexity
//! Linear O(N).
@@ -668,7 +713,7 @@ public:
//! @param il std::initializer_list with values used to construct new content of this container.
//!
//! @par Throws
//! If Value's copy constructor or copy assignment throws,
//! If T's copy constructor or copy assignment throws,
//!
//! @par Complexity
//! Linear O(N).
@@ -682,7 +727,7 @@ public:
//! @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.
//! If T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -690,7 +735,7 @@ public:
//! @pre <tt>size() < capacity()</tt>
//!
//! @brief Inserts a Value constructed with
//! @brief Inserts a T constructed with
//! \c std::forward<Args>(args)... in the end of the container.
//!
//! @return A reference to the created object.
@@ -698,7 +743,7 @@ public:
//! @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.
//! If in-place constructor throws or T's move constructor throws.
//!
//! @par Complexity
//! Constant O(1).
@@ -709,14 +754,14 @@ public:
//! @li \c p 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
//! @brief Inserts a T constructed with
//! \c std::forward<Args>(args)... before p
//!
//! @param p 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.
//! If in-place constructor throws or if T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Constant or linear.
@@ -920,7 +965,7 @@ public:
//!
//! @par Complexity
//! Constant O(1).
Value * data() BOOST_NOEXCEPT_OR_NOTHROW;
T * data() BOOST_NOEXCEPT_OR_NOTHROW;
//! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
//! For a non-empty vector <tt>data() == &front()</tt>.
@@ -930,7 +975,7 @@ public:
//!
//! @par Complexity
//! Constant O(1).
const Value * data() const BOOST_NOEXCEPT_OR_NOTHROW;
const T * data() const BOOST_NOEXCEPT_OR_NOTHROW;
//! @brief Returns iterator to the first element.
//!
@@ -1138,8 +1183,8 @@ public:
//!
//! @par Complexity
//! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2>
bool operator== (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator== (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Checks if contents of two static_vectors are not equal.
//!
@@ -1152,8 +1197,8 @@ bool operator== (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2>
bool operator!= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator!= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors.
//!
@@ -1166,8 +1211,8 @@ bool operator!= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2>
bool operator< (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator< (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors.
//!
@@ -1180,8 +1225,8 @@ bool operator< (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2>
bool operator> (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator> (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors.
//!
@@ -1194,8 +1239,8 @@ bool operator> (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2>
bool operator<= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator<= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors.
//!
@@ -1208,8 +1253,8 @@ bool operator<= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2>
bool operator>= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator>= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Swaps contents of two static_vectors.
//!
@@ -1222,13 +1267,13 @@ bool operator>= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2>
inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y);
template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
inline void swap(static_vector<V, C1, O1> & x, static_vector<V, C2, O2> & y);
#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
template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
inline void swap(static_vector<V, C1, O1> & x, static_vector<V, C2, O2> & y
, typename dtl::enable_if_c< C1 != C2>::type * = 0)
{
x.swap(y);
+18 -12
View File
@@ -501,6 +501,9 @@ struct vector_alloc_holder
BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW
{ BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; }
static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
{ }
private:
void priv_first_allocation(size_type cap)
{
@@ -631,10 +634,13 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
(this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start()));
}
static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
{ allocator_type::on_capacity_overflow(); }
BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap)
{
if(cap > allocator_type::internal_capacity){
throw_bad_alloc();
on_capacity_overflow();
}
}
@@ -648,20 +654,20 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
{
typedef typename real_allocator<value_type, OtherAllocator>::type other_allocator_type;
if(this->m_size > other_allocator_type::internal_capacity || x.m_size > allocator_type::internal_capacity){
throw_bad_alloc();
on_capacity_overflow();
}
this->priv_deep_swap(x);
}
BOOST_CONTAINER_FORCEINLINE void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW
{ //Containers with version 0 allocators can't be moved without moving elements one by one
throw_bad_alloc();
on_capacity_overflow();
}
BOOST_CONTAINER_FORCEINLINE void steal_resources(vector_alloc_holder &)
{ //Containers with version 0 allocators can't be moved without moving elements one by one
throw_bad_alloc();
on_capacity_overflow();
}
BOOST_CONTAINER_FORCEINLINE allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
@@ -2327,7 +2333,7 @@ private:
template<class FwdIt, class Compare>
BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
{
throw_bad_alloc();
alloc_holder_t::on_capacity_overflow();
}
template<class FwdIt, class Compare, class Version>
@@ -2407,7 +2413,7 @@ private:
{
if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
this->capacity() < x.size()){
throw_bad_alloc();
alloc_holder_t::on_capacity_overflow();
}
T* const this_start = this->priv_raw_begin();
T* const other_start = x.priv_raw_begin();
@@ -2459,7 +2465,7 @@ private:
{
if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
this->capacity() < x.size()){
throw_bad_alloc();
alloc_holder_t::on_capacity_overflow();
}
T* const this_start = this->priv_raw_begin();
T* const other_start = x.priv_raw_begin();
@@ -2528,7 +2534,7 @@ private:
}
void priv_reserve_no_capacity(size_type, version_0)
{ throw_bad_alloc(); }
{ alloc_holder_t::on_capacity_overflow(); }
dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
{
@@ -2627,10 +2633,10 @@ private:
( vector_iterator_get_ptr(p), 1, dtl::get_insert_value_proxy<T*, allocator_type>(::boost::forward<U>(x)));
}
dtl::insert_copy_proxy<allocator_type, T*> priv_single_insert_proxy(const T &x)
BOOST_CONTAINER_FORCEINLINE dtl::insert_copy_proxy<allocator_type, T*> priv_single_insert_proxy(const T &x)
{ return dtl::insert_copy_proxy<allocator_type, T*> (x); }
dtl::insert_move_proxy<allocator_type, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
BOOST_CONTAINER_FORCEINLINE dtl::insert_move_proxy<allocator_type, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
{ return dtl::insert_move_proxy<allocator_type, T*> (x); }
template <class U>
@@ -2731,7 +2737,7 @@ private:
iterator priv_forward_range_insert_no_capacity
(const pointer &pos, const size_type, const InsertionProxy , version_0)
{
throw_bad_alloc();
alloc_holder_t::on_capacity_overflow();
return iterator(pos);
}
@@ -2831,7 +2837,7 @@ private:
if (n > remaining){
//This will trigger an error
throw_bad_alloc();
alloc_holder_t::on_capacity_overflow();
}
this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
return this->end();