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

View File

@@ -627,6 +627,11 @@ then the operation is constant time, even with an O(1) size.
[section:configurable_containers Extended functionality: Configurable containers] [section:configurable_containers Extended functionality: Configurable containers]
[*Boost.Container] offers the possibility to configure at compile time some parameters of
several containers, apart from the stored type and the allocator. This configuration is passed as
the last template parameter and defined using the utility classes. The following containers can receive
useful configuration options:
[section:configurable_tree_based_associative_containers Configurable tree-based associative ordered containers] [section:configurable_tree_based_associative_containers Configurable tree-based associative ordered containers]
[classref boost::container::set set], [classref boost::container::multiset multiset], [classref boost::container::set set], [classref boost::container::multiset multiset],
@@ -667,8 +672,7 @@ used to customize these containers:
[section:configurable_vectors Configurable vectors] [section:configurable_vectors Configurable vectors]
[*Boost.Container] offers the possibility to configure at compile time some parameters of The configuration for [classref boost::container::vector vector] is passed as
[classref boost::container::vector vector] implementation. This configuration is passed as
the last template parameter and defined using the utility class the last template parameter and defined using the utility class
[classref boost::container::vector_options vector_options]. The following parameters can be configured: [classref boost::container::vector_options vector_options]. The following parameters can be configured:
@@ -697,8 +701,7 @@ used to customize `vector` container:
[section:configurable_deques Configurable deques] [section:configurable_deques Configurable deques]
[*Boost.Container] offers the possibility to configure at compile time some parameters of The configuration for [classref boost::container::deque deque] is passed as
[classref boost::container::deque deque] implementation. This configuration is passed as
the last template parameter and defined using the utility class the last template parameter and defined using the utility class
[classref boost::container::deque_options deque_options]. The following parameters can be configured: [classref boost::container::deque_options deque_options]. The following parameters can be configured:
@@ -708,6 +711,7 @@ Only one of these paratemers can be specified:
* [classref boost::container::block_bytes block_bytes]: the number of bytes deque will allocate for store * [classref boost::container::block_bytes block_bytes]: the number of bytes deque will allocate for store
elements contiguously: `deque::get_block_size()` will return aproximately `block_bytes/sizeof(value_type)`. elements contiguously: `deque::get_block_size()` will return aproximately `block_bytes/sizeof(value_type)`.
A value of zero means the default value. A value of zero means the default value.
* [classref boost::container::block_size block_size]: the number of elements deque will allocate contiguously. * [classref boost::container::block_size block_size]: the number of elements deque will allocate contiguously.
If this option is specified, `deque::get_block_size()` will return the specified `block_size`. If this option is specified, `deque::get_block_size()` will return the specified `block_size`.
A value of zero means the default value. A value of zero means the default value.
@@ -720,6 +724,28 @@ used to customize `deque` container:
[endsect] [endsect]
[section:configurable_static_vectors Configurable static vector]
The configuration for [classref boost::container::static_vector static_vector] is passed as
the last template parameter and defined using the utility class
[classref boost::container::static_vector_options static_vector_options]. The following parameters can be configured:
* [classref boost::container::alignment alignment]: the minimum alignment (in bytes) that the stored value type
needs. This option allows static vectors that need non-default alignments, e.g., to be used in SIMD operations.
* [classref boost::container::throw_on_overflow throw_on_overflow]: A boolean that specifies if the
container should throw an exception when the compile-time capacity is not enough to hold the requesteed number
of objects. When "false", if the capacit is overflowd, the implementation calls to BOOST_ASSERT and if that assertion
does not throw or abort, undefined behavior is triggered.
See the following example to see how [classref boost::container::static_vector_options static_vector_options] can be
used to customize `static_vector` container:
[import ../example/doc_custom_static_vector.cpp]
[doc_custom_static_vector]
[endsect]
[endsect] [endsect]
[section:extended_allocators Extended functionality: Extended allocators] [section:extended_allocators Extended functionality: Extended allocators]
@@ -1267,6 +1293,8 @@ use [*Boost.Container]? There are several reasons for that:
[section:release_notes Release Notes] [section:release_notes Release Notes]
[section:release_notes_boost_1_71_00 Boost 1.71 Release] [section:release_notes_boost_1_71_00 Boost 1.71 Release]
* Fixed bugs:
* [@https://github.com/boostorg/container/issues/88 GitHub #88: ['"Implement C++17 MoveAssignable requirements for self-move assignments"]]. * [@https://github.com/boostorg/container/issues/88 GitHub #88: ['"Implement C++17 MoveAssignable requirements for self-move assignments"]].
* [@https://github.com/boostorg/container/issues/107 GitHub #107: ['"Alignment ignored in resource_adaptor"]]. * [@https://github.com/boostorg/container/issues/107 GitHub #107: ['"Alignment ignored in resource_adaptor"]].
* [@https://github.com/boostorg/container/pull/109 GitHub #109: ['"Get rid of integer overflow in copy_move_algo.hpp (-fsanitize=integer)"]]. * [@https://github.com/boostorg/container/pull/109 GitHub #109: ['"Get rid of integer overflow in copy_move_algo.hpp (-fsanitize=integer)"]].
@@ -1277,9 +1305,12 @@ use [*Boost.Container]? There are several reasons for that:
* [@https://github.com/boostorg/container/issues/117 GitHub #117: ['"flat_map/map::insert_or_assign with hint has wrong return types"]]. * [@https://github.com/boostorg/container/issues/117 GitHub #117: ['"flat_map/map::insert_or_assign with hint has wrong return types"]].
* [@https://github.com/boostorg/container/issues/118 GitHub #118: ['"Non-unique inplace_set_difference used in in flat_tree_merge_unique and iterator invalidation in insert_unique"]]. * [@https://github.com/boostorg/container/issues/118 GitHub #118: ['"Non-unique inplace_set_difference used in in flat_tree_merge_unique and iterator invalidation in insert_unique"]].
* ['deque] can now have options, using [classref boost::container::deque_options deque_options]. * [classref boost::container::deque deque] can now have options, using [classref boost::container::deque_options deque_options].
The block size/bytes can be be specified. The block size/bytes can be be specified.
* [classref boost::container::static_vector static_vector] can now have options, using [classref boost::container::static_vector_options static_vector_options].
The alignment and throwing behaviour can be be specified.
[endsect] [endsect]
[section:release_notes_boost_1_70_00 Boost 1.70 Release] [section:release_notes_boost_1_70_00 Boost 1.70 Release]

View File

@@ -106,7 +106,7 @@ template <class T
,class Allocator = void > ,class Allocator = void >
class stable_vector; class stable_vector;
template <class T, std::size_t Capacity> template <class T, std::size_t Capacity, class Options = void>
class static_vector; class static_vector;
template <class T, class Allocator = void > template <class T, class Allocator = void >

View File

@@ -195,17 +195,17 @@ struct insert_move_proxy
typedef typename alloc_traits::size_type size_type; typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_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) : 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; BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) ); 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; BOOST_ASSERT(n == 1); (void)n;
*p = ::boost::move(v_); *p = ::boost::move(v_);

View File

@@ -19,6 +19,7 @@
#endif #endif
#include <boost/container/allocator_traits.hpp> #include <boost/container/allocator_traits.hpp>
#include <boost/container/container_fwd.hpp>
namespace boost { namespace boost {
@@ -49,27 +50,6 @@ namespace dtl {
typedef Cont<U> type; 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 #else //C++03 compilers
template <template <class> class Cont //0arg 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; 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) #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 dtl {
} //namespace container { } //namespace container {
} //namespace boost { } //namespace boost {

View File

@@ -253,6 +253,137 @@ using vector_options_t = typename boost::container::vector_options<Options...>::
#endif #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
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// //
// //

View File

@@ -35,9 +35,21 @@ namespace boost { namespace container {
namespace dtl { 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 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: public:
typedef T value_type; typedef T value_type;
@@ -61,6 +73,11 @@ class static_storage_allocator
std::size_t max_size() const std::size_t max_size() const
{ return N; } { 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; 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 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; } { return true; }
private: 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 { } //namespace dtl {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #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 //! 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. //! 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. //!@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 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 #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) 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; friend class static_vector;
public: public:
typedef dtl::static_storage_allocator<Value, Capacity> allocator_type;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -162,7 +207,7 @@ public:
//! @param count The number of values which will be contained in the container. //! @param count The number of values which will be contained in the container.
//! //!
//! @par Throws //! @par Throws
//! If Value's value initialization throws. //! If T's value initialization throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -177,7 +222,7 @@ public:
//! @param count The number of values which will be contained in the container. //! @param count The number of values which will be contained in the container.
//! //!
//! @par Throws //! @par Throws
//! If Value's default initialization throws. //! If T's default initialization throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -196,7 +241,7 @@ public:
//! @param value The value which will be used to copy construct values. //! @param value The value which will be used to copy construct values.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor throws. //! If T's copy constructor throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -214,7 +259,7 @@ public:
//! @param last The iterator to the one after the last element in range. //! @param last The iterator to the one after the last element in range.
//! //!
//! @par Throws //! @par Throws
//! If Value's constructor taking a dereferenced Iterator throws. //! If T's constructor taking a dereferenced Iterator throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -232,7 +277,7 @@ public:
//! @param il std::initializer_list with values to initialize vector. //! @param il std::initializer_list with values to initialize vector.
//! //!
//! @par Throws //! @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 //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -246,7 +291,7 @@ public:
//! @param other The static_vector which content will be copied to this one. //! @param other The static_vector which content will be copied to this one.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor throws. //! If T's copy constructor throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -274,12 +319,12 @@ public:
//! @param other The static_vector which content will be copied to this one. //! @param other The static_vector which content will be copied to this one.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor throws. //! If T's copy constructor throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
template <std::size_t C> template <std::size_t C, class O>
BOOST_CONTAINER_FORCEINLINE static_vector(static_vector<value_type, C> const& other) BOOST_CONTAINER_FORCEINLINE static_vector(static_vector<T, C, O> const& other)
: base_t(other) : base_t(other)
{} {}
@@ -288,8 +333,8 @@ public:
//! @param other The static_vector which content will be moved to this one. //! @param other The static_vector which content will be moved to this one.
//! //!
//! @par Throws //! @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<T>::value is \c true and T'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 false and T's copy constructor throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -305,14 +350,14 @@ public:
//! @param other The static_vector which content will be moved to this one. //! @param other The static_vector which content will be moved to this one.
//! //!
//! @par Throws //! @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<T>::value is \c true and T'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 false and T's copy constructor throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
template <std::size_t C> template <std::size_t C, class O>
BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other) 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<value_type BOOST_MOVE_I C>::base_t, 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. //! @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. //! @param other The static_vector which content will be copied to this one.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor or copy assignment throws. //! If T's copy constructor or copy assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -335,7 +380,7 @@ public:
//! @param il The std::initializer_list which content will be copied to this one. //! @param il The std::initializer_list which content will be copied to this one.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor or copy assignment throws. //! If T's copy constructor or copy assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -350,15 +395,15 @@ public:
//! @param other The static_vector which content will be copied to this one. //! @param other The static_vector which content will be copied to this one.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor or copy assignment throws. //! If T's copy constructor or copy assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
template <std::size_t C> template <std::size_t C, class O>
BOOST_CONTAINER_FORCEINLINE static_vector & operator=(static_vector<value_type, C> const& other) BOOST_CONTAINER_FORCEINLINE static_vector & operator=(static_vector<T, C, O> const& other)
{ {
return static_cast<static_vector&>(base_t::operator= 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. //! @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. //! @param other The static_vector which content will be moved to this one.
//! //!
//! @par Throws //! @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<T>::value is \c true and T'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 false and T's copy constructor or copy assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -384,16 +429,16 @@ public:
//! @param other The static_vector which content will be moved to this one. //! @param other The static_vector which content will be moved to this one.
//! //!
//! @par Throws //! @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<T>::value is \c true and T'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 false and T's copy constructor or copy assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
template <std::size_t C> template <std::size_t C, class O>
BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other) 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= 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 #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. //! @param other The static_vector which content will be swapped with this one's content.
//! //!
//! @par Throws //! @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<T>::value is \c true and T'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 false and T's copy constructor or copy assignment throws,
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -426,13 +471,13 @@ public:
//! @param other The static_vector which content will be swapped with this one's content. //! @param other The static_vector which content will be swapped with this one's content.
//! //!
//! @par Throws //! @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<T>::value is \c true and T'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 false and T's copy constructor or copy assignment throws,
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
template <std::size_t C> template <std::size_t C, class O>
void swap(static_vector<value_type, C> & other); void swap(static_vector<T, C, O> & other);
//! @pre <tt>count <= capacity()</tt> //! @pre <tt>count <= capacity()</tt>
//! //!
@@ -442,7 +487,7 @@ public:
//! @param count The number of elements which will be stored in the container. //! @param count The number of elements which will be stored in the container.
//! //!
//! @par Throws //! @par Throws
//! If Value's value initialization throws. //! If T's value initialization throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -456,7 +501,7 @@ public:
//! @param count The number of elements which will be stored in the container. //! @param count The number of elements which will be stored in the container.
//! //!
//! @par Throws //! @par Throws
//! If Value's default initialization throws. //! If T's default initialization throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -474,7 +519,7 @@ public:
//! @param value The value used to copy construct the new element. //! @param value The value used to copy construct the new element.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor throws. //! If T's copy constructor throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -500,7 +545,7 @@ public:
//! @param value The value used to copy construct the new element. //! @param value The value used to copy construct the new element.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor throws. //! If T's copy constructor throws.
//! //!
//! @par Complexity //! @par Complexity
//! Constant O(1). //! Constant O(1).
@@ -513,7 +558,7 @@ public:
//! @param value The value to move construct the new element. //! @param value The value to move construct the new element.
//! //!
//! @par Throws //! @par Throws
//! If Value's move constructor throws. //! If T's move constructor throws.
//! //!
//! @par Complexity //! @par Complexity
//! Constant O(1). //! Constant O(1).
@@ -540,8 +585,8 @@ public:
//! @param value The value used to copy construct the new element. //! @param value The value used to copy construct the new element.
//! //!
//! @par Throws //! @par Throws
//! @li If Value's copy constructor or copy assignment throws //! @li If T's copy constructor or copy assignment throws
//! @li If Value's move constructor or move assignment throws. //! @li If T's move constructor or move assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Constant or linear. //! Constant or linear.
@@ -557,7 +602,7 @@ public:
//! @param value The value used to move construct the new element. //! @param value The value used to move construct the new element.
//! //!
//! @par Throws //! @par Throws
//! If Value's move constructor or move assignment throws. //! If T's move constructor or move assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Constant or linear. //! Constant or linear.
@@ -574,8 +619,8 @@ public:
//! @param value The value used to copy construct new elements. //! @param value The value used to copy construct new elements.
//! //!
//! @par Throws //! @par Throws
//! @li If Value's copy constructor or copy assignment throws. //! @li If T's copy constructor or copy assignment throws.
//! @li If Value's move constructor or move assignment throws. //! @li If T's move constructor or move assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! 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. //! @param last The iterator to the one after the last element of a range used to construct new elements.
//! //!
//! @par Throws //! @par Throws
//! @li If Value's constructor and assignment taking a dereferenced \c Iterator. //! @li If T's constructor and assignment taking a dereferenced \c Iterator.
//! @li If Value's move constructor or move assignment throws. //! @li If T's move constructor or move assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -611,7 +656,7 @@ public:
//! @param il The std::initializer_list which contains elements that will be inserted. //! @param il The std::initializer_list which contains elements that will be inserted.
//! //!
//! @par Throws //! @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 //! @par Complexity
//! Linear O(N). //! 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> //! @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. //! @param p The position of the element which will be erased from the container.
//! //!
//! @par Throws //! @par Throws
//! If Value's move assignment throws. //! If T's move assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! 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. //! @param last The position of the one after the last element of a range which will be erased from the container.
//! //!
//! @par Throws //! @par Throws
//! If Value's move assignment throws. //! If T's move assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! 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. //! @param last The iterator to the one after the last element of a range used to construct new content of this container.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor or copy assignment throws, //! If T's copy constructor or copy assignment throws,
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -668,7 +713,7 @@ public:
//! @param il std::initializer_list with values used to construct new content of this container. //! @param il std::initializer_list with values used to construct new content of this container.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor or copy assignment throws, //! If T's copy constructor or copy assignment throws,
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -682,7 +727,7 @@ public:
//! @param value The value which will be used to copy construct the new content. //! @param value The value which will be used to copy construct the new content.
//! //!
//! @par Throws //! @par Throws
//! If Value's copy constructor or copy assignment throws. //! If T's copy constructor or copy assignment throws.
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
@@ -690,7 +735,7 @@ public:
//! @pre <tt>size() < capacity()</tt> //! @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. //! \c std::forward<Args>(args)... in the end of the container.
//! //!
//! @return A reference to the created object. //! @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. //! @param args The arguments of the constructor of the new element which will be created at the end of the container.
//! //!
//! @par Throws //! @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 //! @par Complexity
//! Constant O(1). //! 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 \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>
//! @li <tt>size() < capacity()</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 //! \c std::forward<Args>(args)... before p
//! //!
//! @param p The position at which new elements will be inserted. //! @param p The position at which new elements will be inserted.
//! @param args The arguments of the constructor of the new element. //! @param args The arguments of the constructor of the new element.
//! //!
//! @par Throws //! @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 //! @par Complexity
//! Constant or linear. //! Constant or linear.
@@ -920,7 +965,7 @@ public:
//! //!
//! @par Complexity //! @par Complexity
//! Constant O(1). //! 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. //! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
//! For a non-empty vector <tt>data() == &front()</tt>. //! For a non-empty vector <tt>data() == &front()</tt>.
@@ -930,7 +975,7 @@ public:
//! //!
//! @par Complexity //! @par Complexity
//! Constant O(1). //! 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. //! @brief Returns iterator to the first element.
//! //!
@@ -1138,8 +1183,8 @@ public:
//! //!
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2> template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator== (static_vector<V, C1> const& x, static_vector<V, C2> const& y); 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. //! @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 //! @par Complexity
//! Linear O(N). //! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2> template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator!= (static_vector<V, C1> const& x, static_vector<V, C2> const& y); bool operator!= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors. //! @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 //! @par Complexity
//! Linear O(N). //! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2> template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator< (static_vector<V, C1> const& x, static_vector<V, C2> const& y); bool operator< (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors. //! @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 //! @par Complexity
//! Linear O(N). //! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2> template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator> (static_vector<V, C1> const& x, static_vector<V, C2> const& y); bool operator> (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors. //! @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 //! @par Complexity
//! Linear O(N). //! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2> template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator<= (static_vector<V, C1> const& x, static_vector<V, C2> const& y); bool operator<= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors. //! @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 //! @par Complexity
//! Linear O(N). //! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2> template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
bool operator>= (static_vector<V, C1> const& x, static_vector<V, C2> const& y); bool operator>= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Swaps contents of two static_vectors. //! @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 //! @par Complexity
//! Linear O(N). //! Linear O(N).
template<typename V, std::size_t C1, std::size_t C2> template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y); inline void swap(static_vector<V, C1, O1> & x, static_vector<V, C2, O2> & y);
#else #else
template<typename V, std::size_t C1, std::size_t C2> template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y inline void swap(static_vector<V, C1, O1> & x, static_vector<V, C2, O2> & y
, typename dtl::enable_if_c< C1 != C2>::type * = 0) , typename dtl::enable_if_c< C1 != C2>::type * = 0)
{ {
x.swap(y); x.swap(y);

View File

@@ -501,6 +501,9 @@ struct vector_alloc_holder
BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW
{ BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; } { BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; }
static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
{ }
private: private:
void priv_first_allocation(size_type cap) 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())); (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) BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap)
{ {
if(cap > allocator_type::internal_capacity){ 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; 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){ 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); this->priv_deep_swap(x);
} }
BOOST_CONTAINER_FORCEINLINE void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW 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 { //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 &) BOOST_CONTAINER_FORCEINLINE void steal_resources(vector_alloc_holder &)
{ //Containers with version 0 allocators can't be moved without moving elements one by one { //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 BOOST_CONTAINER_FORCEINLINE allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
@@ -2327,7 +2333,7 @@ private:
template<class FwdIt, class Compare> template<class FwdIt, class Compare>
BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0) 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> 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 && if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
this->capacity() < x.size()){ this->capacity() < x.size()){
throw_bad_alloc(); alloc_holder_t::on_capacity_overflow();
} }
T* const this_start = this->priv_raw_begin(); T* const this_start = this->priv_raw_begin();
T* const other_start = x.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 && if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
this->capacity() < x.size()){ this->capacity() < x.size()){
throw_bad_alloc(); alloc_holder_t::on_capacity_overflow();
} }
T* const this_start = this->priv_raw_begin(); T* const this_start = this->priv_raw_begin();
T* const other_start = x.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) 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() 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))); ( 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); } { 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); } { return dtl::insert_move_proxy<allocator_type, T*> (x); }
template <class U> template <class U>
@@ -2731,7 +2737,7 @@ private:
iterator priv_forward_range_insert_no_capacity iterator priv_forward_range_insert_no_capacity
(const pointer &pos, const size_type, const InsertionProxy , version_0) (const pointer &pos, const size_type, const InsertionProxy , version_0)
{ {
throw_bad_alloc(); alloc_holder_t::on_capacity_overflow();
return iterator(pos); return iterator(pos);
} }
@@ -2831,7 +2837,7 @@ private:
if (n > remaining){ if (n > remaining){
//This will trigger an error //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); this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
return this->end(); return this->end();