From 2802a1f50dbf0f79b248781349e07591af646bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 10 Dec 2017 23:33:41 +0100 Subject: [PATCH] - Add configuration options to vector - Cleanup tree configuration options --- doc/Jamfile.v2 | 3 +- doc/container.qbk | 175 ++++++---- example/doc_custom_vector.cpp | 54 +++ include/boost/container/container_fwd.hpp | 33 +- include/boost/container/detail/flat_tree.hpp | 91 +++-- .../boost/container/detail/next_capacity.hpp | 70 ++-- include/boost/container/detail/tree.hpp | 29 +- .../boost/container/detail/value_functors.hpp | 36 ++ include/boost/container/list.hpp | 21 +- include/boost/container/options.hpp | 165 +++++++++ include/boost/container/pmr/flat_map.hpp | 12 +- include/boost/container/pmr/flat_set.hpp | 12 +- include/boost/container/pmr/map.hpp | 8 +- include/boost/container/pmr/set.hpp | 8 +- include/boost/container/set.hpp | 2 +- include/boost/container/slist.hpp | 30 +- include/boost/container/small_vector.hpp | 5 +- include/boost/container/string.hpp | 6 +- include/boost/container/vector.hpp | 321 +++++++++++------- proj/vc7ide/container.sln | 152 +-------- proj/vc7ide/doc_custom_vector.vcproj | 136 ++++++++ proj/vc7ide/doc_extended_allocators.vcproj | 2 +- proj/vc7ide/doc_move_containers.vcproj | 2 +- proj/vc7ide/vector_options_test.vcproj | 135 ++++++++ test/vector_options_test.cpp | 121 +++++++ test/vector_test.cpp | 4 - 26 files changed, 1122 insertions(+), 511 deletions(-) create mode 100644 example/doc_custom_vector.cpp create mode 100644 include/boost/container/detail/value_functors.hpp create mode 100644 proj/vc7ide/doc_custom_vector.vcproj create mode 100644 proj/vc7ide/vector_options_test.vcproj create mode 100644 test/vector_options_test.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 62bb90d..dedb9c1 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -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 struct OPTION_NAME{};\" \\ + \"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template struct OPTION_NAME{};\" \\ + \"BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) = template struct OPTION_NAME{};\" \\ \"BOOST_CONTAINER_DOC1ST(T1, T2)=T1\" \\ \"BOOST_CONTAINER_DOCIGN(T) \"\\ \"BOOST_CONTAINER_DOCONLY(T)=T\"\\ diff --git a/doc/container.qbk b/doc/container.qbk index 4d232fa..c5039ce 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -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]. diff --git a/example/doc_custom_vector.cpp b/example/doc_custom_vector.cpp new file mode 100644 index 0000000..08dfad7 --- /dev/null +++ b/example/doc_custom_vector.cpp @@ -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 +#include + +//Make sure assertions are active +#ifdef NDEBUG +#undef NDEBUG +#endif +#include + +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 >::type size_option_t; + + //Size-optimized vector is smaller than the default one. + typedef vector, size_option_t > size_optimized_vector_t; + BOOST_STATIC_ASSERT(( sizeof(size_optimized_vector_t) < sizeof(vector) )); + + //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 >::type growth_50_option_t; + + //Fill the vector until full capacity is reached + vector, 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; +} +//] diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp index 2ad5967..e4fe6f8 100644 --- a/include/boost/container/container_fwd.hpp +++ b/include/boost/container/container_fwd.hpp @@ -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 new_allocator; template > + ,class Allocator = new_allocator + ,class Options = void> class vector; template > class slist; -template -struct tree_opt; - -typedef tree_opt tree_assoc_defaults; - template ,class Allocator = new_allocator - ,class Options = tree_assoc_defaults > + ,class Options = void> class set; template ,class Allocator = new_allocator - ,class Options = tree_assoc_defaults > + ,class Options = void > class multiset; template ,class Allocator = new_allocator > - ,class Options = tree_assoc_defaults > + ,class Options = void > class map; template ,class Allocator = new_allocator > - ,class Options = tree_assoc_defaults > + ,class Options = void > class multimap; template -//! - optimize_size -typedef implementation_defined tree_assoc_defaults; - #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! Type used to tag that the input range is diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 22f9187..0758703 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -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 @@ -118,23 +124,25 @@ BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal } template -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 -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 -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_::value>()); + (aux_flat_tree_merge_equal_non_merge_member) + ( dest, first, last, comp, dtl::bool_::value>()); } template -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 -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 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 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 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 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 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 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 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 -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 -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 -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 -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 -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 -BOOST_CONTAINER_FORCEINLINE void +BOOST_CONTAINER_FORCEINLINE void // has_reserve == false flat_tree_reserve(SequenceContainer &, typename SequenceContainer::size_type, dtl::false_) { } -template +template // has_capacity == true BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type flat_tree_capacity(const SequenceContainer &tseq, dtl::true_) { return tseq.capacity(); } -template +template // 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 flat_tree_value_compare : private Compare @@ -324,19 +342,12 @@ class flat_tree_value_compare Compare &get_comp() { return *this; } }; -/* -template -struct get_flat_tree_iterators -{ - typedef typename boost::container::dtl:: - vec_iterator iterator; - typedef typename boost::container::dtl:: - vec_iterator const_iterator; - typedef boost::container::reverse_iterator reverse_iterator; - typedef boost::container::reverse_iterator const_reverse_iterator; -}; -*/ +/////////////////////////////////////// +// +// select_container_type +// +/////////////////////////////////////// template < class Value, class AllocatorOrContainer , bool = boost::container::dtl::is_container::value > struct select_container_type @@ -350,6 +361,12 @@ struct select_container_type typedef boost::container::vector type; }; + +/////////////////////////////////////// +// +// flat_tree +// +/////////////////////////////////////// template class flat_tree diff --git a/include/boost/container/detail/next_capacity.hpp b/include/boost/container/detail/next_capacity.hpp index 464e8d8..7e6554d 100644 --- a/include/boost/container/detail/next_capacity.hpp +++ b/include/boost/container/detail/next_capacity.hpp @@ -23,52 +23,54 @@ // container/detail #include +#include + namespace boost { namespace container { namespace dtl { -enum NextCapacityOption { NextCapacityDouble, NextCapacity60Percent }; - -template -struct next_capacity_calculator; - -template -struct next_capacity_calculator +template +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 + 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 -struct next_capacity_calculator -{ - 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 { diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 0ea5769..8d41158 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -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 +template +struct get_tree_opt +{ + typedef Options type; +}; + +template<> +struct get_tree_opt +{ + typedef tree_assoc_defaults type; +}; + +template class tree : public dtl::node_alloc_holder < Allocator , typename dtl::intrusive_tree_type < Allocator, tree_value_compare ::pointer, Compare, KeyOfValue> - , Options::tree_type, Options::optimize_size>::type + , get_tree_opt::type::tree_type + , get_tree_opt::type::optimize_size + >::type > { typedef tree_value_compare < typename allocator_traits::pointer , Compare, KeyOfValue> ValComp; + typedef typename get_tree_opt::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 AllocHolder; typedef typename AllocHolder::NodePtr NodePtr; @@ -461,7 +476,7 @@ class tree typedef typename Icont::const_iterator iconst_iterator; typedef dtl::allocator_destroyer Destroyer; typedef typename AllocHolder::alloc_version alloc_version; - typedef intrusive_tree_proxy intrusive_tree_proxy_t; + typedef intrusive_tree_proxy intrusive_tree_proxy_t; BOOST_COPYABLE_AND_MOVABLE(tree) diff --git a/include/boost/container/detail/value_functors.hpp b/include/boost/container/detail/value_functors.hpp new file mode 100644 index 0000000..a2c494c --- /dev/null +++ b/include/boost/container/detail/value_functors.hpp @@ -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 +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +//Functors for member algorithm defaults +template +struct value_less +{ + bool operator()(const ValueType &a, const ValueType &b) const + { return a < b; } +}; + +template +struct value_equal +{ + bool operator()(const ValueType &a, const ValueType &b) const + { return a == b; } +}; + +#endif //BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index bd039b7..c74372f 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -33,6 +33,7 @@ #include #include #include +#include // move #include #include @@ -1204,7 +1205,7 @@ class list //! Note: 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()); } //! Effects: Removes adjacent duplicate elements or adjacent //! elements that satisfy some binary predicate from the list. @@ -1234,7 +1235,7 @@ class list //! Complexity: 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()); } //! Requires: The lists x and *this must be distinct. //! @@ -1300,7 +1301,7 @@ class list //! Complexity: 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()); } //! Effects: This function sorts the list *this according to std::less. //! 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_less_t; + typedef value_equal value_equal_t; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; diff --git a/include/boost/container/options.hpp b/include/boost/container/options.hpp index da8b6a7..2ac7783 100644 --- a/include/boost/container/options.hpp +++ b/include/boost/container/options.hpp @@ -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 @@ -37,6 +55,8 @@ struct tree_opt static const bool optimize_size = OptimizeSize; }; +typedef tree_opt 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 +using tree_assoc_options_t = typename boost::container::tree_assoc_options::type; + +#endif + +//////////////////////////////////////////////////////////////// +// +// +// OPTIONS FOR VECTOR-BASED CONTAINERS +// +// +//////////////////////////////////////////////////////////////// + +#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + +template +struct get_stored_size_type_with_alloctraits +{ + typedef StoredSizeType type; +}; + +template +struct get_stored_size_type_with_alloctraits +{ + typedef typename AllocTraits::size_type type; +}; + +template +struct vector_opt +{ + typedef GrowthType growth_factor_type; + typedef StoredSizeType stored_size_type; + + template + struct get_stored_size_type + : get_stored_size_type_with_alloctraits + {}; +}; + +class default_next_capacity; + +typedef vector_opt 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:

