Skip to content

Commit af58c7d

Browse files
committed
Added stored_size option to small_vector
1 parent 13603d7 commit af58c7d

File tree

5 files changed

+81
-8
lines changed

5 files changed

+81
-8
lines changed

doc/container.qbk

+9-1
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,12 @@ the last template parameter and defined using the utility class
803803
[classref boost::container::growth_factor_60 growth_factor_60] and
804804
[classref boost::container::growth_factor_50 growth_factor_100].
805805

806+
* [classref boost::container::stored_size stored_size]: the type that will be used to store size-related
807+
parameters inside of the vector. Sometimes, when the maximum capacity to be used is much less than the
808+
theoretical maximum that a vector can hold, it's interesting to use smaller unsigned integer types to represent
809+
`size()` and `capacity()` inside vector, so that the size of an empty vector is minimized and cache
810+
performance might be improved. See [classref boost::container::stored_size stored_size] for more details.
811+
806812
See the following example to see how [classref boost::container::small_vector_options small_vector_options] can be
807813
used to customize `small_vector`:
808814

@@ -1417,7 +1423,9 @@ use [*Boost.Container]? There are several reasons for that:
14171423

14181424
[section:release_notes_boost_1_87_00 Boost 1.87 Release]
14191425

1420-
* Added [classref boost::container::stored_size stored_size] option to [classref boost::container::static_vector static_vector].
1426+
* Added [classref boost::container::stored_size stored_size] option to
1427+
[classref boost::container::static_vector static_vector] and
1428+
[classref boost::container::small_vector small_vector].
14211429

14221430
* Fixed bugs/issues:
14231431
* [@https://github.com/boostorg/container/issues/261 GitHub #261: ['"End iterators are not dereferencable"]].

example/doc_custom_small_vector.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ int main ()
4141
growth_50_vector.push_back(1);
4242
assert(growth_50_vector.capacity() == old_cap*3/2);
4343

44+
//This option specifies that a vector that will use "unsigned char" as
45+
//the type to store capacity or size internally.
46+
typedef small_vector_options< stored_size<unsigned char> >::type size_option_t;
47+
48+
//Size-optimized vector is smaller than the default one.
49+
typedef small_vector<int, 10, new_allocator<int>, size_option_t > size_optimized_vector_t;
50+
assert((sizeof(size_optimized_vector_t) < sizeof(small_vector<int, 10>)));
51+
4452
return 0;
4553
}
4654
//]

include/boost/container/options.hpp

+10-5
Original file line numberDiff line numberDiff line change
@@ -359,20 +359,23 @@ BOOST_INTRUSIVE_OPTION_CONSTANT(inplace_alignment, std::size_t, Alignment, inpla
359359

360360
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
361361

362-
template<class GrowthType, std::size_t InplaceAlignment>
362+
template<class GrowthType, std::size_t InplaceAlignment, class StoredSizeType>
363363
struct small_vector_opt
364364
{
365-
typedef GrowthType growth_factor_type;
365+
typedef GrowthType growth_factor_type;
366366
BOOST_STATIC_CONSTEXPR std::size_t inplace_alignment = InplaceAlignment;
367+
typedef StoredSizeType stored_size_type;
367368
};
368369

369-
typedef small_vector_opt<void, 0u> small_vector_null_opt;
370+
typedef small_vector_opt<void, 0u, void> small_vector_null_opt;
370371

371372
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
372373

373374
//! Helper metafunction to combine options into a single type to be used
374375
//! by \c boost::container::small_vector.
375-
//! Supported options are: \c boost::container::growth_factor and \c boost::container::inplace_alignment
376+
//! Supported options are: \c boost::container::growth_factor,
377+
//! \c boost::container::inplace_alignment and
378+
//! \c boost::container::stored_size.
376379
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
377380
template<class ...Options>
378381
#else
@@ -390,7 +393,9 @@ struct small_vector_options
390393
#endif
391394
>::type packed_options;
392395
typedef small_vector_opt< typename packed_options::growth_factor_type
393-
, packed_options::inplace_alignment> implementation_defined;
396+
, packed_options::inplace_alignment
397+
, typename packed_options::stored_size_type
398+
> implementation_defined;
394399
/// @endcond
395400
typedef implementation_defined type;
396401
};

