- 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

@@ -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());
}