+//!`template`
+//!`SizeType operator()(SizeType cur_cap, SizeType add_min_cap, SizeType max_cap) const;`.

+//!`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::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::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 +#else +template +#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 +using vector_options_t = typename boost::container::vector_options::type; + +#endif + + } //namespace container { } //namespace boost { diff --git a/include/boost/container/pmr/flat_map.hpp b/include/boost/container/pmr/flat_map.hpp index 150d533..76c697b 100644 --- a/include/boost/container/pmr/flat_map.hpp +++ b/include/boost/container/pmr/flat_map.hpp @@ -26,14 +26,12 @@ namespace pmr { template - ,class Options = tree_assoc_defaults > + ,class Compare = std::less > using flat_map = boost::container::flat_map > >; template - ,class Options = tree_assoc_defaults > + ,class Compare = std::less > using flat_multimap = boost::container::flat_multimap > >; #endif @@ -42,8 +40,7 @@ using flat_multimap = boost::container::flat_multimap - ,class Options = tree_assoc_defaults > + ,class Compare = std::less > struct flat_map_of { typedef boost::container::flat_map > > type; @@ -53,8 +50,7 @@ struct flat_map_of //! that uses a polymorphic allocator template - ,class Options = tree_assoc_defaults > + ,class Compare = std::less > struct flat_multimap_of { typedef boost::container::flat_multimap > > type; diff --git a/include/boost/container/pmr/flat_set.hpp b/include/boost/container/pmr/flat_set.hpp index 6d4292b..f072c95 100644 --- a/include/boost/container/pmr/flat_set.hpp +++ b/include/boost/container/pmr/flat_set.hpp @@ -25,13 +25,11 @@ namespace pmr { #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template - ,class Options = tree_assoc_defaults > + ,class Compare = std::less > using flat_set = boost::container::flat_set >; template - ,class Options = tree_assoc_defaults > + ,class Compare = std::less > using flat_multiset = boost::container::flat_multiset >; #endif @@ -39,8 +37,7 @@ using flat_multiset = boost::container::flat_multiset - ,class Options = tree_assoc_defaults > + ,class Compare = std::less > struct flat_set_of { typedef boost::container::flat_set > type; @@ -49,8 +46,7 @@ struct flat_set_of //! A portable metafunction to obtain a flat_multiset //! that uses a polymorphic allocator template - ,class Options = tree_assoc_defaults > + ,class Compare = std::less > struct flat_multiset_of { typedef boost::container::flat_multiset > type; diff --git a/include/boost/container/pmr/map.hpp b/include/boost/container/pmr/map.hpp index 165a473..7182160 100644 --- a/include/boost/container/pmr/map.hpp +++ b/include/boost/container/pmr/map.hpp @@ -27,13 +27,13 @@ namespace pmr { template - ,class Options = tree_assoc_defaults > + ,class Options = void > using map = boost::container::map >, Options>; template - ,class Options = tree_assoc_defaults > + ,class Options = void > using multimap = boost::container::multimap >, Options>; #endif @@ -43,7 +43,7 @@ using multimap = boost::container::multimap - ,class Options = tree_assoc_defaults > + ,class Options = void > struct map_of { typedef boost::container::map >, Options> type; @@ -54,7 +54,7 @@ struct map_of template - ,class Options = tree_assoc_defaults > + ,class Options = void > struct multimap_of { typedef boost::container::multimap >, Options> type; diff --git a/include/boost/container/pmr/set.hpp b/include/boost/container/pmr/set.hpp index 04583ce..3201696 100644 --- a/include/boost/container/pmr/set.hpp +++ b/include/boost/container/pmr/set.hpp @@ -26,12 +26,12 @@ namespace pmr { template - ,class Options = tree_assoc_defaults > + ,class Options = void > using set = boost::container::set, Options>; template - ,class Options = tree_assoc_defaults > + ,class Options = void > using multiset = boost::container::multiset, Options>; #endif @@ -40,7 +40,7 @@ using multiset = boost::container::multiset - ,class Options = tree_assoc_defaults > + ,class Options = void > struct set_of { typedef boost::container::set, Options> type; @@ -50,7 +50,7 @@ struct set_of //! that uses a polymorphic allocator template - ,class Options = tree_assoc_defaults > + ,class Options = void > struct multiset_of { typedef boost::container::multiset, Options> type; diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 1bff1a3..f6cde19 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -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 Allocator = new_allocator, class Options = tree_assoc_defaults > +template , class Allocator = new_allocator, class Options = void> #else template #endif diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 272a11c..8159f11 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -34,6 +34,7 @@ #include #include #include +#include // intrusive #include #include @@ -1165,7 +1166,7 @@ class slist //! Note: 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()); } //! Effects: Removes adjacent duplicate elements or adjacent //! elements that satisfy some binary predicate from the list. @@ -1195,7 +1196,7 @@ class slist //! Complexity: 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()); } //! Requires: The lists x and *this must be distinct. //! @@ -1261,7 +1262,7 @@ class slist //! Complexity: 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()); } //! Effects: This function sorts the list *this according to std::less. //! 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_less_t; + typedef value_equal 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 }; diff --git a/include/boost/container/small_vector.hpp b/include/boost/container/small_vector.hpp index 0cb1db2..7f8b8f6 100644 --- a/include/boost/container/small_vector.hpp +++ b/include/boost/container/small_vector.hpp @@ -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 > vector_alloc_holder_t; + typedef typename allocator_traits_type::size_type size_type; + typedef vector_alloc_holder< small_vector_allocator, size_type > vector_alloc_holder_t; typedef vector > vector_base; typedef small_vector_base derived_type; // @@ -350,7 +351,6 @@ class small_vector_base typedef small_vector_allocator 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 BOOST_COPYABLE_AND_MOVABLE(small_vector) - typedef typename base_type::initial_capacity_t initial_capacity_t; typedef allocator_traits allocator_traits_type; public: diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index d6c8be2..8418d39 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -292,10 +292,8 @@ class basic_string_base size_type next_capacity(size_type additional_objects) const { - return next_capacity_calculator - :: - 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) diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 0c33606..0d26181 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -27,6 +27,7 @@ #include #include //new_allocator #include +#include // container detail #include #include //equal() @@ -39,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -73,8 +75,6 @@ namespace container { #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED -namespace dtl { - template class vec_iterator { @@ -82,7 +82,7 @@ class vec_iterator typedef std::random_access_iterator_tag iterator_category; typedef typename boost::intrusive::pointer_traits::element_type value_type; typedef typename boost::intrusive::pointer_traits::difference_type difference_type; - typedef typename if_c + typedef typename dtl::if_c < IsConst , typename boost::intrusive::pointer_traits::template rebind_pointer::type @@ -244,30 +244,28 @@ struct vector_merge_cursor Comp &m_cmp; }; -} //namespace dtl { +struct initial_capacity_t{}; template -BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const dtl::vec_iterator &it) BOOST_NOEXCEPT_OR_NOTHROW +BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const vec_iterator &it) BOOST_NOEXCEPT_OR_NOTHROW { return it.get_ptr(); } template -BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(dtl::vec_iterator &it) BOOST_NOEXCEPT_OR_NOTHROW +BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(vec_iterator &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 struct vector_value_traits_base { - static const bool trivial_dctr = is_trivially_destructible::value; + static const bool trivial_dctr = dtl::is_trivially_destructible::value; static const bool trivial_dctr_after_move = has_trivial_destructor_after_move::value; - static const bool trivial_copy = is_trivially_copy_constructible::value; - static const bool nothrow_copy = is_nothrow_copy_constructible::value || trivial_copy; - static const bool trivial_assign = is_trivially_copy_assignable::value; - static const bool nothrow_assign = is_nothrow_copy_assignable::value || trivial_assign; + static const bool trivial_copy = dtl::is_trivially_copy_constructible::value; + static const bool nothrow_copy = dtl::is_nothrow_copy_constructible::value || trivial_copy; + static const bool trivial_assign = dtl::is_trivially_copy_assignable::value; + static const bool nothrow_assign = dtl::is_nothrow_copy_assignable::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::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_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 - 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(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(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(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(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(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(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(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::value) : Allocator() , m_start(p) , m_size() - , m_capacity(n) + //n is guaranteed to fit into stored_size_type + , m_capacity(static_cast(n)) {} template - 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(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 + size_type next_capacity(size_type additional_objects) const { - return next_capacity_calculator - ::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 + 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 -struct vector_alloc_holder +template +struct vector_alloc_holder : public Allocator { private: @@ -530,8 +585,9 @@ struct vector_alloc_holder 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 + template friend struct vector_alloc_holder; //Constructor, does not throw @@ -548,7 +604,7 @@ struct vector_alloc_holder //Constructor, does not throw template - 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(a)) , m_size(initial_size) //Size is initialized here... { @@ -557,7 +613,7 @@ struct vector_alloc_holder } //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 (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start())); } - template - vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder BOOST_RV_REF_END holder) + template + vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder 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 this->priv_deep_swap(x); } - template - void deep_swap(vector_alloc_holder &x) + template + void deep_swap(vector_alloc_holder &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 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 - void priv_deep_swap(vector_alloc_holder &x) + template + void priv_deep_swap(vector_alloc_holder &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 } }; -} //namespace dtl { +struct growth_factor_60; + +template +struct default_if_void +{ + typedef T type; +}; + +template +struct default_if_void +{ + typedef Default type; +}; + +template +struct get_vector_opt +{ + typedef vector_opt< typename default_if_void::type + , typename default_if_void::type + > type; +}; + +template +struct get_vector_opt +{ + typedef vector_opt type; +}; + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -660,28 +743,32 @@ struct vector_alloc_holder //! //! \tparam T The type of object that is stored in the vector //! \tparam Allocator The allocator used for all internal memory management -template ) > +//! \tparam Options A type produced from \c boost::container::vector_options. +template ), class Options BOOST_CONTAINER_DOCONLY(= void) > class vector { #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - struct value_less - { - typedef typename boost::container::allocator_traits::value_type value_type; - bool operator()(const value_type &a, const value_type &b) const - { return a < b; } - }; + typedef typename boost::container::allocator_traits::size_type alloc_size_type; + typedef typename get_vector_opt::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 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::value) ); typedef typename dtl::version::type alloc_version; - typedef boost::container::dtl::vector_alloc_holder alloc_holder_t; + typedef boost::container::vector_alloc_holder alloc_holder_t; alloc_holder_t m_holder; typedef allocator_traits allocator_traits_type; - template + template friend class vector; typedef typename allocator_traits_type::pointer pointer_impl; - typedef dtl::vec_iterator iterator_impl; - typedef dtl::vec_iterator const_iterator_impl; + typedef vec_iterator iterator_impl; + typedef vec_iterator 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 value_traits; + typedef vector_value_traits value_traits; typedef constant_iterator 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 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(a)) + : m_holder(initial_capacity_t(), initial_memory, capacity, ::boost::forward(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 //! //! Complexity: 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 //! //! Complexity: 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 //! //! Note: 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 //! //! Note: 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 //! //! Complexity: 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 //! //! Complexity: 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 //! //! Complexity: 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 //! //! Complexity: 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 //! //! Complexity: 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 //! Throws: Nothing. //! //! Complexity: 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(); } //! Effects: Returns true if x and y are equal //! //! Complexity: 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()); } //! Effects: Returns true if x and y are unequal //! //! Complexity: 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); } //! Effects: Returns true if x is less than y @@ -2060,25 +2146,25 @@ class vector //! Effects: Returns true if x is greater than y //! //! Complexity: 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; } //! Effects: Returns true if x is equal or less than y //! //! Complexity: 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); } //! Effects: Returns true if x is equal or greater than y //! //! Complexity: 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); } //! Effects: x.swap(y) //! //! Complexity: 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 - 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 inserter_t; + typedef vector_insert_ordered_cursor inserter_t; return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it)); } template - 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 - 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 - 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 - 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 - 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 priv_resize_proxy(const T &x) + BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy priv_resize_proxy(const T &x) { return dtl::insert_n_copies_proxy(x); } - dtl::insert_default_initialized_n_proxy priv_resize_proxy(default_init_t) + BOOST_CONTAINER_FORCEINLINE dtl::insert_default_initialized_n_proxy priv_resize_proxy(default_init_t) { return dtl::insert_default_initialized_n_proxy(); } - dtl::insert_value_initialized_n_proxy priv_resize_proxy(value_init_t) + BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy priv_resize_proxy(value_init_t) { return dtl::insert_value_initialized_n_proxy(); } template @@ -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(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(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 - 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()); } diff --git a/proj/vc7ide/container.sln b/proj/vc7ide/container.sln index bce3d02..17abc0c 100644 --- a/proj/vc7ide/container.sln +++ b/proj/vc7ide/container.sln @@ -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 diff --git a/proj/vc7ide/doc_custom_vector.vcproj b/proj/vc7ide/doc_custom_vector.vcproj new file mode 100644 index 0000000..8faafca --- /dev/null +++ b/proj/vc7ide/doc_custom_vector.vcproj @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_extended_allocators.vcproj b/proj/vc7ide/doc_extended_allocators.vcproj index 945ace3..2ffacc3 100644 --- a/proj/vc7ide/doc_extended_allocators.vcproj +++ b/proj/vc7ide/doc_extended_allocators.vcproj @@ -13,7 +13,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/vector_options_test.cpp b/test/vector_options_test.cpp new file mode 100644 index 0000000..9b414fb --- /dev/null +++ b/test/vector_options_test.cpp @@ -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 +#include +#include +#include + +using namespace boost::container; + +template +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 +void test_stored_size_type() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = vector_options_t< stored_size >; + #else + typedef typename vector_options + < stored_size >::type options_t; + #endif + + //Test first with a typical allocator + { + typedef vector, options_t> vector_t; + test_stored_size_type_impl(); + } + //Test with a V2 allocator + { + typedef vector, options_t> vector_t; + test_stored_size_type_impl(); + } +} + +void test_growth_factor_50() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = vector_options_t< growth_factor >; + #else + typedef vector_options + < growth_factor >::type options_t; + #endif + + vector, 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 >; + #else + typedef vector_options + < growth_factor >::type options_t; + #endif + + vector, 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 >; + #else + typedef vector_options + < growth_factor >::type options_t; + #endif + + vector, 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(); + test_stored_size_type(); + return ::boost::report_errors(); +} diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 5b8f431..25fe1af 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -38,13 +38,9 @@ template class boost::container::vector < test::movable_and_copyable_int , allocator >; -namespace dtl { - template class vec_iterator; template class vec_iterator; -} - }} int test_expand_bwd()