include/boost/container/small_vector.hpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ struct get_vopt_from_svopt
6969
: get_small_vector_opt<Options>::type
7070
{
7171
typedef typename get_small_vector_opt<Options>::type options_t;
72-
typedef vector_opt< typename options_t::growth_factor_type, void> type;
72+
typedef vector_opt< typename options_t::growth_factor_type
73+
, typename options_t::stored_size_type
74+
> type;
7375
};
7476

7577
template<>
@@ -340,9 +342,11 @@ struct small_vector_storage<T, 0u, Alignment>
340342
//!
341343
template <class T, class SecAlloc, class Options>
342344
class small_vector_base
345+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
343346
: public dtl::vector_for_small_vector<T, SecAlloc, Options>::type
347+
#endif
344348
{
345-
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKEDVECTOR
349+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
346350
public:
347351
//Make it public as it will be inherited by small_vector and container
348352
//must have this public member

test/small_vector_options_test.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//
99
//////////////////////////////////////////////////////////////////////////////
1010
#include <boost/container/small_vector.hpp>
11+
#include <boost/container/allocator.hpp>
1112
#include <boost/core/lightweight_test.hpp>
1213
#include <boost/assert.hpp>
1314
using namespace boost::container;
@@ -100,11 +101,58 @@ void test_growth_factor_100()
100101
BOOST_TEST(new_capacity == 2*old_capacity);
101102
}
102103

104+
template<class Unsigned, class VectorType>
105+
void test_stored_size_type_impl()
106+
{
107+
#ifndef BOOST_NO_EXCEPTIONS
108+
VectorType v;
109+
typedef typename VectorType::size_type size_type;
110+
typedef typename VectorType::value_type value_type;
111+
size_type const max = Unsigned(-1);
112+
v.resize(5);
113+
v.resize(max);
114+
BOOST_TEST_THROWS(v.resize(max+1), std::exception);
115+
BOOST_TEST_THROWS(v.push_back(value_type(1)), std::exception);
116+
BOOST_TEST_THROWS(v.insert(v.begin(), value_type(1)), std::exception);
117+
BOOST_TEST_THROWS(v.emplace(v.begin(), value_type(1)),std::exception);
118+
BOOST_TEST_THROWS(v.reserve(max+1), std::exception);
119+
BOOST_TEST_THROWS(VectorType v2(max+1), std::exception);
120+
#endif
121+
}
122+
123+
template<class Unsigned>
124+
void test_stored_size_type()
125+
{
126+
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
127+
using options_t = small_vector_options_t< stored_size<Unsigned> >;
128+
#else
129+
typedef typename small_vector_options
130+
< stored_size<Unsigned> >::type options_t;
131+
#endif
132+
133+
typedef small_vector<unsigned char, Unsigned(-1)> normal_small_vector_t;
134+
135+
//Test first with a typical allocator
136+
{
137+
typedef small_vector<unsigned char, Unsigned(-1), new_allocator<unsigned char>, options_t> small_vector_t;
138+
test_stored_size_type_impl<Unsigned, small_vector_t>();
139+
BOOST_CONTAINER_STATIC_ASSERT(sizeof(normal_small_vector_t) > sizeof(small_vector_t));
140+
}
141+
//Test with a V2 allocator
142+
{
143+
typedef small_vector<unsigned char, Unsigned(-1), allocator<unsigned char>, options_t> small_vector_t;
144+
test_stored_size_type_impl<Unsigned, small_vector_t>();
145+
BOOST_CONTAINER_STATIC_ASSERT(sizeof(normal_small_vector_t) > sizeof(small_vector_t));
146+
}
147+
}
148+
103149
int main()
104150
{
105151
test_alignment();
106152
test_growth_factor_50();
107153
test_growth_factor_60();
108154
test_growth_factor_100();
155+
test_stored_size_type<unsigned char>();
156+
test_stored_size_type<unsigned short>();
109157
return ::boost::report_errors();
110158
}

0 commit comments

Comments
 (0)