![]() |
Home | Libraries | People | FAQ | More |
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:
set, multiset,
map and multimap
associative containers are implemented as binary search trees which offer
the needed complexity and stability guarantees required by the C++ standard
for associative containers.
Boost.Container offers the possibility to
configure at compile time some parameters of the binary search tree implementation.
This configuration is passed as the last template parameter and defined using
the utility class tree_assoc_options.
The following parameters can be configured:
tree_type).
By default these containers use a red-black tree but the user can use
other tree types:
optimize_size).
By default this option is activated and is only meaningful to red-black
and avl trees (in other cases, this option will be ignored). This option
will try to put rebalancing metadata inside the "parent" pointer
of the node if the pointer type has enough alignment. Usually, due to
alignment issues, the metadata uses the size of a pointer yielding to
four pointer size overhead per node, whereas activating this option usually
leads to 3 pointer size overhead. Although some mask operations must
be performed to extract data from this special "parent" pointer,
in several systems this option also improves performance due to the improved
cache usage produced by the node size reduction.
See the following example to see how tree_assoc_options
can be used to customize these containers:
#include <boost/container/set.hpp> //Make sure assertions are active #ifdef NDEBUG #undef NDEBUG #endif #include <cassert> int main () { using namespace boost::container; //First define several options //-------------------------------------------- // 'tree_type' option //-------------------------------------------- //This option specifies an AVL tree based associative container typedef tree_assoc_options< tree_type<avl_tree> >::type AVLTree; //This option specifies an Splay tree based associative container typedef tree_assoc_options< tree_type<splay_tree> >::type SplayTree; //Splay tree based multiset container typedef multiset<int, std::less<int>, new_allocator<int>, SplayTree> SplayMultiset; //AVLTree based set container typedef set<int, std::less<int>, new_allocator<int>, AVLTree> AvlSet; AvlSet avl_set; avl_set.insert(0); assert(avl_set.find(0) != avl_set.end()); SplayMultiset splay_mset; splay_mset.insert(2); splay_mset.insert(2); assert(splay_mset.count(2) == 2); //-------------------------------------------- // 'optimize_size' option //-------------------------------------------- //This option specifies an AVL tree based associative container //disabling node size optimization. typedef tree_assoc_options< tree_type<avl_tree> , optimize_size<false> >::type AVLTreeNoSizeOpt; //AVLTree based set container without size optimization typedef set<int, std::less<int>, new_allocator<int>, AVLTreeNoSizeOpt> AvlSetNoSizeOpt; AvlSetNoSizeOpt avl_set_no_szopt; avl_set_no_szopt.insert(1); avl_set_no_szopt.insert(1); assert(avl_set_no_szopt.count(1) == 1); return 0; }
The configuration for vector
is passed as the last template parameter and defined using the utility class
vector_options.
The following parameters can be configured:
growth_factor:
the growth policy of the vector. The rate at which the capacity grows
is implementation dependent and implementations choose exponential growth
in order to meet the amortized constant time requirements. A higher growth
factor will make it faster as it will require less data movement, but
it will have a greater memory impact (on average, more memory will be
unused). A user can provide a custom implementation of the growth factor
and some predefined policies are available: growth_factor_50,
growth_factor_60
(usually the default in Boost.Container) and growth_factor_100.
stored_size:
the type that will be used to store size-related parameters inside the
vector. Sometimes, when the maximum vector capacity to be used is much
less than std::size_t capacity, it may be beneficial
to use a smaller unsigned integer type to represent size() and capacity() values inside the vector, so that the
size of an empty vector object is minimized and cache performance is
possibly improved. See stored_size
for more details. Note that due to alignment issues, using a unsigned
type smaller than std::size_t to store size-related parameters might
not bring any size gains and will severely limit the maximum size of
the container.
See the following example to see how vector_options
can be used to customize vector:
#include <boost/container/vector.hpp> //Make sure assertions are active #ifdef NDEBUG #undef NDEBUG #endif #include <cassert> int main () { using namespace boost::container; //-------------------------------------------- // 'stored_size' option //-------------------------------------------- //This option specifies that a vector that will use "unsigned char" as //the type to store capacity or size internally. typedef vector_options< stored_size<unsigned char> >::type size_option_t; //Size-optimized vector is smaller than the default one. typedef vector<int, new_allocator<int>, size_option_t > size_optimized_vector_t; assert(( sizeof(size_optimized_vector_t) < sizeof(vector<int>) )); //Requesting capacity for more elements than representable by "unsigned char" //is an error in the size optimized vector. bool exception_thrown = false; try { size_optimized_vector_t v(256); } catch(...){ exception_thrown = true; } assert(exception_thrown == true); //-------------------------------------------- // 'growth_factor' option //-------------------------------------------- //This option specifies that a vector will increase its capacity 50% //each time the previous capacity was exhausted. typedef vector_options< growth_factor<growth_factor_50> >::type growth_50_option_t; //Fill the vector until full capacity is reached vector<int, new_allocator<int>, growth_50_option_t > growth_50_vector(5, 0); const std::size_t old_cap = growth_50_vector.capacity(); growth_50_vector.resize(old_cap); //Now insert an additional item and check the new buffer is 50% bigger growth_50_vector.push_back(1); assert(growth_50_vector.capacity() == old_cap*3/2); return 0; }
The configuration for static_vector
is passed as the last template parameter and defined using the utility class
static_vector_options.
The following parameters can be configured:
inplace_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.
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 overflowed, the
implementation calls to BOOST_ASSERT
and if that assertion does not throw or abort, undefined behavior is
triggered.
stored_size:
the type that will be used to store size-related parameters inside the
vector. See stored_size
option in Configurable
vector chapter and stored_size
for more details.
See the following example to see how static_vector_options
can be used to customize static_vector:
#include <boost/container/static_vector.hpp> //Make sure assertions are active #ifdef NDEBUG #undef NDEBUG #endif #include <cassert> int main () { using namespace boost::container; //-------------------------------------------- // 'inplace_alignment' option //-------------------------------------------- //This option specifies the desired alignment for value_type typedef static_vector_options< inplace_alignment<16u> >::type alignment_16_option_t; //Check 16 byte alignment option static_vector<int, 10, alignment_16_option_t > sv; assert(((std::size_t)sv.data() % 16u) == 0); //-------------------------------------------- // 'throw_on_overflow' option //-------------------------------------------- //This static_vector won't throw on overflow, for maximum performance typedef static_vector_options< throw_on_overflow<false> >::type no_throw_options_t; //Create static_vector with no throw on overflow static_vector<int, 10, no_throw_options_t > sv2; //-------------------------------------------- // 'stored_size' option //-------------------------------------------- //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; }
The configuration for small_vector
is passed as the last template parameter and defined using the utility class
small_vector_options.
The following parameters can be configured:
inplace_alignment:
the minimum alignment (in bytes) for the in-place storage used to build
the "small" number of elements. The alignment
of the dynamic memory must be provided by the allocator and it is not
affected by this option.
growth_factor:
the growth policy of the vector. See growth_factor
option in Configurable
vector chapter and growth_factor
for more details.
stored_size:
the type that will be used to store size-related parameters inside the
vector. See stored_size
option in Configurable
vector chapter and stored_size
for more details.
See the following example to see how small_vector_options
can be used to customize small_vector:
#include <boost/container/small_vector.hpp> //Make sure assertions are active #ifdef NDEBUG #undef NDEBUG #endif #include <cassert> int main () { using namespace boost::container; //-------------------------------------------- // 'inplace_alignment' option //-------------------------------------------- //This option specifies the desired alignment for the internal value_type typedef small_vector_options< inplace_alignment<16u> >::type alignment_16_option_t; //Check 16 byte alignment option small_vector<int, 10, void, alignment_16_option_t > sv; assert(((std::size_t)sv.data() % 16u) == 0); //-------------------------------------------- // 'growth_factor' option //-------------------------------------------- //This option specifies that a vector will increase its capacity 50% //each time the previous capacity was exhausted. typedef small_vector_options< growth_factor<growth_factor_50> >::type growth_50_option_t; //Fill the vector until full capacity is reached small_vector<int, 10, void, growth_50_option_t > growth_50_vector(10, 0); const std::size_t old_cap = growth_50_vector.capacity(); growth_50_vector.resize(old_cap); //Now insert an additional item and check the new buffer is 50% bigger growth_50_vector.push_back(1); assert(growth_50_vector.capacity() == old_cap*3/2); //-------------------------------------------- // 'stored_size' option //-------------------------------------------- //This option specifies that a vector that will use "unsigned char" as //the type to store capacity or size internally. typedef small_vector_options< stored_size<unsigned char> >::type size_option_t; //Size-optimized vector is smaller than the default one. typedef small_vector<int, 10, new_allocator<int>, size_option_t > size_optimized_vector_t; assert((sizeof(size_optimized_vector_t) < sizeof(small_vector<int, 10>))); return 0; }
The configuration for deque
/ segtor is passed
as the last template parameter and defined using the utility class deque_options and segtor_options respectively.
The following parameters can be configured:
Parameters that control the size of container's 'block''segment' (the container allocates contiguous chunks of elements, called 'blocks''segments'). Only one of these paratemers can be specified:
block_bytes/segment_bytes: the
number of bytes the container will allocate to store elements contiguously:
deque::get_block_size()
will return aproximately block_bytes/sizeof(value_type) / segment_bytes/sizeof(value_type). A value of zero means the default value.
block_size/segment_size: the number
of elements the container will allocate contiguously. If this option
is specified, deque::get_block_size()
will return the specified block_size/segment_size. A value of zero means
the default value.
stored_size:
the type that will be used to store size-related parameters inside the
vector. See stored_size
option in Configurable
vector chapter and stored_size
for more details.
See the following example to see how deque_options
can be used to customize deque:
#include <boost/container/deque.hpp> //Make sure assertions are active #ifdef NDEBUG #undef NDEBUG #endif #include <cassert> int main () { using namespace boost::container; //-------------------------------------------- // 'stored_size' option //-------------------------------------------- //This option specifies that a deque that will use "unsigned char" as //the type to store capacity or size internally. typedef deque_options< stored_size<unsigned char> >::type size_option_t; //Size-optimized deque is smaller than the default one. typedef deque<int, new_allocator<int>, size_option_t > size_optimized_deque_t; assert(( sizeof(size_optimized_deque_t) < sizeof(deque<int>) )); //Requesting capacity for more elements than representable by "unsigned char" //is an error in the size optimized deque. bool exception_thrown = false; try { size_optimized_deque_t v(256); } catch(...){ exception_thrown = true; } assert(exception_thrown == true); //-------------------------------------------- // 'block_size/segment_size' option //-------------------------------------------- //This option specifies the desired block size for deque typedef deque_options< block_size<128u> >::type block_128_option_t; //segment_size is an alias for block_size (an alias for block_size) typedef deque_options< segment_size<128u> >::type segment_128_option_t; //This deque will allocate blocks of 128 elements typedef deque<int, void, block_128_option_t > block_128_deque_t; assert(block_128_deque_t::get_block_size() == 128u); //This deque will allocate segments of 128 elements (an alias for block_size) typedef deque<int, void, segment_128_option_t > segment_128_deque_t; assert(segment_128_deque_t::get_block_size() == 128u); //-------------------------------------------- // 'block_bytes/segment_bytes' option //-------------------------------------------- //This option specifies the maximum block size for deque //in bytes typedef deque_options< block_bytes<1024u> >::type block_1024_bytes_option_t; //This option specifies the maximum segment size for deque //in bytes (an alias for block_bytes) typedef deque_options< segment_bytes<1024u> >::type segment_1024_bytes_option_t; //This deque will allocate blocks of 1024 bytes typedef deque<int, void, block_1024_bytes_option_t > block_1024_bytes_deque_t; assert(block_1024_bytes_deque_t::get_block_size() == 1024u/sizeof(int)); //This deque will allocate blocks of 1024 bytes (an alias for block_bytes) typedef deque<int, void, segment_1024_bytes_option_t > segment_1024_bytes_deque_t; assert(segment_1024_bytes_deque_t::get_block_size() == 1024u/sizeof(int)); return 0; }
See the following example to see how segtor_options
can be used to customize segtor:
#include <boost/container/segtor.hpp> //Make sure assertions are active #ifdef NDEBUG #undef NDEBUG #endif #include <cassert> int main () { using namespace boost::container; //-------------------------------------------- // 'stored_size' option //-------------------------------------------- //This option specifies that a segtor will use "unsigned char" as //the type to store capacity or size internally. typedef segtor_options< stored_size<unsigned char> >::type size_option_t; //Size-optimized segtor is smaller than the default one. typedef segtor<int, new_allocator<int>, size_option_t > size_optimized_segtor_t; assert(( sizeof(size_optimized_segtor_t) < sizeof(segtor<int>) )); //Requesting capacity for more elements than representable by "unsigned char" //is an error in the size optimized segtor. bool exception_thrown = false; try { size_optimized_segtor_t v(256); } catch(...){ exception_thrown = true; } assert(exception_thrown == true); //-------------------------------------------- // 'block_size/segment_size' option //-------------------------------------------- //This option specifies the desired block size for segtor typedef segtor_options< block_size<128u> >::type block_128_option_t; //segment_size is an alias for block_size (an alias for block_size) typedef segtor_options< segment_size<128u> >::type segment_128_option_t; //This segtor will allocate blocks of 128 elements typedef segtor<int, void, block_128_option_t > block_128_segtor_t; assert(block_128_segtor_t::get_block_size() == 128u); //This segtor will allocate segments of 128 elements (an alias for block_size) typedef segtor<int, void, segment_128_option_t > segment_128_segtor_t; assert(segment_128_segtor_t::get_block_size() == 128u); //-------------------------------------------- // 'block_bytes/segment_bytes' option //-------------------------------------------- //This option specifies the maximum block size for segtor //in bytes typedef segtor_options< block_bytes<1024u> >::type block_1024_bytes_option_t; //This option specifies the maximum segment size for segtor //in bytes (an alias for block_bytes) typedef segtor_options< segment_bytes<1024u> >::type segment_1024_bytes_option_t; //This segtor will allocate blocks of 1024 bytes typedef segtor<int, void, block_1024_bytes_option_t > block_1024_bytes_segtor_t; assert(block_1024_bytes_segtor_t::get_block_size() == 1024u/sizeof(int)); //This segtor will allocate blocks of 1024 bytes (an alias for block_bytes) typedef segtor<int, void, segment_1024_bytes_option_t > segment_1024_bytes_segtor_t; assert(segment_1024_bytes_segtor_t::get_block_size() == 1024u/sizeof(int)); return 0; }
The configuration for devector
is passed as the last template parameter and defined using the utility class
devector_options.
The following parameters can be configured:
growth_factor:
the growth policy of the vector. See growth_factor
option in Configurable
vector chapter and growth_factor
for more details.
stored_size:
the type that will be used to store size-related parameters inside the
vector. See stored_size
option in Configurable
vector chapter and stored_size
for more details.
relocate_on_XX:
load factor limit that will determine if new memory should be allocated
or elements should relocated inside existing memory, when the free space
is exhausted at one end of the container.
See the following example to see how devector_options
can be used to customize devector:
#include <boost/container/devector.hpp> //Make sure assertions are active #ifdef NDEBUG #undef NDEBUG #endif #include <cassert> int main () { using namespace boost::container; //-------------------------------------------- // 'stored_size' option //-------------------------------------------- //Specify that a devector will use "unsigned char" as the type to store size/capacity typedef devector_options< stored_size<unsigned char> >::type size_option_t; //Size-optimized devector is smaller than the default one. typedef devector<int, new_allocator<int>, size_option_t > size_optimized_devector_t; assert(( sizeof(size_optimized_devector_t) < sizeof(devector<int>) )); //Requesting capacity for more elements than representable by "unsigned char" is an error bool exception_thrown = false; try { size_optimized_devector_t v(256); } catch(...){ exception_thrown = true; } assert(exception_thrown == true); //-------------------------------------------- // 'growth_factor' option //-------------------------------------------- //Specify that a devector will increase its capacity 50% when reallocating typedef devector_options< growth_factor<growth_factor_50> >::type growth_50_option_t; //Fill the devector until full capacity is reached devector<int, new_allocator<int>, growth_50_option_t > growth_50_dv(5, 0); std::size_t old_cap = growth_50_dv.capacity(); growth_50_dv.resize(old_cap); //Now insert an additional item and check the new buffer is 50% bigger growth_50_dv.push_back(1); assert(growth_50_dv.capacity() == old_cap*3/2); //-------------------------------------------- // 'relocate_on' option //-------------------------------------------- //Specifies that a devector will not reallocate but relocate elements if the free space //at one end is exhausted and the total load factor is below the 66% threshold. typedef devector_options< relocate_on_66 >::type relocation_66_option_t; //Configure devector to have equal free space at both ends devector<int, new_allocator<int>, relocation_66_option_t > reloc_66_dv (16u, 16u, reserve_only_tag_t()); old_cap = reloc_66_dv.capacity(); const std::size_t front_free_cap = reloc_66_dv.front_free_capacity(); //Fill vector at the back end while (reloc_66_dv.back_free_capacity() > 0) reloc_66_dv.push_back(0); //Front free capacity is intact assert(reloc_66_dv.front_free_capacity() == front_free_cap); //Now insert new element, values should relocated to the middle as the //load factor is near 50% reloc_66_dv.push_back(0); assert(reloc_66_dv.capacity() == old_cap); assert(reloc_66_dv.front_free_capacity() < front_free_cap); //Fill the back end again while (reloc_66_dv.back_free_capacity() > 0) reloc_66_dv.push_back(1); //New insertion should reallocate as load factor is higher than 66% reloc_66_dv.push_back(-1); assert(reloc_66_dv.capacity() > old_cap); return 0; }
The configuration for basic_string
is passed as the last template parameter and defined using the utility class
string_options.
The following parameters can be configured:
growth_factor:
the growth policy of the vector. See growth_factor
option in Configurable
vector chapter and growth_factor
for more details.
stored_size:
the type that will be used to store size-related parameters inside the
vector. See stored_size
option in Configurable
vector chapter and stored_size
for more details. Note that the internal small string optimization buffer
might be reduced in size if a smaller than std::size_t
stored_size unsigned
type is used.
inline_chars:
the number of characters (excluding terminating null) that will be stored
inside basic_string (small
string optimization) before using dynamic allocation. Due to internal
data structure limitations, this value must be equal or less than 127.
The implementation will guarantee at least that number of characters
in the internal buffer, but it might be more depending on alignment issues
and the stored_size option.
See the following example to see how string_options
can be used to customize string_options:
#include <boost/container/string.hpp> //Make sure assertions are active #ifdef NDEBUG #undef NDEBUG #endif #include <cassert> int main () { using namespace boost::container; //-------------------------- // Option "stored_size" //-------------------------- //This option specifies that a string that will use "unsigned char" as //the type to store capacity or size internally. typedef string_options< stored_size<unsigned char> >::type size_option_t; //Size-optimized string is smaller than the default one. typedef basic_string<char, std::char_traits<char>, void, size_option_t > size_optimized_string_t; assert(( sizeof(size_optimized_string_t) < sizeof(basic_string<char>) )); //The internal small string optimization buffer is also smaller assert(( size_optimized_string_t().capacity() < basic_string<char>().capacity() )); //Requesting capacity for more elements than representable by half of the //"unsigned char" max (due to the need to a bit to indicate short/long representation) //minus 1 (due to the terminating null) is an error in the size optimized string. bool exception_thrown = false; try { size_optimized_string_t v(127, 'a'); } catch(...){ exception_thrown = true; } assert(exception_thrown == true); //-------------------------- // Option "inline_chars" //-------------------------- //This option specifies the capacity of the internally stored buffer //The maximum value due to internal data organization is 127 chars typedef string_options< inline_chars<100> >::type inline_chars_option_t; typedef basic_string<char, std::char_traits<char>, void, inline_chars_option_t > inline100_string_t; //The size of the object will grow accordingly assert(( sizeof(inline100_string_t) > sizeof(basic_string<char>) )); assert(( sizeof(inline100_string_t) > 100 )); //Internal capacity will be at least the specified one assert((inline100_string_t().capacity() >= 100)); //-------------------------- // Option "growth_factor" //-------------------------- //This option specifies that a string will increase its capacity 50% //each time the previous capacity was exhausted. typedef string_options< growth_factor<growth_factor_50> >::type growth_50_option_t; //Fill the string until full capacity is reached basic_string<char, std::char_traits<char>, void, growth_50_option_t > growth_50_string(5, 0); const std::size_t old_cap = growth_50_string.capacity(); growth_50_string.resize(old_cap); //Now insert an additional item and check the new buffer is aproximately //50% bigger (rounding due to the null terminator might round down) growth_50_string.push_back(1); assert(growth_50_string.capacity() == old_cap*3/2); return 0; }