mirror of
https://github.com/boostorg/container.git
synced 2025-07-30 12:37:17 +02:00
Added stored_size
option to static_vector
This commit is contained in:
@ -770,6 +770,12 @@ the last template parameter and defined using the utility class
|
|||||||
of objects. When "false", if the capacit is overflowed, the implementation calls to BOOST_ASSERT and if that assertion
|
of objects. When "false", if the capacit is overflowed, the implementation calls to BOOST_ASSERT and if that assertion
|
||||||
does not throw or abort, undefined behavior is triggered.
|
does not throw or abort, undefined behavior is triggered.
|
||||||
|
|
||||||
|
* [classref boost::container::stored_size stored_size]: the type that will be used to store size-related
|
||||||
|
parameters inside of the vector. Sometimes, when the static to be used is much less than `std::size_t`
|
||||||
|
it's interesting to use a smaller unsigned integer types to represent `size()` inside `static_vector``,
|
||||||
|
so that the size of an empty vector is minimized and cache
|
||||||
|
performance might be improved. See [classref boost::container::stored_size stored_size] for more details.
|
||||||
|
|
||||||
See the following example to see how [classref boost::container::static_vector_options static_vector_options] can be
|
See the following example to see how [classref boost::container::static_vector_options static_vector_options] can be
|
||||||
used to customize `static_vector`:
|
used to customize `static_vector`:
|
||||||
|
|
||||||
@ -1411,6 +1417,8 @@ use [*Boost.Container]? There are several reasons for that:
|
|||||||
|
|
||||||
[section:release_notes_boost_1_87_00 Boost 1.87 Release]
|
[section:release_notes_boost_1_87_00 Boost 1.87 Release]
|
||||||
|
|
||||||
|
* Added [classref boost::container::stored_size stored_size] option to [classref boost::container::static_vector static_vector].
|
||||||
|
|
||||||
* Fixed bugs/issues:
|
* Fixed bugs/issues:
|
||||||
* [@https://github.com/boostorg/container/issues/261 GitHub #261: ['"End iterators are not dereferencable"]].
|
* [@https://github.com/boostorg/container/issues/261 GitHub #261: ['"End iterators are not dereferencable"]].
|
||||||
* [@https://github.com/boostorg/container/issues/288 GitHub #288: ['"Compile error when using flat_map::extract_sequence with small_vector"]].
|
* [@https://github.com/boostorg/container/issues/288 GitHub #288: ['"Compile error when using flat_map::extract_sequence with small_vector"]].
|
||||||
|
@ -33,6 +33,14 @@ int main ()
|
|||||||
//Create static_vector with no throw on overflow
|
//Create static_vector with no throw on overflow
|
||||||
static_vector<int, 10, no_throw_options_t > sv2;
|
static_vector<int, 10, no_throw_options_t > sv2;
|
||||||
|
|
||||||
|
//This options specifies that internal `size()` can be represented by an unsigned char
|
||||||
|
//instead of the default `std::size_t`.
|
||||||
|
typedef static_vector_options< stored_size<unsigned char> >::type stored_size_uchar_t;
|
||||||
|
|
||||||
|
//Create static_vector that internally stores `size()` in an unsigned char
|
||||||
|
//because `capacity()` will be less thatn 256.
|
||||||
|
static_vector<unsigned char, 10, stored_size_uchar_t> sv3;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//]
|
//]
|
||||||
|
@ -289,8 +289,8 @@ BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_fa
|
|||||||
//!
|
//!
|
||||||
//!If the maximum capacity() to be used is limited, a user can try to use 8-bit, 16-bit
|
//!If the maximum capacity() to be used is limited, a user can try to use 8-bit, 16-bit
|
||||||
//!(e.g. in 32-bit machines), or 32-bit size types (e.g. in a 64 bit machine) to see if some
|
//!(e.g. in 32-bit machines), or 32-bit size types (e.g. in a 64 bit machine) to see if some
|
||||||
//!memory can be saved for empty vectors. This could potentially performance benefits due to better
|
//!memory can be saved, specially for empty containers. This could potentially improve performance
|
||||||
//!cache usage.
|
//!due to better cache usage.
|
||||||
//!
|
//!
|
||||||
//!Note that alignment requirements can disallow theoretical space savings. Example:
|
//!Note that alignment requirements can disallow theoretical space savings. Example:
|
||||||
//!\c vector holds a pointer and two size types (for size and capacity), in a 32 bit machine
|
//!\c vector holds a pointer and two size types (for size and capacity), in a 32 bit machine
|
||||||
@ -301,7 +301,7 @@ BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_fa
|
|||||||
//!Measure the size of the resulting container and do not assume a smaller \c stored_size
|
//!Measure the size of the resulting container and do not assume a smaller \c stored_size
|
||||||
//!will always lead to a smaller sizeof(container).
|
//!will always lead to a smaller sizeof(container).
|
||||||
//!
|
//!
|
||||||
//!If a user tries to insert more elements than representable by \c stored_size, vector
|
//!If a user tries to insert more elements than representable by \c stored_size, the container
|
||||||
//!will throw a length_error.
|
//!will throw a length_error.
|
||||||
//!
|
//!
|
||||||
//!If this option is not specified, `allocator_traits<A>::size_type` (usually std::size_t) will
|
//!If this option is not specified, `allocator_traits<A>::size_type` (usually std::size_t) will
|
||||||
@ -337,7 +337,6 @@ struct vector_options
|
|||||||
|
|
||||||
//! Helper alias metafunction to combine options into a single type to be used
|
//! Helper alias metafunction to combine options into a single type to be used
|
||||||
//! by \c boost::container::vector.
|
//! by \c boost::container::vector.
|
||||||
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
|
|
||||||
template<class ...Options>
|
template<class ...Options>
|
||||||
using vector_options_t = typename boost::container::vector_options<Options...>::type;
|
using vector_options_t = typename boost::container::vector_options<Options...>::type;
|
||||||
|
|
||||||
@ -400,7 +399,6 @@ struct small_vector_options
|
|||||||
|
|
||||||
//! Helper alias metafunction to combine options into a single type to be used
|
//! Helper alias metafunction to combine options into a single type to be used
|
||||||
//! by \c boost::container::small_vector.
|
//! by \c boost::container::small_vector.
|
||||||
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
|
|
||||||
template<class ...Options>
|
template<class ...Options>
|
||||||
using small_vector_options_t = typename boost::container::small_vector_options<Options...>::type;
|
using small_vector_options_t = typename boost::container::small_vector_options<Options...>::type;
|
||||||
|
|
||||||
@ -427,20 +425,22 @@ BOOST_INTRUSIVE_OPTION_CONSTANT(throw_on_overflow, bool, ThrowOnOverflow, throw_
|
|||||||
|
|
||||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||||
|
|
||||||
template<bool ThrowOnOverflow, std::size_t InplaceAlignment>
|
template<bool ThrowOnOverflow, std::size_t InplaceAlignment, class StoredSizeType>
|
||||||
struct static_vector_opt
|
struct static_vector_opt
|
||||||
{
|
{
|
||||||
BOOST_STATIC_CONSTEXPR bool throw_on_overflow = ThrowOnOverflow;
|
BOOST_STATIC_CONSTEXPR bool throw_on_overflow = ThrowOnOverflow;
|
||||||
BOOST_STATIC_CONSTEXPR std::size_t inplace_alignment = InplaceAlignment;
|
BOOST_STATIC_CONSTEXPR std::size_t inplace_alignment = InplaceAlignment;
|
||||||
|
typedef StoredSizeType stored_size_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef static_vector_opt<true, 0u> static_vector_null_opt;
|
typedef static_vector_opt<true, 0u, void> static_vector_null_opt;
|
||||||
|
|
||||||
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||||
|
|
||||||
//! Helper metafunction to combine options into a single type to be used
|
//! Helper metafunction to combine options into a single type to be used
|
||||||
//! by \c boost::container::static_vector.
|
//! by \c boost::container::static_vector.
|
||||||
//! Supported options are: \c boost::container::throw_on_overflow and \c boost::container::inplace_alignment
|
//! Supported options are: \c boost::container::throw_on_overflow, \c boost::container::inplace_alignment
|
||||||
|
//! and \c boost::container::stored_size.
|
||||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||||
template<class ...Options>
|
template<class ...Options>
|
||||||
#else
|
#else
|
||||||
@ -458,7 +458,9 @@ struct static_vector_options
|
|||||||
#endif
|
#endif
|
||||||
>::type packed_options;
|
>::type packed_options;
|
||||||
typedef static_vector_opt< packed_options::throw_on_overflow
|
typedef static_vector_opt< packed_options::throw_on_overflow
|
||||||
, packed_options::inplace_alignment> implementation_defined;
|
, packed_options::inplace_alignment
|
||||||
|
, typename packed_options::stored_size_type
|
||||||
|
> implementation_defined;
|
||||||
/// @endcond
|
/// @endcond
|
||||||
typedef implementation_defined type;
|
typedef implementation_defined type;
|
||||||
};
|
};
|
||||||
@ -467,7 +469,6 @@ struct static_vector_options
|
|||||||
|
|
||||||
//! Helper alias metafunction to combine options into a single type to be used
|
//! Helper alias metafunction to combine options into a single type to be used
|
||||||
//! by \c boost::container::static_vector.
|
//! by \c boost::container::static_vector.
|
||||||
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
|
|
||||||
template<class ...Options>
|
template<class ...Options>
|
||||||
using static_vector_options_t = typename boost::container::static_vector_options<Options...>::type;
|
using static_vector_options_t = typename boost::container::static_vector_options<Options...>::type;
|
||||||
|
|
||||||
@ -587,7 +588,6 @@ struct devector_options
|
|||||||
|
|
||||||
//! Helper alias metafunction to combine options into a single type to be used
|
//! Helper alias metafunction to combine options into a single type to be used
|
||||||
//! by \c boost::container::devector.
|
//! by \c boost::container::devector.
|
||||||
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
|
|
||||||
template<class ...Options>
|
template<class ...Options>
|
||||||
using devector_options_t = typename boost::container::devector_options<Options...>::type;
|
using devector_options_t = typename boost::container::devector_options<Options...>::type;
|
||||||
|
|
||||||
@ -643,7 +643,6 @@ struct deque_options
|
|||||||
|
|
||||||
//! Helper alias metafunction to combine options into a single type to be used
|
//! Helper alias metafunction to combine options into a single type to be used
|
||||||
//! by \c boost::container::deque.
|
//! by \c boost::container::deque.
|
||||||
//! Supported options are: \c boost::container::block_bytes
|
|
||||||
template<class ...Options>
|
template<class ...Options>
|
||||||
using deque_options_t = typename boost::container::deque_options<Options...>::type;
|
using deque_options_t = typename boost::container::deque_options<Options...>::type;
|
||||||
|
|
||||||
|
@ -102,6 +102,19 @@ struct get_static_vector_opt<void>
|
|||||||
typedef static_vector_null_opt type;
|
typedef static_vector_null_opt type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class Options>
|
||||||
|
struct get_vector_opt_from_static_vector_opt
|
||||||
|
{
|
||||||
|
typedef typename get_static_vector_opt<Options>::type options_t;
|
||||||
|
typedef vector_opt<void, typename options_t::stored_size_type> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct get_vector_opt_from_static_vector_opt<void>
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, std::size_t Capacity, class Options>
|
template <typename T, std::size_t Capacity, class Options>
|
||||||
struct get_static_vector_allocator
|
struct get_static_vector_allocator
|
||||||
{
|
{
|
||||||
@ -114,7 +127,6 @@ struct get_static_vector_allocator
|
|||||||
> type;
|
> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} //namespace dtl {
|
} //namespace dtl {
|
||||||
|
|
||||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||||
@ -148,12 +160,18 @@ struct get_static_vector_allocator
|
|||||||
//! is specified, by default throw_on_overflow<true> option is set.
|
//! is specified, by default throw_on_overflow<true> option is set.
|
||||||
template <typename T, std::size_t Capacity, class Options BOOST_CONTAINER_DOCONLY(= void) >
|
template <typename T, std::size_t Capacity, class Options BOOST_CONTAINER_DOCONLY(= void) >
|
||||||
class static_vector
|
class static_vector
|
||||||
: public vector<T, typename dtl::get_static_vector_allocator< T, Capacity, Options>::type>
|
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||||
|
: public vector< T
|
||||||
|
, typename dtl::get_static_vector_allocator< T, Capacity, Options>::type
|
||||||
|
, typename dtl::get_vector_opt_from_static_vector_opt<Options>::type
|
||||||
|
>
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||||
typedef typename dtl::get_static_vector_allocator< T, Capacity, Options>::type allocator_type;
|
typedef typename dtl::get_static_vector_allocator< T, Capacity, Options>::type allocator_type;
|
||||||
typedef vector<T, allocator_type > base_t;
|
typedef typename dtl::get_vector_opt_from_static_vector_opt<Options>::type options_type;
|
||||||
|
typedef vector<T, allocator_type, options_type> base_t;
|
||||||
|
|
||||||
BOOST_COPYABLE_AND_MOVABLE(static_vector)
|
BOOST_COPYABLE_AND_MOVABLE(static_vector)
|
||||||
|
|
||||||
|
@ -643,7 +643,7 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
|
|||||||
template<class AllocConvertible>
|
template<class AllocConvertible>
|
||||||
vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
|
vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
|
||||||
: allocator_type(boost::forward<AllocConvertible>(a))
|
: allocator_type(boost::forward<AllocConvertible>(a))
|
||||||
, m_size(initial_size) //Size is initialized here...
|
, m_size(static_cast<stored_size_type>(initial_size)) //Size is initialized here...
|
||||||
{
|
{
|
||||||
//... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
|
//... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
|
||||||
this->priv_first_allocation(initial_size);
|
this->priv_first_allocation(initial_size);
|
||||||
@ -652,7 +652,7 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
|
|||||||
//Constructor, does not throw
|
//Constructor, does not throw
|
||||||
vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
|
vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
|
||||||
: allocator_type()
|
: allocator_type()
|
||||||
, m_size(initial_size) //Size is initialized here...
|
, m_size(static_cast<stored_size_type>(initial_size)) //Size is initialized here...
|
||||||
{
|
{
|
||||||
//... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
|
//... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
|
||||||
this->priv_first_allocation(initial_size);
|
this->priv_first_allocation(initial_size);
|
||||||
|
@ -131,9 +131,49 @@ void test_throw_on_overflow()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Unsigned, class VectorType>
|
||||||
|
void test_stored_size_type_impl()
|
||||||
|
{
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
VectorType v;
|
||||||
|
typedef typename VectorType::size_type size_type;
|
||||||
|
typedef typename VectorType::value_type value_type;
|
||||||
|
size_type const max = Unsigned(-1);
|
||||||
|
v.resize(5);
|
||||||
|
v.resize(max);
|
||||||
|
BOOST_TEST_THROWS(v.resize(max+1), std::exception);
|
||||||
|
BOOST_TEST_THROWS(v.push_back(value_type(1)), std::exception);
|
||||||
|
BOOST_TEST_THROWS(v.insert(v.begin(), value_type(1)), std::exception);
|
||||||
|
BOOST_TEST_THROWS(v.emplace(v.begin(), value_type(1)),std::exception);
|
||||||
|
BOOST_TEST_THROWS(v.reserve(max+1), std::exception);
|
||||||
|
BOOST_TEST_THROWS(VectorType v2(max+1), std::exception);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Unsigned>
|
||||||
|
void test_stored_size_type()
|
||||||
|
{
|
||||||
|
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||||
|
using options_t = static_vector_options_t< stored_size<Unsigned> >;
|
||||||
|
#else
|
||||||
|
typedef typename static_vector_options
|
||||||
|
< stored_size<Unsigned> >::type options_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef static_vector<unsigned char, Unsigned(-1)> normal_static_vector_t;
|
||||||
|
|
||||||
|
{
|
||||||
|
typedef static_vector<unsigned char, Unsigned(-1), options_t> static_vector_t;
|
||||||
|
BOOST_CONTAINER_STATIC_ASSERT(sizeof(normal_static_vector_t) > sizeof(static_vector_t));
|
||||||
|
test_stored_size_type_impl<Unsigned, static_vector_t>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
test_alignment();
|
test_alignment();
|
||||||
test_throw_on_overflow();
|
test_throw_on_overflow();
|
||||||
|
test_stored_size_type<unsigned char>();
|
||||||
|
test_stored_size_type<unsigned short>();
|
||||||
return ::boost::report_errors();
|
return ::boost::report_errors();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user