- Add configuration options to vector

- Cleanup tree configuration options
This commit is contained in:
Ion Gaztañaga
2017-12-10 23:33:41 +01:00
parent 82abe673fc
commit 2802a1f50d
26 changed files with 1122 additions and 511 deletions

View File

@ -40,7 +40,8 @@ doxygen autodoc
\"BOOST_RV_REF_END_IF_CXX11=&&\" \\
\"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\
\"BOOST_FWD_REF(a)=a &&\" \\
\"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template<TYPE VALUE> struct OPTION_NAME{};\" \\
\"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template<TYPE VALUE> struct OPTION_NAME{};\" \\
\"BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) = template<class TYPE> struct OPTION_NAME{};\" \\
\"BOOST_CONTAINER_DOC1ST(T1, T2)=T1\" \\
\"BOOST_CONTAINER_DOCIGN(T) \"\\
\"BOOST_CONTAINER_DOCONLY(T)=T\"\\

View File

@ -8,7 +8,7 @@
[library Boost.Container
[quickbook 1.5]
[authors [Gaztanaga, Ion]]
[copyright 2009-2015 Ion Gaztanaga]
[copyright 2009-2017 Ion Gaztanaga]
[id container]
[dirname container]
[purpose Containers library]
@ -31,10 +31,13 @@ that don't comply with the latest C++ standard.
In short, what does [*Boost.Container] offer?
* Move semantics are implemented, including move emulation for pre-C++11 compilers.
* New advanced features (e.g. placement insertion, recursive containers) are present.
* Emplacement and move semantics are implemented, including emulation for pre-C++11 compilers.
* Polymorphic allocators and memory resources, including implementation and emulation for pre-C++17 compilers
* New advanced features (e.g. recursive containers, configuration options for containers) are present.
* Containers support stateful allocators and are compatible with [*Boost.Interprocess]
(they can be safely placed in shared memory).
* Users obtain a more uniform performance across all plataforms,
including [link container.main_features.scary_iterators SCARY iterators].
* The library offers new useful containers:
* [classref boost::container::flat_map flat_map],
[classref boost::container::flat_set flat_set],
@ -44,6 +47,12 @@ In short, what does [*Boost.Container] offer?
searches.
* [classref boost::container::stable_vector stable_vector]: a std::list and std::vector hybrid
container: vector-like random-access iterators and list-like iterator stability in insertions and erasures.
* [classref boost::container::static_vector static_vector ]: a vector-like container that internally embeds
(statically allocates) all needed memory up to the maximum capacity. Maximum capacity can't be increased and
it's specified at compile time.
* [classref boost::container::small_vector small_vector ]: a vector-like container that internally embeds
(statically allocates) a minimum amount of memory, but dynamically allocates elements when capacity
has to be increased. This minimum capacity is specified at compile time.
* [classref boost::container::slist slist]: the classic pre-standard singly linked list implementation
offering constant-time `size()`. Note that C++11 `forward_list` has no `size()`.
@ -159,9 +168,11 @@ unless specifically allowed for that component]].
Fortunately all [*Boost.Container] containers except
[classref boost::container::static_vector static_vector] and
[classref boost::container::small_vector small_vector] and
[classref boost::container::basic_string basic_string] are designed to support incomplete types.
[classref boost::container::static_vector static_vector] is special because
it statically allocates memory for `value_type` and this requires complete types and
[classref boost::container::static_vector static_vector] and
[classref boost::container::small_vector small_vector] are special because
they statically allocates memory for `value_type` and this requires complete types.
[classref boost::container::basic_string basic_string] implements Small String Optimization which
also requires complete types.
@ -533,7 +544,7 @@ stateful allocators, etc.
[endsect]
[section:extended_functionality Extended functionality]
[section:extended_functionality Extended functionality: Basic extensions]
[section:default_initialialization Default initialization for vector-like containers]
@ -569,46 +580,6 @@ times.
[endsect]
[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::map map] and [classref boost::container::multimap 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
[classref boost::container::tree_assoc_options tree_assoc_options].
The following parameters can be configured:
* The underlying [*tree implementation] type ([classref boost::container::tree_type tree_type]).
By default these containers use a red-black tree but the user can use other tree types:
* [@http://en.wikipedia.org/wiki/Red%E2%80%93black_tree Red-Black Tree]
* [@http://en.wikipedia.org/wiki/Avl_trees AVL tree]
* [@http://en.wikipedia.org/wiki/Scapegoat_tree Scapegoat tree]. In this case Insertion and Deletion
are amortized O(log n) instead of O(log n).
* [@http://en.wikipedia.org/wiki/Splay_tree Splay tree]. In this case Searches, Insertions and Deletions
are amortized O(log n) instead of O(log n).
* Whether the [*size saving] mechanisms are used to implement the tree nodes
([classref boost::container::optimize_size 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 [classref boost::container::tree_assoc_options tree_assoc_options] can be
used to customize these containers:
[import ../example/doc_custom_tree.cpp]
[doc_custom_tree]
[endsect]
[section:constant_time_range_splice Constant-time range splice for `(s)list`]
In the first C++ standard `list::size()` was not required to be constant-time,
@ -647,7 +618,81 @@ then the operation is constant time, even with an O(1) size.
[endsect]
[section:extended_allocators Extended allocators]
[endsect]
[section:configurable_containers Extended functionality: Configurable 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::map map] and [classref boost::container::multimap 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
[classref boost::container::tree_assoc_options tree_assoc_options]. The following parameters can be configured:
* The underlying [*tree implementation] type ([classref boost::container::tree_type tree_type]).
By default these containers use a red-black tree but the user can use other tree types:
* [@http://en.wikipedia.org/wiki/Red%E2%80%93black_tree Red-Black Tree]
* [@http://en.wikipedia.org/wiki/Avl_trees AVL tree]
* [@http://en.wikipedia.org/wiki/Scapegoat_tree Scapegoat tree]. In this case Insertion and Deletion
are amortized O(log n) instead of O(log n).
* [@http://en.wikipedia.org/wiki/Splay_tree Splay tree]. In this case Searches, Insertions and Deletions
are amortized O(log n) instead of O(log n).
* Whether the [*size saving] mechanisms are used to implement the tree nodes
([classref boost::container::optimize_size 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 [classref boost::container::tree_assoc_options tree_assoc_options] can be
used to customize these containers:
[import ../example/doc_custom_tree.cpp]
[doc_custom_tree]
[endsect]
[section:configurable_vectors Configurable vectors]
[*Boost.Container] offers the possibility to configure at compile time some parameters of
[classref boost::container::vector vector] implementation. This configuration is passed as
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::growth_factor growth_factor]: the growth policy of the vector.
The rate at which the capacity of a vector grows is implementation dependent and
implementations choose exponential growth in order to meet the amortized constant time requirement for push_back.
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 it's own implementation and some predefined
policies are available: [classref boost::container::growth_factor_50 growth_factor_50],
[classref boost::container::growth_factor_60 growth_factor_60] and
[classref boost::container::growth_factor_50 growth_factor_100].
* [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 maximum capacity to be used is much less than the
theoretical maximum that a vector can hold, it's interesting to use smaller unsigned integer types to represent
`size()` and `capacity()` inside 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::vector_options vector_options] can be
used to customize `vector` container:
[import ../example/doc_custom_vector.cpp]
[doc_custom_vector]
[endsect]
[endsect]
[section:extended_allocators Extended functionality: Extended allocators]
Many C++ programmers have ever wondered where does good old realloc fit in C++. And that's a good question.
Could we improve [classref boost::container::vector vector] performance using memory expansion mechanisms
@ -700,7 +745,7 @@ Use them simply specifying the new allocator in the corresponding template argum
[endsect]
[section:polymorphic_memory_resources Polymorphic Memory Resources ]
[section:polymorphic_memory_resources Extended Functionality: Polymorphic Memory Resources ]
The document
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html C++ Extensions for Library Fundamentals (Final draft: N4480)]
@ -818,31 +863,6 @@ type-erasured allocator-capable classes even in C++03 compilers.
[endsect]
[/
/a__section:previous_element_slist Previous element for slist__a
/
/The C++11 `std::forward_list` class implement a singly linked list, similar to `slist`, and these
/containers only offer forward iterators and implement insertions and splice operations that operate with ranges
/to be inserted ['after] that position. In those cases, sometimes it's interesting to obtain an iterator pointing
/to the previous element of another element. This operation can be implemented
/
/a__endsect__a
]
[/
/a__section:get_stored_allocator Obtain stored allocator__a
/
/STL containers offer a `get_allocator()` member to obtain a copy of the allocator that
/the container is using to allocate and construct elements. For performance reasons, some
/applications need o
/
/http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html
/
/a__endsect__a
/]
[endsect]
[section:Cpp11_conformance C++11/C++14 Conformance]
[*Boost.Container] aims for full C++11 conformance except reasoned deviations,
@ -1212,6 +1232,13 @@ use [*Boost.Container]? There are several reasons for that:
[section:release_notes Release Notes]
[section:release_notes_boost_1_67_00 Boost 1.67 Release]
* ['vector] can now have options, using [classref boost::container::vector_options vector_options].
The growth factor and the stored size type can be specified.
[endsect]
[section:release_notes_boost_1_66_00 Boost 1.66 Release]
* ['flat_[multi]map/set] can now work as container adaptors, as proposed in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0429r1.pdf P0429R1].
@ -1362,7 +1389,7 @@ use [*Boost.Container]? There are several reasons for that:
* Added DlMalloc-based [link container.extended_functionality.extended_allocators Extended Allocators].
* [link container.extended_functionality.configurable_tree_based_associative_containers Improved configurability]
* [link container.extended_functionality.configurable_containers.configurable_tree_based_associative_containers Improved configurability]
of tree-based ordered associative containers. AVL, Scapegoat and Splay trees are now available
to implement [classref boost::container::set set], [classref boost::container::multiset multiset],
[classref boost::container::map map] and [classref boost::container::multimap multimap].

View File

@ -0,0 +1,54 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//[doc_custom_vector
#include <boost/container/vector.hpp>
#include <boost/static_assert.hpp>
//Make sure assertions are active
#ifdef NDEBUG
#undef NDEBUG
#endif
#include <cassert>
int main ()
{
using namespace boost::container;
//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;
BOOST_STATIC_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);
//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;
}
//]

View File

@ -88,23 +88,14 @@ namespace boost{ namespace container{ namespace pmr{
namespace boost {
namespace container {
//! Enumeration used to configure ordered associative containers
//! with a concrete tree implementation.
enum tree_type_enum
{
red_black_tree,
avl_tree,
scapegoat_tree,
splay_tree
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template<class T>
class new_allocator;
template <class T
,class Allocator = new_allocator<T> >
,class Allocator = new_allocator<T>
,class Options = void>
class vector;
template <class T
@ -130,35 +121,30 @@ template <class T
,class Allocator = new_allocator<T> >
class slist;
template<tree_type_enum TreeType, bool OptimizeSize>
struct tree_opt;
typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
template <class Key
,class Compare = std::less<Key>
,class Allocator = new_allocator<Key>
,class Options = tree_assoc_defaults >
,class Options = void>
class set;
template <class Key
,class Compare = std::less<Key>
,class Allocator = new_allocator<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
class multiset;
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = new_allocator<std::pair<const Key, T> >
,class Options = tree_assoc_defaults >
,class Options = void >
class map;
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = new_allocator<std::pair<const Key, T> >
,class Options = tree_assoc_defaults >
,class Options = void >
class multimap;
template <class Key
@ -246,13 +232,6 @@ class synchronized_pool_resource;
} //namespace pmr {
#else
//! Default options for tree-based associative containers
//! - tree_type<red_black_tree>
//! - optimize_size<true>
typedef implementation_defined tree_assoc_defaults;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! Type used to tag that the input range is

View File

@ -108,6 +108,12 @@ namespace boost {
namespace container {
namespace dtl {
///////////////////////////////////////
//
// Helper functions to merge elements
//
///////////////////////////////////////
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
template<class SequenceContainer, class Iterator, class Compare>
@ -118,23 +124,25 @@ BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal_non_merge_member
void aux_flat_tree_merge_equal_non_merge_member //is_contiguous_container == true
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
{
typedef typename SequenceContainer::iterator iterator;
typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::size_type size_type;
iterator const it = dest.insert( dest.end(), first, last );
value_type *const braw = boost::movelib::iterator_to_raw_pointer(dest.begin());
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
value_type *const sraw = boost::movelib::iterator_to_raw_pointer(dest.begin()+dest.size());
boost::movelib::adaptive_sort(iraw, eraw, comp, sraw, dest.capacity());
boost::movelib::adaptive_merge(braw, iraw, eraw, comp, sraw, dest.capacity()- dest.size());
value_type *const sraw = boost::movelib::iterator_to_raw_pointer(dest.begin())+dest.size();
size_type const sraw_size = dest.capacity()- dest.size();
boost::movelib::adaptive_sort(iraw, eraw, comp, sraw, sraw_size);
boost::movelib::adaptive_merge(braw, iraw, eraw, comp, sraw, sraw_size);
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal_non_merge_member
void aux_flat_tree_merge_equal_non_merge_member //is_contiguous_container == false
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
{
typedef typename SequenceContainer::iterator iterator;
@ -145,22 +153,22 @@ BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal_non_merge_member
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal //has_merge_unique == false
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
{
(flat_tree_merge_equal_non_merge_member)( dest, first, last, comp
, dtl::bool_<is_contiguous_container<SequenceContainer>::value>());
(aux_flat_tree_merge_equal_non_merge_member)
( dest, first, last, comp, dtl::bool_<is_contiguous_container<SequenceContainer>::value>());
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == true
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
{
dest.merge_unique(first, last, comp);
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == false
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
{
(flat_tree_merge_equal)(dest, first, last, comp, dtl::false_());
@ -170,7 +178,7 @@ BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique
template<class SequenceContainer, class Iterator>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
flat_tree_index_of
flat_tree_index_of // has_index_of == true
(SequenceContainer& cont, Iterator p, dtl::true_)
{
return cont.index_of(p);
@ -178,7 +186,7 @@ BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
template<class SequenceContainer, class Iterator>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
flat_tree_index_of
flat_tree_index_of // has_index_of == false
(SequenceContainer& cont, Iterator p, dtl::false_)
{
typedef typename SequenceContainer::size_type size_type;
@ -187,7 +195,7 @@ BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
template<class Iterator, class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE Iterator
flat_tree_nth
flat_tree_nth // has_nth == true
(SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::true_)
{
return cont.nth(n);
@ -195,7 +203,7 @@ BOOST_CONTAINER_FORCEINLINE Iterator
template<class Iterator, class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE Iterator
flat_tree_nth
flat_tree_nth // has_nth == false
(SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::false_)
{
return cont.begin()+ n;
@ -203,7 +211,7 @@ BOOST_CONTAINER_FORCEINLINE Iterator
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::stored_allocator_type &
flat_tree_get_stored_allocator
flat_tree_get_stored_allocator // has_get_stored_allocator == true
(SequenceContainer& cont, dtl::true_)
{
return cont.get_stored_allocator();
@ -211,7 +219,7 @@ BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::stored_allocator_type &
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE const typename SequenceContainer::stored_allocator_type &
flat_tree_get_stored_allocator
flat_tree_get_stored_allocator // has_get_stored_allocator == true
(const SequenceContainer& cont, dtl::true_)
{
return cont.get_stored_allocator();
@ -219,14 +227,15 @@ BOOST_CONTAINER_FORCEINLINE const typename SequenceContainer::stored_allocator_t
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::allocator_type
flat_tree_get_stored_allocator
flat_tree_get_stored_allocator // has_get_stored_allocator == false
(SequenceContainer& cont, dtl::false_)
{
return cont.get_allocator();
}
template<class SequenceContainer, class Compare>
void flat_tree_adopt_sequence_equal(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
void flat_tree_adopt_sequence_equal // is_contiguous_container == true
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
{
tseq.clear();
boost::movelib::adaptive_sort
@ -239,14 +248,16 @@ void flat_tree_adopt_sequence_equal(SequenceContainer &tseq, BOOST_RV_REF(Sequen
}
template<class SequenceContainer, class Compare>
void flat_tree_adopt_sequence_equal(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
void flat_tree_adopt_sequence_equal // is_contiguous_container == false
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
{
boost::movelib::adaptive_sort(seq.begin(), seq.end(), comp);
tseq = boost::move(seq);
}
template<class SequenceContainer, class Compare>
void flat_tree_adopt_sequence_unique(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
void flat_tree_adopt_sequence_unique// is_contiguous_container == true
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
{
boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin())
@ -261,7 +272,8 @@ void flat_tree_adopt_sequence_unique(SequenceContainer &tseq, BOOST_RV_REF(Seque
}
template<class SequenceContainer, class Compare>
void flat_tree_adopt_sequence_unique(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
void flat_tree_adopt_sequence_unique// is_contiguous_container == false
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
{
boost::movelib::adaptive_sort(seq.begin(), seq.end(), comp);
seq.erase(boost::movelib::unique
@ -270,32 +282,38 @@ void flat_tree_adopt_sequence_unique(SequenceContainer &tseq, BOOST_RV_REF(Seque
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE void
BOOST_CONTAINER_FORCEINLINE void // has_reserve == true
flat_tree_reserve(SequenceContainer &tseq, typename SequenceContainer::size_type cap, dtl::true_)
{
tseq.reserve(cap);
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE void
BOOST_CONTAINER_FORCEINLINE void // has_reserve == false
flat_tree_reserve(SequenceContainer &, typename SequenceContainer::size_type, dtl::false_)
{
}
template<class SequenceContainer>
template<class SequenceContainer> // has_capacity == true
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
flat_tree_capacity(const SequenceContainer &tseq, dtl::true_)
{
return tseq.capacity();
}
template<class SequenceContainer>
template<class SequenceContainer> // has_capacity == false
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
flat_tree_capacity(const SequenceContainer &tseq, dtl::false_)
{
return tseq.size();
}
///////////////////////////////////////
//
// flat_tree_value_compare
//
///////////////////////////////////////
template<class Compare, class Value, class KeyOfValue>
class flat_tree_value_compare
: private Compare
@ -324,19 +342,12 @@ class flat_tree_value_compare
Compare &get_comp()
{ return *this; }
};
/*
template<class Pointer>
struct get_flat_tree_iterators
{
typedef typename boost::container::dtl::
vec_iterator<Pointer, false> iterator;
typedef typename boost::container::dtl::
vec_iterator<Pointer, true > const_iterator;
typedef boost::container::reverse_iterator<iterator> reverse_iterator;
typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
};
*/
///////////////////////////////////////
//
// select_container_type
//
///////////////////////////////////////
template < class Value, class AllocatorOrContainer
, bool = boost::container::dtl::is_container<AllocatorOrContainer>::value >
struct select_container_type
@ -350,6 +361,12 @@ struct select_container_type<Value, AllocatorOrContainer, false>
typedef boost::container::vector<Value, AllocatorOrContainer> type;
};
///////////////////////////////////////
//
// flat_tree
//
///////////////////////////////////////
template <class Value, class KeyOfValue,
class Compare, class AllocatorOrContainer>
class flat_tree

View File

@ -23,52 +23,54 @@
// container/detail
#include <boost/container/detail/min_max.hpp>
#include <boost/static_assert.hpp>
namespace boost {
namespace container {
namespace dtl {
enum NextCapacityOption { NextCapacityDouble, NextCapacity60Percent };
template<class SizeType, NextCapacityOption Option>
struct next_capacity_calculator;
template<class SizeType>
struct next_capacity_calculator<SizeType, NextCapacityDouble>
template<unsigned Minimum, unsigned Numerator, unsigned Denominator>
struct grow_factor_ratio
{
static SizeType get(const SizeType max_size
,const SizeType capacity
,const SizeType n)
BOOST_STATIC_ASSERT(Numerator > Denominator);
BOOST_STATIC_ASSERT(Numerator < 100);
BOOST_STATIC_ASSERT(Denominator < 100);
BOOST_STATIC_ASSERT(Denominator == 1 || (0 != Numerator % Denominator));
template<class SizeType>
SizeType operator()(const SizeType cur_cap, const SizeType add_min_cap, const SizeType max_cap) const
{
const SizeType remaining = max_size - capacity;
if ( remaining < n )
boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
const SizeType additional = max_value(n, capacity);
return ( remaining < additional ) ? max_size : ( capacity + additional );
}
};
const SizeType overflow_limit = ((SizeType)-1) / Numerator;
template<class SizeType>
struct next_capacity_calculator<SizeType, NextCapacity60Percent>
{
static SizeType get(const SizeType max_size
,const SizeType capacity
,const SizeType n)
{
const SizeType remaining = max_size - capacity;
if ( remaining < n )
boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
const SizeType m3 = max_size/3;
SizeType new_cap = 0;
if (capacity < m3)
return capacity + max_value(3*(capacity+1)/5, n);
if (capacity < m3*2)
return capacity + max_value((capacity+1)/2, n);
return max_size;
if(cur_cap <= overflow_limit){
new_cap = cur_cap * Numerator / Denominator;
}
else if(Denominator == 1 || (SizeType(new_cap = cur_cap) / Denominator) > overflow_limit){
new_cap = (SizeType)-1;
}
else{
new_cap *= Numerator;
}
return max_value(SizeType(Minimum), max_value(cur_cap+add_min_cap, min_value(max_cap, new_cap)));
}
};
} //namespace dtl {
struct growth_factor_50
: dtl::grow_factor_ratio<0, 3, 2>
{};
struct growth_factor_60
: dtl::grow_factor_ratio<0, 8, 5>
{};
struct growth_factor_100
: dtl::grow_factor_ratio<0, 2, 1>
{};
} //namespace container {
} //namespace boost {

View File

@ -429,24 +429,39 @@ struct key_node_compare
{ return this->key_comp()(key_of_value()(nonkey1.get_data()), key_of_value()(nonkey2.get_data())); }
};
template <class T, class KeyOfValue,
class Compare, class Allocator,
class Options = tree_assoc_defaults>
template<class Options>
struct get_tree_opt
{
typedef Options type;
};
template<>
struct get_tree_opt<void>
{
typedef tree_assoc_defaults type;
};
template <class T, class KeyOfValue, class Compare, class Allocator, class Options>
class tree
: public dtl::node_alloc_holder
< Allocator
, typename dtl::intrusive_tree_type
< Allocator, tree_value_compare
<typename allocator_traits<Allocator>::pointer, Compare, KeyOfValue>
, Options::tree_type, Options::optimize_size>::type
, get_tree_opt<Options>::type::tree_type
, get_tree_opt<Options>::type::optimize_size
>::type
>
{
typedef tree_value_compare
< typename allocator_traits<Allocator>::pointer
, Compare, KeyOfValue> ValComp;
typedef typename get_tree_opt<Options>::type options_type;
typedef typename dtl::intrusive_tree_type
< Allocator, ValComp, Options::tree_type
, Options::optimize_size>::type Icont;
< Allocator, ValComp
, options_type::tree_type
, options_type::optimize_size
>::type Icont;
typedef dtl::node_alloc_holder
<Allocator, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
@ -461,7 +476,7 @@ class tree
typedef typename Icont::const_iterator iconst_iterator;
typedef dtl::allocator_destroyer<NodeAlloc> Destroyer;
typedef typename AllocHolder::alloc_version alloc_version;
typedef intrusive_tree_proxy<Options::tree_type> intrusive_tree_proxy_t;
typedef intrusive_tree_proxy<options_type::tree_type> intrusive_tree_proxy_t;
BOOST_COPYABLE_AND_MOVABLE(tree)

View File

@ -0,0 +1,36 @@
#ifndef BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP
#define BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2017-2017. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
//Functors for member algorithm defaults
template<class ValueType>
struct value_less
{
bool operator()(const ValueType &a, const ValueType &b) const
{ return a < b; }
};
template<class ValueType>
struct value_equal
{
bool operator()(const ValueType &a, const ValueType &b) const
{ return a == b; }
};
#endif //BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP

View File

@ -33,6 +33,7 @@
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/value_functors.hpp>
// move
#include <boost/move/utility_core.hpp>
#include <boost/move/iterator.hpp>
@ -1204,7 +1205,7 @@ class list
//! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
void unique()
{ this->unique(value_equal()); }
{ this->unique(value_equal_t()); }
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that satisfy some binary predicate from the list.
@ -1234,7 +1235,7 @@ class list
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
void merge(list &x)
{ this->merge(x, value_less()); }
{ this->merge(x, value_less_t()); }
//! <b>Requires</b>: The lists x and *this must be distinct.
//!
@ -1300,7 +1301,7 @@ class list
//! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
//! is the list's size.
void sort()
{ this->sort(value_less()); }
{ this->sort(value_less_t()); }
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
//! The sort is stable, that is, the relative order of equivalent elements is preserved.
@ -1457,18 +1458,8 @@ class list
}
};
//Functors for member algorithm defaults
struct value_less
{
bool operator()(const value_type &a, const value_type &b) const
{ return a < b; }
};
struct value_equal
{
bool operator()(const value_type &a, const value_type &b) const
{ return a == b; }
};
typedef value_less<value_type> value_less_t;
typedef value_equal<value_type> value_equal_t;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};

View File

@ -28,6 +28,24 @@
namespace boost {
namespace container {
////////////////////////////////////////////////////////////////
//
//
// OPTIONS FOR ASSOCIATIVE TREE-BASED CONTAINERS
//
//
////////////////////////////////////////////////////////////////
//! Enumeration used to configure ordered associative containers
//! with a concrete tree implementation.
enum tree_type_enum
{
red_black_tree,
avl_tree,
scapegoat_tree,
splay_tree
};
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template<tree_type_enum TreeType, bool OptimizeSize>
@ -37,6 +55,8 @@ struct tree_opt
static const bool optimize_size = OptimizeSize;
};
typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!This option setter specifies the underlying tree type
@ -72,6 +92,151 @@ struct tree_assoc_options
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 tree-based associative containers
template<class ...Options>
using tree_assoc_options_t = typename boost::container::tree_assoc_options<Options...>::type;
#endif
////////////////////////////////////////////////////////////////
//
//
// OPTIONS FOR VECTOR-BASED CONTAINERS
//
//
////////////////////////////////////////////////////////////////
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template<class AllocTraits, class StoredSizeType>
struct get_stored_size_type_with_alloctraits
{
typedef StoredSizeType type;
};
template<class AllocTraits>
struct get_stored_size_type_with_alloctraits<AllocTraits, void>
{
typedef typename AllocTraits::size_type type;
};
template<class GrowthType, class StoredSizeType>
struct vector_opt
{
typedef GrowthType growth_factor_type;
typedef StoredSizeType stored_size_type;
template<class AllocTraits>
struct get_stored_size_type
: get_stored_size_type_with_alloctraits<AllocTraits, StoredSizeType>
{};
};
class default_next_capacity;
typedef vector_opt<void, void> vector_null_opt;
#else //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!This growth factor argument specifies that the container should increase it's
//!capacity a 50% when existing capacity is exhausted.
struct growth_factor_50{};
//!This growth factor argument specifies that the container should increase it's
//!capacity a 60% when existing capacity is exhausted.
struct growth_factor_60{};
//!This growth factor argument specifies that the container should increase it's
//!capacity a 100% (doubling its capacity) when existing capacity is exhausted.
struct growth_factor_100{};
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!This option setter specifies the growth factor strategy of the underlying vector.
//!
//!\tparam GrowthFactor A function object that has the following signature:<br/><br/>
//!`template<class SizeType>`<br/>
//!`SizeType operator()(SizeType cur_cap, SizeType add_min_cap, SizeType max_cap) const;`.<br/><br/>
//!`cur_cap` is the current capacity, `add_min_cap` is the minimum additional capacity
//!we want to achieve and `max_cap` is the maximum capacity that the allocator or other
//!factors allow. The implementation should return a value between `cur_cap` + `add_min_cap`
//!and `max_cap`. `cur_cap` + `add_min_cap` is guaranteed not to overflow/wraparound,
//! but the implementation should handle wraparound produced by the growth factor.
//!
//!Predefined growth factors that can be passed as arguments to this option are:
//!\c boost::container::growth_factor_50
//!\c boost::container::growth_factor_60
//!\c boost::container::growth_factor_100
//!
//!If this option is not specified, a default will be used by the container.
BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_factor_type)
//!This option specifies the unsigned integer type that a user wants the container
//!to use to hold size-related information inside a container (e.g. current size, current capacity).
//!
//!\tparam StoredSizeType A unsigned integer type. It shall be smaller than than the size
//! of the size_type deduced from `allocator_traits<A>::size_type` or the same type.
//!
//!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
//!memory can be saved for empty vectors. This could potentially performance benefits due to better
//!cache usage.
//!
//!Note that alignment requirements can disallow theoritical space savings. Example:
//!\c vector holds a pointer and two size types (for size and capacity), in a 32 bit machine
//!a 8 bit size type (total size: 4 byte pointer + 2 x 1 byte sizes = 6 bytes)
//!will not save space when comparing two 16-bit size types because usually
//!a 32 bit alignment is required for vector and the size will be rounded to 8 bytes. In a 64-bit
//!machine a 16 bit size type does not usually save memory when comparing to a 32-bit size type.
//!Measure the size of the resulting container and do not assume a smaller \c stored_size
//!will always lead to a smaller sizeof(container).
//!
//!If a user tries to insert more elements than representable by \c stored_size, vector
//!will throw a length_error.
//!
//!If this option is not specified, `allocator_traits<A>::size_type` (usually std::size_t) will
//!be used to store size-related information inside the container.
BOOST_INTRUSIVE_OPTION_TYPE(stored_size, StoredSizeType, StoredSizeType, stored_size_type)
//! Helper metafunction to combine options into a single type to be used
//! by \c boost::container::vector.
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
#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 vector_options
{
/// @cond
typedef typename ::boost::intrusive::pack_options
< vector_null_opt,
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
>::type packed_options;
typedef vector_opt< typename packed_options::growth_factor_type
, typename packed_options::stored_size_type> 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::vector.
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
template<class ...Options>
using vector_options_t = typename boost::container::vector_options<Options...>::type;
#endif
} //namespace container {
} //namespace boost {

View File

@ -26,14 +26,12 @@ namespace pmr {
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Compare = std::less<Key > >
using flat_map = boost::container::flat_map<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > >;
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Compare = std::less<Key> >
using flat_multimap = boost::container::flat_multimap<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > >;
#endif
@ -42,8 +40,7 @@ using flat_multimap = boost::container::flat_multimap<Key, T, Compare, polymorph
//! that uses a polymorphic allocator
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Compare = std::less<Key> >
struct flat_map_of
{
typedef boost::container::flat_map<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > > type;
@ -53,8 +50,7 @@ struct flat_map_of
//! that uses a polymorphic allocator
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Compare = std::less<Key> >
struct flat_multimap_of
{
typedef boost::container::flat_multimap<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > > type;

View File

@ -25,13 +25,11 @@ namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Compare = std::less<Key> >
using flat_set = boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> >;
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Compare = std::less<Key> >
using flat_multiset = boost::container::flat_multiset<Key, Compare, polymorphic_allocator<Key> >;
#endif
@ -39,8 +37,7 @@ using flat_multiset = boost::container::flat_multiset<Key, Compare, polymorphic_
//! A portable metafunction to obtain a flat_set
//! that uses a polymorphic allocator
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Compare = std::less<Key> >
struct flat_set_of
{
typedef boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> > type;
@ -49,8 +46,7 @@ struct flat_set_of
//! A portable metafunction to obtain a flat_multiset
//! that uses a polymorphic allocator
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Compare = std::less<Key> >
struct flat_multiset_of
{
typedef boost::container::flat_multiset<Key, Compare, polymorphic_allocator<Key> > type;

View File

@ -27,13 +27,13 @@ namespace pmr {
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
using map = boost::container::map<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options>;
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
using multimap = boost::container::multimap<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options>;
#endif
@ -43,7 +43,7 @@ using multimap = boost::container::multimap<Key, T, Compare, polymorphic_allocat
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
struct map_of
{
typedef boost::container::map<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options> type;
@ -54,7 +54,7 @@ struct map_of
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
struct multimap_of
{
typedef boost::container::multimap<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options> type;

View File

@ -26,12 +26,12 @@ namespace pmr {
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
using set = boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options>;
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
using multiset = boost::container::multiset<Key, Compare, polymorphic_allocator<Key>, Options>;
#endif
@ -40,7 +40,7 @@ using multiset = boost::container::multiset<Key, Compare, polymorphic_allocator<
//! that uses a polymorphic allocator
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
struct set_of
{
typedef boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options> type;
@ -50,7 +50,7 @@ struct set_of
//! that uses a polymorphic allocator
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
,class Options = void >
struct multiset_of
{
typedef boost::container::multiset<Key, Compare, polymorphic_allocator<Key>, Options> type;

View File

@ -60,7 +60,7 @@ namespace container {
//! \tparam Compare is the comparison functor used to order keys
//! \tparam Allocator is the allocator to be used to allocate memory for this container
//! \tparam Options is an packed option type generated using using boost::container::tree_assoc_options.
template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class Options = tree_assoc_defaults >
template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class Options = void>
#else
template <class Key, class Compare, class Allocator, class Options>
#endif

View File

@ -34,6 +34,7 @@
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/value_functors.hpp>
// intrusive
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/slist.hpp>
@ -1165,7 +1166,7 @@ class slist
//! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
void unique()
{ this->unique(value_equal()); }
{ this->unique(value_equal_t()); }
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that satisfy some binary predicate from the list.
@ -1195,7 +1196,7 @@ class slist
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
void merge(slist & x)
{ this->merge(x, value_less()); }
{ this->merge(x, value_less_t()); }
//! <b>Requires</b>: The lists x and *this must be distinct.
//!
@ -1261,7 +1262,7 @@ class slist
//! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
//! is the list's size.
void sort()
{ this->sort(value_less()); }
{ this->sort(value_less_t()); }
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
//! The sort is stable, that is, the relative order of equivalent elements is preserved.
@ -1625,28 +1626,9 @@ class slist
};
//Functors for member algorithm defaults
struct value_less
{
bool operator()(const value_type &a, const value_type &b) const
{ return a < b; }
};
typedef value_less<value_type> value_less_t;
typedef value_equal<value_type> value_equal_t;
struct value_equal
{
bool operator()(const value_type &a, const value_type &b) const
{ return a == b; }
};
struct value_equal_to_this
{
explicit value_equal_to_this(const value_type &ref)
: m_ref(ref){}
bool operator()(const value_type &val) const
{ return m_ref == val; }
const value_type &m_ref;
};
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};

View File

@ -282,7 +282,8 @@ class small_vector_allocator
pointer internal_storage() const
{
typedef typename Allocator::value_type value_type;
typedef vector_alloc_holder< small_vector_allocator<Allocator> > vector_alloc_holder_t;
typedef typename allocator_traits_type::size_type size_type;
typedef vector_alloc_holder< small_vector_allocator<Allocator>, size_type > vector_alloc_holder_t;
typedef vector<value_type, small_vector_allocator<Allocator> > vector_base;
typedef small_vector_base<value_type, Allocator> derived_type;
//
@ -350,7 +351,6 @@ class small_vector_base
typedef small_vector_allocator<SecondaryAllocator> allocator_type;
protected:
typedef typename base_type::initial_capacity_t initial_capacity_t;
BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t initial_capacity)
: base_type(initial_capacity_t(), this->internal_storage(), initial_capacity)
@ -481,7 +481,6 @@ class small_vector : public small_vector_base<T, Allocator>
BOOST_COPYABLE_AND_MOVABLE(small_vector)
typedef typename base_type::initial_capacity_t initial_capacity_t;
typedef allocator_traits<typename base_type::allocator_type> allocator_traits_type;
public:

View File

@ -292,10 +292,8 @@ class basic_string_base
size_type next_capacity(size_type additional_objects) const
{
return next_capacity_calculator
<size_type, NextCapacityDouble /*NextCapacity60Percent*/>::
get( allocator_traits_type::max_size(this->alloc())
, this->priv_storage(), additional_objects );
return growth_factor_100()
( this->priv_storage(), additional_objects, allocator_traits_type::max_size(this->alloc()));
}
void deallocate(pointer p, size_type n)

View File

@ -27,6 +27,7 @@
#include <boost/container/allocator_traits.hpp>
#include <boost/container/new_allocator.hpp> //new_allocator
#include <boost/container/throw_exception.hpp>
#include <boost/container/options.hpp>
// container detail
#include <boost/container/detail/advanced_insert_int.hpp>
#include <boost/container/detail/algorithm.hpp> //equal()
@ -39,6 +40,7 @@
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/next_capacity.hpp>
#include <boost/container/detail/value_functors.hpp>
#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/version_type.hpp>
@ -73,8 +75,6 @@ namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace dtl {
template <class Pointer, bool IsConst>
class vec_iterator
{
@ -82,7 +82,7 @@ class vec_iterator
typedef std::random_access_iterator_tag iterator_category;
typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
typedef typename if_c
typedef typename dtl::if_c
< IsConst
, typename boost::intrusive::pointer_traits<Pointer>::template
rebind_pointer<const value_type>::type
@ -244,30 +244,28 @@ struct vector_merge_cursor
Comp &m_cmp;
};
} //namespace dtl {
struct initial_capacity_t{};
template<class Pointer, bool IsConst>
BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const dtl::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
{ return it.get_ptr(); }
template<class Pointer, bool IsConst>
BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(dtl::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
{ return it.get_ptr(); }
namespace dtl {
struct uninitialized_size_t {};
static const uninitialized_size_t uninitialized_size = uninitialized_size_t();
struct vector_uninitialized_size_t {};
static const vector_uninitialized_size_t vector_uninitialized_size = vector_uninitialized_size_t();
template <class T>
struct vector_value_traits_base
{
static const bool trivial_dctr = is_trivially_destructible<T>::value;
static const bool trivial_dctr = dtl::is_trivially_destructible<T>::value;
static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
static const bool trivial_copy = is_trivially_copy_constructible<T>::value;
static const bool nothrow_copy = is_nothrow_copy_constructible<T>::value || trivial_copy;
static const bool trivial_assign = is_trivially_copy_assignable<T>::value;
static const bool nothrow_assign = is_nothrow_copy_assignable<T>::value || trivial_assign;
static const bool trivial_copy = dtl::is_trivially_copy_constructible<T>::value;
static const bool nothrow_copy = dtl::is_nothrow_copy_constructible<T>::value || trivial_copy;
static const bool trivial_assign = dtl::is_trivially_copy_assignable<T>::value;
static const bool nothrow_assign = dtl::is_nothrow_copy_assignable<T>::value || trivial_assign;
};
@ -289,6 +287,7 @@ struct vector_value_traits
//!This struct deallocates and allocated memory
template < class Allocator
, class StoredSizeType
, class AllocatorVersion = typename dtl::version<Allocator>::type
>
struct vector_alloc_holder
@ -298,7 +297,8 @@ struct vector_alloc_holder
BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
public:
typedef Allocator allocator_type;
typedef Allocator allocator_type;
typedef StoredSizeType stored_size_type;
typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
typedef typename allocator_traits_type::pointer pointer;
typedef typename allocator_traits_type::size_type size_type;
@ -334,28 +334,34 @@ struct vector_alloc_holder
//Constructor, does not throw
template<class AllocConvertible>
vector_alloc_holder(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(boost::forward<AllocConvertible>(a))
, m_start()
, m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
//Size is initialized here so vector should only call uninitialized_xxx after this
, m_size(static_cast<stored_size_type>(initial_size))
, m_capacity()
{
if(initial_size){
pointer reuse = pointer();
m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse);
size_type final_cap = initial_size;
m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
m_capacity = static_cast<stored_size_type>(final_cap);
}
}
//Constructor, does not throw
vector_alloc_holder(uninitialized_size_t, size_type initial_size)
vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
: Allocator()
, m_start()
, m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
//Size is initialized here so vector should only call uninitialized_xxx after this
, m_size(static_cast<stored_size_type>(initial_size))
, m_capacity()
{
if(initial_size){
pointer reuse = pointer();
m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse);
size_type final_cap = initial_size;
m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
m_capacity = static_cast<stored_size_type>(final_cap);
}
}
@ -369,17 +375,17 @@ struct vector_alloc_holder
holder.m_size = holder.m_capacity = 0;
}
vector_alloc_holder(pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder)
vector_alloc_holder(initial_capacity_t, pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder)
: Allocator(BOOST_MOVE_BASE(Allocator, holder))
, m_start(p)
, m_size(holder.m_size)
, m_capacity(capacity)
, m_capacity(static_cast<stored_size_type>(capacity))
{
allocator_type &this_alloc = this->alloc();
allocator_type &x_alloc = holder.alloc();
if(this->is_propagable_from(x_alloc, holder.start(), this_alloc, true)){
if(this->m_capacity){
allocator_traits_type::deallocate(this->alloc(), this->m_start, this->m_capacity);
this->deallocate(this->m_start, this->m_capacity);
}
m_start = holder.m_start;
m_capacity = holder.m_capacity;
@ -389,23 +395,26 @@ struct vector_alloc_holder
else if(this->m_capacity < holder.m_size){
size_type const n = holder.m_size;
pointer reuse = pointer();
m_start = this->allocation_command(allocate_new, n, m_capacity = n, reuse);
size_type final_cap = n;
m_start = this->allocation_command(allocate_new, n, final_cap, reuse);
m_capacity = static_cast<stored_size_type>(final_cap);
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
#endif
}
}
vector_alloc_holder(pointer p, size_type n)
vector_alloc_holder(initial_capacity_t, pointer p, size_type n)
BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
: Allocator()
, m_start(p)
, m_size()
, m_capacity(n)
//n is guaranteed to fit into stored_size_type
, m_capacity(static_cast<stored_size_type>(n))
{}
template<class AllocFwd>
vector_alloc_holder(pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
vector_alloc_holder(initial_capacity_t, pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
: Allocator(::boost::forward<AllocFwd>(a))
, m_start(p)
, m_size()
@ -415,7 +424,7 @@ struct vector_alloc_holder
BOOST_CONTAINER_FORCEINLINE ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
{
if(this->m_capacity){
allocator_traits_type::deallocate(this->alloc(), this->m_start, this->m_capacity);
this->deallocate(this->m_start, this->m_capacity);
}
}
@ -426,6 +435,21 @@ struct vector_alloc_holder
return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse);
}
BOOST_CONTAINER_FORCEINLINE pointer allocate(size_type n)
{
const size_type max_alloc = allocator_traits_type::max_size(this->alloc());
const size_type max = max_alloc <= stored_size_type(-1) ? max_alloc : stored_size_type(-1);
if ( max < n )
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
return allocator_traits_type::allocate(this->alloc(), n);
}
BOOST_CONTAINER_FORCEINLINE void deallocate(const pointer &p, size_type n)
{
allocator_traits_type::deallocate(this->alloc(), p, n);
}
bool try_expand_fwd(size_type at_least)
{
//There is not enough memory, try to expand the old one
@ -443,17 +467,24 @@ struct vector_alloc_holder
return success;
}
BOOST_CONTAINER_FORCEINLINE size_type next_capacity(size_type additional_objects) const
template<class GrowthFactorType>
size_type next_capacity(size_type additional_objects) const
{
return next_capacity_calculator
<size_type, NextCapacityDouble //NextCapacity60Percent
>::get( allocator_traits_type::max_size(this->alloc())
, this->m_capacity, additional_objects );
BOOST_ASSERT(additional_objects > size_type(this->m_capacity - this->m_size));
size_type max = allocator_traits_type::max_size(this->alloc());
(clamp_by_stored_size_type)(max, stored_size_type());
const size_type remaining_cap = max - size_type(this->m_capacity);
const size_type min_additional_cap = additional_objects - size_type(this->m_capacity - this->m_size);
if ( remaining_cap < min_additional_cap )
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
return GrowthFactorType()( size_type(this->m_capacity), min_additional_cap, max);
}
pointer m_start;
size_type m_size;
size_type m_capacity;
pointer m_start;
stored_size_type m_size;
stored_size_type m_capacity;
void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
{
@ -478,9 +509,9 @@ struct vector_alloc_holder
{ return *this; }
const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW { return m_start; }
const size_type &capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_capacity; }
size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_capacity; }
void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW { m_start = p; }
void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW { m_capacity = c; }
void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; }
private:
void priv_first_allocation(size_type cap)
@ -495,15 +526,30 @@ struct vector_alloc_holder
}
}
BOOST_CONTAINER_FORCEINLINE static void clamp_by_stored_size_type(size_type &, size_type)
{}
template<class SomeStoredSizeType>
BOOST_CONTAINER_FORCEINLINE static void clamp_by_stored_size_type(size_type &s, SomeStoredSizeType)
{
if (s >= SomeStoredSizeType(-1) )
s = SomeStoredSizeType(-1);
}
BOOST_CONTAINER_FORCEINLINE pointer priv_allocation_command(version_1, boost::container::allocation_type command,
size_type ,
size_type limit_size,
size_type &prefer_in_recvd_out_size,
pointer &reuse)
{
(void)command;
BOOST_ASSERT( (command & allocate_new));
BOOST_ASSERT(!(command & nothrow_allocation));
pointer const p = allocator_traits_type::allocate(this->alloc(), prefer_in_recvd_out_size, reuse);
//First detect overflow on smaller stored_size_types
if (limit_size > stored_size_type(-1)){
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
}
(clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
pointer const p = this->allocate(prefer_in_recvd_out_size);
reuse = pointer();
return p;
}
@ -513,13 +559,22 @@ struct vector_alloc_holder
size_type &prefer_in_recvd_out_size,
pointer &reuse)
{
return this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
//First detect overflow on smaller stored_size_types
if (limit_size > stored_size_type(-1)){
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
}
(clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
//Allocate memory
pointer p = this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
//If after allocation prefer_in_recvd_out_size is not representable by stored_size_type, truncate it.
(clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
return p;
}
};
//!This struct deallocates and allocated memory
template <class Allocator>
struct vector_alloc_holder<Allocator, version_0>
template <class Allocator, class StoredSizeType>
struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
: public Allocator
{
private:
@ -530,8 +585,9 @@ struct vector_alloc_holder<Allocator, version_0>
typedef typename allocator_traits_type::pointer pointer;
typedef typename allocator_traits_type::size_type size_type;
typedef typename allocator_traits_type::value_type value_type;
typedef StoredSizeType stored_size_type;
template <class OtherAllocator, class OtherAllocatorVersion>
template <class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
friend struct vector_alloc_holder;
//Constructor, does not throw
@ -548,7 +604,7 @@ struct vector_alloc_holder<Allocator, version_0>
//Constructor, does not throw
template<class AllocConvertible>
vector_alloc_holder(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(boost::forward<AllocConvertible>(a))
, m_size(initial_size) //Size is initialized here...
{
@ -557,7 +613,7 @@ struct vector_alloc_holder<Allocator, version_0>
}
//Constructor, does not throw
vector_alloc_holder(uninitialized_size_t, size_type initial_size)
vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
: Allocator()
, m_size(initial_size) //Size is initialized here...
{
@ -573,8 +629,8 @@ struct vector_alloc_holder<Allocator, version_0>
(this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start()));
}
template<class OtherAllocator, class OtherAllocatorVersion>
vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> BOOST_RV_REF_END holder)
template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> BOOST_RV_REF_END holder)
: Allocator()
, m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
{
@ -597,8 +653,8 @@ struct vector_alloc_holder<Allocator, version_0>
this->priv_deep_swap(x);
}
template<class OtherAllocator, class OtherAllocatorVersion>
void deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
void deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
{
if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){
throw_bad_alloc();
@ -628,12 +684,12 @@ struct vector_alloc_holder<Allocator, version_0>
BOOST_CONTAINER_FORCEINLINE pointer start() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_storage(); }
BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_capacity; }
size_type m_size;
stored_size_type m_size;
private:
template<class OtherAllocator, class OtherAllocatorVersion>
void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
{
const size_type MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity;
value_type *const first_this = boost::movelib::to_raw_pointer(this->start());
@ -649,7 +705,34 @@ struct vector_alloc_holder<Allocator, version_0>
}
};
} //namespace dtl {
struct growth_factor_60;
template<class T, class Default>
struct default_if_void
{
typedef T type;
};
template<class Default>
struct default_if_void<void, Default>
{
typedef Default type;
};
template<class Options, class AllocatorSizeType>
struct get_vector_opt
{
typedef vector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type
, typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type
> type;
};
template<class AllocatorSizeType>
struct get_vector_opt<void, AllocatorSizeType>
{
typedef vector_opt<growth_factor_60, AllocatorSizeType> type;
};
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@ -660,28 +743,32 @@ struct vector_alloc_holder<Allocator, version_0>
//!
//! \tparam T The type of object that is stored in the vector
//! \tparam Allocator The allocator used for all internal memory management
template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) >
//! \tparam Options A type produced from \c boost::container::vector_options.
template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>), class Options BOOST_CONTAINER_DOCONLY(= void) >
class vector
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
struct value_less
{
typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
bool operator()(const value_type &a, const value_type &b) const
{ return a < b; }
};
typedef typename boost::container::allocator_traits<Allocator>::size_type alloc_size_type;
typedef typename get_vector_opt<Options, alloc_size_type>::type options_type;
typedef typename options_type::growth_factor_type growth_factor_type;
typedef typename options_type::stored_size_type stored_size_type;
typedef value_less<T> value_less_t;
//If provided the stored_size option must specify a type that is equal or a type that is smaller.
BOOST_STATIC_ASSERT( (sizeof(stored_size_type) < sizeof(alloc_size_type) ||
dtl::is_same<stored_size_type, alloc_size_type>::value) );
typedef typename dtl::version<Allocator>::type alloc_version;
typedef boost::container::dtl::vector_alloc_holder<Allocator> alloc_holder_t;
typedef boost::container::vector_alloc_holder<Allocator, stored_size_type> alloc_holder_t;
alloc_holder_t m_holder;
typedef allocator_traits<Allocator> allocator_traits_type;
template <class U, class UAllocator>
template <class U, class UAllocator, class UOptions>
friend class vector;
typedef typename allocator_traits_type::pointer pointer_impl;
typedef dtl::vec_iterator<pointer_impl, false> iterator_impl;
typedef dtl::vec_iterator<pointer_impl, true > const_iterator_impl;
typedef vec_iterator<pointer_impl, false> iterator_impl;
typedef vec_iterator<pointer_impl, true > const_iterator_impl;
protected:
static bool is_propagable_from(const Allocator &from_alloc, pointer_impl p, const Allocator &to_alloc, bool const propagate_allocator)
@ -716,7 +803,7 @@ class vector
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(vector)
typedef dtl::vector_value_traits<Allocator> value_traits;
typedef vector_value_traits<Allocator> value_traits;
typedef constant_iterator<T, difference_type> cvalue_iterator;
protected:
@ -724,14 +811,13 @@ class vector
BOOST_CONTAINER_FORCEINLINE void steal_resources(vector &x)
{ return this->m_holder.steal_resources(x.m_holder); }
struct initial_capacity_t{};
template<class AllocFwd>
BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a)
: m_holder(initial_memory, capacity, ::boost::forward<AllocFwd>(a))
: m_holder(initial_capacity_t(), initial_memory, capacity, ::boost::forward<AllocFwd>(a))
{}
BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity)
: m_holder(initial_memory, capacity)
: m_holder(initial_capacity_t(), initial_memory, capacity)
{}
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@ -768,7 +854,7 @@ class vector
//!
//! <b>Complexity</b>: Linear to n.
explicit vector(size_type n)
: m_holder(dtl::uninitialized_size, n)
: m_holder(vector_uninitialized_size, n)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
@ -785,7 +871,7 @@ class vector
//!
//! <b>Complexity</b>: Linear to n.
explicit vector(size_type n, const allocator_type &a)
: m_holder(dtl::uninitialized_size, a, n)
: m_holder(vector_uninitialized_size, a, n)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
@ -804,7 +890,7 @@ class vector
//!
//! <b>Note</b>: Non-standard extension
vector(size_type n, default_init_t)
: m_holder(dtl::uninitialized_size, n)
: m_holder(vector_uninitialized_size, n)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
@ -823,7 +909,7 @@ class vector
//!
//! <b>Note</b>: Non-standard extension
vector(size_type n, default_init_t, const allocator_type &a)
: m_holder(dtl::uninitialized_size, a, n)
: m_holder(vector_uninitialized_size, a, n)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
@ -840,7 +926,7 @@ class vector
//!
//! <b>Complexity</b>: Linear to n.
vector(size_type n, const T& value)
: m_holder(dtl::uninitialized_size, n)
: m_holder(vector_uninitialized_size, n)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
@ -857,7 +943,7 @@ class vector
//!
//! <b>Complexity</b>: Linear to n.
vector(size_type n, const T& value, const allocator_type& a)
: m_holder(dtl::uninitialized_size, a, n)
: m_holder(vector_uninitialized_size, a, n)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
@ -907,7 +993,7 @@ class vector
//!
//! <b>Complexity</b>: Linear to the elements x contains.
vector(const vector &x)
: m_holder( dtl::uninitialized_size
: m_holder( vector_uninitialized_size
, allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc())
, x.size())
{
@ -970,7 +1056,7 @@ class vector
//!
//! <b>Complexity</b>: Linear to the elements x contains.
vector(const vector &x, const allocator_type &a)
: m_holder(dtl::uninitialized_size, a, x.size())
: m_holder(vector_uninitialized_size, a, x.size())
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += x.size() != 0;
@ -988,7 +1074,7 @@ class vector
//!
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
vector(BOOST_RV_REF(vector) x, const allocator_type &a)
: m_holder( dtl::uninitialized_size, a
: m_holder( vector_uninitialized_size, a
, is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true) ? 0 : x.size()
)
{
@ -1194,7 +1280,7 @@ class vector
pointer const old_p = this->m_holder.start();
if(old_p){
this->priv_destroy_all();
allocator_traits_type::deallocate(this->m_holder.alloc(), old_p, old_capacity);
this->m_holder.deallocate(old_p, old_capacity);
}
this->m_holder.start(ret);
this->m_holder.capacity(real_cap);
@ -2028,19 +2114,19 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
void clear() BOOST_NOEXCEPT_OR_NOTHROW
BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
{ this->priv_destroy_all(); }
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const vector& x, const vector& y)
BOOST_CONTAINER_FORCEINLINE friend bool operator==(const vector& x, const vector& y)
{ return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const vector& x, const vector& y)
BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const vector& x, const vector& y)
{ return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
@ -2060,25 +2146,25 @@ class vector
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const vector& x, const vector& y)
BOOST_CONTAINER_FORCEINLINE friend bool operator>(const vector& x, const vector& y)
{ return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const vector& x, const vector& y)
BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const vector& x, const vector& y)
{ return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const vector& x, const vector& y)
BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const vector& x, const vector& y)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(vector& x, vector& y)
BOOST_CONTAINER_FORCEINLINE friend void swap(vector& x, vector& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@ -2099,26 +2185,26 @@ class vector
//Absolutely experimental. This function might change, disappear or simply crash!
template<class BiDirPosConstIt, class BiDirValueIt>
void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
BOOST_CONTAINER_FORCEINLINE void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
{
typedef dtl::vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t;
typedef vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t;
return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
}
template<class BidirIt>
void merge(BidirIt first, BidirIt last)
{ this->merge(first, last, value_less()); }
BOOST_CONTAINER_FORCEINLINE void merge(BidirIt first, BidirIt last)
{ this->merge(first, last, value_less_t()); }
template<class BidirIt, class Compare>
void merge(BidirIt first, BidirIt last, Compare comp)
BOOST_CONTAINER_FORCEINLINE void merge(BidirIt first, BidirIt last, Compare comp)
{ this->priv_merge(dtl::false_type(), first, last, comp); }
template<class BidirIt>
void merge_unique(BidirIt first, BidirIt last)
{ this->priv_merge(dtl::true_type(), first, last, value_less()); }
BOOST_CONTAINER_FORCEINLINE void merge_unique(BidirIt first, BidirIt last)
{ this->priv_merge(dtl::true_type(), first, last, value_less_t()); }
template<class BidirIt, class Compare>
void merge_unique(BidirIt first, BidirIt last, Compare comp)
BOOST_CONTAINER_FORCEINLINE void merge_unique(BidirIt first, BidirIt last, Compare comp)
{ this->priv_merge(dtl::true_type(), first, last, comp); }
private:
@ -2209,7 +2295,7 @@ class vector
}
template<class UniqueBool, class FwdIt, class Compare>
void priv_merge_in_new_buffer(UniqueBool, FwdIt, size_type, Compare, version_0)
BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(UniqueBool, FwdIt, size_type, Compare, version_0)
{
throw_bad_alloc();
}
@ -2266,7 +2352,7 @@ class vector
pointer const old_p = this->m_holder.start();
size_type const old_cap = this->m_holder.capacity();
boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size);
allocator_traits_type::deallocate(a, old_p, old_cap);
this->m_holder.deallocate(old_p, old_cap);
this->m_holder.m_size = old_size + added;
this->m_holder.start(new_storage);
this->m_holder.capacity(new_cap);
@ -2274,10 +2360,10 @@ class vector
new_values_destroyer.release();
}
bool room_enough() const
BOOST_CONTAINER_FORCEINLINE bool room_enough() const
{ return this->m_holder.m_size < this->m_holder.capacity(); }
pointer back_ptr() const
BOOST_CONTAINER_FORCEINLINE pointer back_ptr() const
{ return this->m_holder.start() + this->m_holder.m_size; }
size_type priv_index_of(pointer p) const
@ -2331,7 +2417,7 @@ class vector
}
else if(is_propagable_from_x){
this->clear();
allocator_traits_type::deallocate(this->m_holder.alloc(), this->m_holder.m_start, this->m_holder.m_capacity);
this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
this->m_holder.steal_resources(x.m_holder);
}
//Else do a one by one move
@ -2429,7 +2515,7 @@ class vector
{
//There is not enough memory, allocate a new buffer
//Pass the hint so that allocators can take advantage of this.
pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start);
pointer const p = this->m_holder.allocate(new_cap);
//We will reuse insert code, so create a dummy input iterator
this->priv_forward_range_insert_new_allocation
( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
@ -2537,13 +2623,13 @@ class vector
}
}
dtl::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x)
BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x)
{ return dtl::insert_n_copies_proxy<Allocator, T*>(x); }
dtl::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t)
BOOST_CONTAINER_FORCEINLINE dtl::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t)
{ return dtl::insert_default_initialized_n_proxy<Allocator, T*>(); }
dtl::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t)
BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t)
{ return dtl::insert_value_initialized_n_proxy<Allocator, T*>(); }
template <class U>
@ -2560,7 +2646,7 @@ class vector
}
}
void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
BOOST_CONTAINER_FORCEINLINE void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
{}
void priv_shrink_to_fit(version_1)
@ -2569,14 +2655,14 @@ class vector
if(cp){
const size_type sz = this->size();
if(!sz){
allocator_traits_type::deallocate(this->m_holder.alloc(), this->m_holder.m_start, cp);
this->m_holder.deallocate(this->m_holder.m_start, cp);
this->m_holder.m_start = pointer();
this->m_holder.m_capacity = 0;
}
else if(sz < cp){
//Allocate a new buffer.
//Pass the hint so that allocators can take advantage of this.
pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), sz, this->m_holder.m_start);
pointer const p = this->m_holder.allocate(sz);
//We will reuse insert code, so create a dummy input iterator
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
@ -2595,7 +2681,7 @@ class vector
if(cp){
const size_type sz = this->size();
if(!sz){
allocator_traits_type::deallocate(this->m_holder.alloc(), this->m_holder.m_start, cp);
this->m_holder.deallocate(this->m_holder.m_start, cp);
this->m_holder.m_start = pointer();
this->m_holder.m_capacity = 0;
}
@ -2629,10 +2715,9 @@ class vector
const size_type n_pos = pos - this->m_holder.start();
T *const raw_pos = boost::movelib::to_raw_pointer(pos);
const size_type new_cap = this->m_holder.next_capacity(n);
const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
//Pass the hint so that allocators can take advantage of this.
T * const new_buf = boost::movelib::to_raw_pointer
(allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start));
T * const new_buf = boost::movelib::to_raw_pointer(this->m_holder.allocate(new_cap));
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc;
#endif
@ -2651,7 +2736,7 @@ class vector
//There is not enough memory, allocate a new
//buffer or expand the old one.
size_type real_cap = this->m_holder.next_capacity(n);
size_type real_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
pointer reuse(this->m_holder.start());
pointer const ret (this->m_holder.allocation_command
(allocate_new | expand_fwd | expand_bwd, this->m_holder.m_size + n, real_cap, reuse));
@ -2725,7 +2810,7 @@ class vector
}
template <class InsertionProxy, class AllocVersion>
iterator priv_forward_range_insert_at_end
BOOST_CONTAINER_FORCEINLINE iterator priv_forward_range_insert_at_end
(const size_type n, const InsertionProxy insert_range_proxy, AllocVersion)
{
return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy);
@ -2909,10 +2994,10 @@ class vector
//If there is allocated memory, destroy and deallocate
if(!value_traits::trivial_dctr_after_move)
boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
allocator_traits_type::deallocate(this->m_holder.alloc(), this->m_holder.start(), this->m_holder.capacity());
this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
}
this->m_holder.start(new_start);
this->m_holder.m_size = new_finish - new_start;
this->m_holder.m_size = size_type(new_finish - new_start);
this->m_holder.capacity(new_cap);
//All construction successful, disable rollbacks
new_values_destroyer.release();
@ -3248,12 +3333,12 @@ class vector
}
}
bool priv_in_range(const_iterator pos) const
BOOST_CONTAINER_FORCEINLINE bool priv_in_range(const_iterator pos) const
{
return (this->begin() <= pos) && (pos < this->end());
}
bool priv_in_range_or_end(const_iterator pos) const
BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const
{
return (this->begin() <= pos) && (pos <= this->end());
}

View File

@ -1,72 +1,4 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set_test", "set_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792606}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map_test", "map_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792606}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_emplace", "doc_emplace.vcproj", "{5CE11C83-FA84-295A-4FA2-D7921A0BAB02}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_move_containers", "doc_move_containers.vcproj", "{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_recursive_containers", "doc_recursive_containers.vcproj", "{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_type_erasure", "doc_type_erasure.vcproj", "{5C8E1C13-A4F4-2C55-4FA2-D100BA6A9041}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alloc_basic_test", "alloc_basic_test.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alloc_full_test", "alloc_full_test.vcproj", "{CD57C283-1862-9FE5-BF87-BA91293A76D3}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_alloc_lib", "alloc_lib.vcproj", "{685AC59C-E667-4096-9DAA-AB76083C7092}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "allocator_traits_test", "allocator_traits_test.vcproj", "{5CE11C83-096A-84FE-4FA2-D3A6BA792002}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_adaptive_node_pool", "bench_adaptive_node_pool.vcproj", "{C8AD2618-79EB-8612-42FE-2A3AC9667A13}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_alloc_expand_bwd", "bench_alloc_expand_bwd.vcproj", "{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_alloc", "bench_alloc.vcproj", "{7CC83A22-8612-7BF8-2F4E-BD9493C6A071}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_alloc_expand_fwd", "bench_alloc_expand_fwd.vcproj", "{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_alloc_shrink_to_fit", "bench_alloc_shrink_to_fit.vcproj", "{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_set", "bench_set.vcproj", "{5E1C1C23-26A9-4FE5-A24E-DA735271C32B}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_static_vector", "bench_static_vector.vcproj", "{55E1C1C3-84FE-26A9-4A2E-D7901C32BA02}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_containerlib", "container.vcproj", "{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
@ -319,6 +251,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_tree_test", "flat_tree
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vector_options_test", "vector_options_test.vcproj", "{3E10C8C3-4F8E-96A0-4FA2-D032BA7A6092}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_custom_vector", "doc_custom_vector.vcproj", "{5E11C8B3-A8C4-4A2F-295A-7951A0EDAA02}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
@ -327,74 +267,6 @@ Global
GlobalSection(ProjectDependencies) = postSolution
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.Build.0 = Release|Win32
{5CE11C83-FA84-295A-4FA2-D7921A0BAB02}.Debug.ActiveCfg = Debug|Win32
{5CE11C83-FA84-295A-4FA2-D7921A0BAB02}.Debug.Build.0 = Debug|Win32
{5CE11C83-FA84-295A-4FA2-D7921A0BAB02}.Release.ActiveCfg = Release|Win32
{5CE11C83-FA84-295A-4FA2-D7921A0BAB02}.Release.Build.0 = Release|Win32
{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}.Debug.ActiveCfg = Debug|Win32
{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}.Debug.Build.0 = Debug|Win32
{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}.Release.ActiveCfg = Release|Win32
{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}.Release.Build.0 = Release|Win32
{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}.Debug.ActiveCfg = Debug|Win32
{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}.Debug.Build.0 = Debug|Win32
{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}.Release.ActiveCfg = Release|Win32
{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}.Release.Build.0 = Release|Win32
{5C8E1C13-A4F4-2C55-4FA2-D100BA6A9041}.Debug.ActiveCfg = Debug|Win32
{5C8E1C13-A4F4-2C55-4FA2-D100BA6A9041}.Debug.Build.0 = Debug|Win32
{5C8E1C13-A4F4-2C55-4FA2-D100BA6A9041}.Release.ActiveCfg = Release|Win32
{5C8E1C13-A4F4-2C55-4FA2-D100BA6A9041}.Release.Build.0 = Release|Win32
{CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32
{CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32
{CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32
{CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32
{CD57C283-1862-9FE5-BF87-BA91293A76D3}.Debug.ActiveCfg = Debug|Win32
{CD57C283-1862-9FE5-BF87-BA91293A76D3}.Debug.Build.0 = Debug|Win32
{CD57C283-1862-9FE5-BF87-BA91293A76D3}.Release.ActiveCfg = Release|Win32
{CD57C283-1862-9FE5-BF87-BA91293A76D3}.Release.Build.0 = Release|Win32
{685AC59C-E667-4096-9DAA-AB76083C7092}.Debug.ActiveCfg = Debug|Win32
{685AC59C-E667-4096-9DAA-AB76083C7092}.Debug.Build.0 = Debug|Win32
{685AC59C-E667-4096-9DAA-AB76083C7092}.Release.ActiveCfg = Release|Win32
{685AC59C-E667-4096-9DAA-AB76083C7092}.Release.Build.0 = Release|Win32
{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.ActiveCfg = Debug|Win32
{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.Build.0 = Debug|Win32
{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.ActiveCfg = Release|Win32
{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.Build.0 = Release|Win32
{C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.ActiveCfg = Debug|Win32
{C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.Build.0 = Debug|Win32
{C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.ActiveCfg = Release|Win32
{C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.Build.0 = Release|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Debug.ActiveCfg = Debug|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Debug.Build.0 = Debug|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Release.ActiveCfg = Release|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Release.Build.0 = Release|Win32
{7CC83A22-8612-7BF8-2F4E-BD9493C6A071}.Debug.ActiveCfg = Debug|Win32
{7CC83A22-8612-7BF8-2F4E-BD9493C6A071}.Debug.Build.0 = Debug|Win32
{7CC83A22-8612-7BF8-2F4E-BD9493C6A071}.Release.ActiveCfg = Release|Win32
{7CC83A22-8612-7BF8-2F4E-BD9493C6A071}.Release.Build.0 = Release|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Debug.ActiveCfg = Debug|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Debug.Build.0 = Debug|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Release.ActiveCfg = Release|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Release.Build.0 = Release|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Debug.ActiveCfg = Debug|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Debug.Build.0 = Debug|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Release.ActiveCfg = Release|Win32
{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}.Release.Build.0 = Release|Win32
{5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Debug.ActiveCfg = Debug|Win32
{5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Debug.Build.0 = Debug|Win32
{5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Release.ActiveCfg = Release|Win32
{5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Release.Build.0 = Release|Win32
{55E1C1C3-84FE-26A9-4A2E-D7901C32BA02}.Debug.ActiveCfg = Debug|Win32
{55E1C1C3-84FE-26A9-4A2E-D7901C32BA02}.Debug.Build.0 = Debug|Win32
{55E1C1C3-84FE-26A9-4A2E-D7901C32BA02}.Release.ActiveCfg = Release|Win32
{55E1C1C3-84FE-26A9-4A2E-D7901C32BA02}.Release.Build.0 = Release|Win32
{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.ActiveCfg = Debug|Win32
{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.Build.0 = Debug|Win32
{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.ActiveCfg = Release|Win32
@ -645,6 +517,14 @@ Global
{DE1834C3-2609-FE38-4FA5-0BA0D3CD0796}.Debug.Build.0 = Debug|Win32
{DE1834C3-2609-FE38-4FA5-0BA0D3CD0796}.Release.ActiveCfg = Release|Win32
{DE1834C3-2609-FE38-4FA5-0BA0D3CD0796}.Release.Build.0 = Release|Win32
{3E10C8C3-4F8E-96A0-4FA2-D032BA7A6092}.Debug.ActiveCfg = Debug|Win32
{3E10C8C3-4F8E-96A0-4FA2-D032BA7A6092}.Debug.Build.0 = Debug|Win32
{3E10C8C3-4F8E-96A0-4FA2-D032BA7A6092}.Release.ActiveCfg = Release|Win32
{3E10C8C3-4F8E-96A0-4FA2-D032BA7A6092}.Release.Build.0 = Release|Win32
{5E11C8B3-A8C4-4A2F-295A-7951A0EDAA02}.Debug.ActiveCfg = Debug|Win32
{5E11C8B3-A8C4-4A2F-295A-7951A0EDAA02}.Debug.Build.0 = Debug|Win32
{5E11C8B3-A8C4-4A2F-295A-7951A0EDAA02}.Release.ActiveCfg = Release|Win32
{5E11C8B3-A8C4-4A2F-295A-7951A0EDAA02}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection

View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="doc_custom_vector"
ProjectGUID="{5E11C8B3-A8C4-4A2F-295A-7951A0EDAA02}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/doc_custom_vector"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/doc_custom_vector_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/doc_custom_vector.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"
/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/doc_custom_vector"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/doc_custom_vector.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4F4737BC-032A-5430-AC75-A32542AA2D1F}">
<File
RelativePath="..\..\example\doc_custom_vector.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -13,7 +13,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/vector_test"
IntermediateDirectory="Debug/doc_extended_allocators"
ConfigurationType="1"
CharacterSet="2">
<Tool

View File

@ -13,7 +13,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/vector_test"
IntermediateDirectory="Debug/doc_move_containers"
ConfigurationType="1"
CharacterSet="2">
<Tool

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="vector_options_test"
ProjectGUID="{3E10C8C3-4F8E-96A0-4FA2-D032BA7A6092}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/vector_options_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/vector_options_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/vector_options_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/vector_options_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/vector_options_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{3BCC4057-7AC5-1273-6AD6-5A3296A32D7F}">
<File
RelativePath="..\..\test\vector_options_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,121 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/vector.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/detail/next_capacity.hpp>
#include <boost/core/lightweight_test.hpp>
using namespace boost::container;
template<class Unsigned, class VectorType>
void test_stored_size_type_impl()
{
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);
}
template<class Unsigned>
void test_stored_size_type()
{
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
using options_t = vector_options_t< stored_size<Unsigned> >;
#else
typedef typename vector_options
< stored_size<Unsigned> >::type options_t;
#endif
//Test first with a typical allocator
{
typedef vector<unsigned char, new_allocator<unsigned char>, options_t> vector_t;
test_stored_size_type_impl<Unsigned, vector_t>();
}
//Test with a V2 allocator
{
typedef vector<unsigned char, allocator<unsigned char>, options_t> vector_t;
test_stored_size_type_impl<Unsigned, vector_t>();
}
}
void test_growth_factor_50()
{
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
using options_t = vector_options_t< growth_factor<growth_factor_50> >;
#else
typedef vector_options
< growth_factor<growth_factor_50> >::type options_t;
#endif
vector<int, new_allocator<int>, options_t> v;
v.resize(5);
v.resize(v.capacity());
std::size_t old_capacity = v.capacity();
v.push_back(0);
std::size_t new_capacity = v.capacity();
BOOST_TEST(new_capacity == old_capacity + old_capacity/2);
}
void test_growth_factor_60()
{
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
using options_t = vector_options_t< growth_factor<growth_factor_60> >;
#else
typedef vector_options
< growth_factor<growth_factor_60> >::type options_t;
#endif
vector<int, new_allocator<int>, options_t> v;
v.resize(5);
v.resize(v.capacity());
std::size_t old_capacity = v.capacity();
v.push_back(0);
std::size_t new_capacity = v.capacity();
BOOST_TEST(new_capacity == old_capacity + 3*old_capacity/5);
}
void test_growth_factor_100()
{
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
using options_t = vector_options_t< growth_factor<growth_factor_100> >;
#else
typedef vector_options
< growth_factor<growth_factor_100> >::type options_t;
#endif
vector<int, new_allocator<int>, options_t> v;
v.resize(5);
v.resize(v.capacity());
std::size_t old_capacity = v.capacity();
v.push_back(0);
std::size_t new_capacity = v.capacity();
BOOST_TEST(new_capacity == 2*old_capacity);
}
int main()
{
test_growth_factor_50();
test_growth_factor_60();
test_growth_factor_100();
test_stored_size_type<unsigned char>();
test_stored_size_type<unsigned short>();
return ::boost::report_errors();
}

View File

@ -38,13 +38,9 @@ template class boost::container::vector
< test::movable_and_copyable_int
, allocator<test::movable_and_copyable_int> >;
namespace dtl {
template class vec_iterator<int*, true >;
template class vec_iterator<int*, false>;
}
}}
int test_expand_bwd()