Added support for configurable tree-based associative containers. In addition to RB trees, AVL, Scapegoat and Splay trees are experimentally supported.

This commit is contained in:
Ion Gaztañaga
2014-01-03 13:26:57 +01:00
parent 2489010881
commit 01486761a6
21 changed files with 1193 additions and 155 deletions

View File

@@ -290,6 +290,15 @@ template<class BoostClass, class StdClass>
void launch_tests(const char *BoostContName, const char *StdContName) void launch_tests(const char *BoostContName, const char *StdContName)
{ {
try { try {
std::cout << "**********************************************" << '\n';
std::cout << "**********************************************" << '\n';
std::cout << "**********************************************" << '\n';
std::cout << '\n';
std::cout << BoostContName << " .VS " << StdContName << '\n';
std::cout << '\n';
std::cout << "**********************************************" << '\n';
std::cout << "**********************************************" << '\n';
std::cout << "**********************************************" << '\n' << std::endl;
fill_ranges(); fill_ranges();
{ {
std::cout << "Construct benchmark:" << BoostContName << std::endl; std::cout << "Construct benchmark:" << BoostContName << std::endl;
@@ -333,20 +342,36 @@ void launch_tests(const char *BoostContName, const char *StdContName)
int main() int main()
{ {
using namespace boost::container;
//set vs std::set //set vs std::set
launch_tests< boost::container::set<int> , std::set<int> > launch_tests< set<int> , std::set<int> >
("boost::container::set<int>", "std::set<int>"); ("set<int>", "std::set<int>");
//set(RB) vs set(AVL)
launch_tests< set<int>, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree> >::type > >
("set<int>(RB)", "set<int>(AVL)");
//set(RB) vs set(SG)
launch_tests< set<int>, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<scapegoat_tree> >::type > >
("set<int>(RB)", "set<int>(SG)");
launch_tests< set<int>, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<splay_tree> >::type > >
("set<int>(RB)", "set<int>(SP)");
//set(sizeopt) vs set(!sizeopt)
launch_tests< set<int>, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< optimize_size<false> >::type > >
("set<int>(sizeopt=true)", "set<int>(sizeopt=false)");
//set(AVL,sizeopt) vs set(AVL,!sizeopt)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree> >::type >
, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree>, optimize_size<false> >::type > >
("set<int>(AVL,sizeopt=true)", "set<int>(AVL,sizeopt=false)");
//set vs set<..., allocator_v2> //set vs set<..., allocator_v2>
launch_tests< boost::container::set<int> , boost::container::set<int, std::less<int>, boost::container::allocator<int> > > launch_tests< set<int> , set<int, std::less<int>, allocator<int> > >
("boost::container::set<int>", "boost::container::set<int, ..., boost::container::allocator<int>" ); ("set<int>", "set<int, ..., allocator<int>" );
//multiset vs std::set //multiset vs std::set
launch_tests< boost::container::multiset<int> , std::multiset<int> > launch_tests< multiset<int> , std::multiset<int> >
("boost::container::multiset<int>", "std::multiset<int>"); ("multiset<int>", "std::multiset<int>");
//flat_set vs set //flat_set vs set
launch_tests< boost::container::flat_set<int> , boost::container::set<int> > launch_tests< flat_set<int> , set<int> >
("boost::container::flat_set<int>", "boost::container::set<int>"); ("flat_set<int>", "set<int>");
//flat_multiset vs multiset //flat_multiset vs multiset
launch_tests< boost::container::flat_multiset<int> , boost::container::multiset<int> > launch_tests< flat_multiset<int> , multiset<int> >
("boost::container::flat_multiset<int>", "boost::container::multiset<int>"); ("flat_multiset<int>", "multiset<int>");
return 0; return 0;
} }

View File

@@ -35,7 +35,9 @@ doxygen autodoc
\"BOOST_RV_REF_BEG=\" \\ \"BOOST_RV_REF_BEG=\" \\
\"BOOST_RV_REF_END=&&\" \\ \"BOOST_RV_REF_END=&&\" \\
\"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\ \"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\
\"BOOST_FWD_REF(a)=a &&\"" \"BOOST_FWD_REF(a)=a &&\" \\
\"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template<TYPE VALUE> struct OPTION_NAME{};\" \\
\"BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) = template<class TYPE> struct OPTION_NAME{};\" "
<xsl:param>"boost.doxygen.reftitle=Boost.Container Header Reference" <xsl:param>"boost.doxygen.reftitle=Boost.Container Header Reference"
; ;

View File

@@ -549,6 +549,46 @@ times.
[endsect] [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`] [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, In the first C++ standard `list::size()` was not required to be constant-time,
@@ -637,6 +677,11 @@ The following extended allocators are provided:
to the system. The overhead can be very low (< 5% for small nodes) and it's nearly as fast as [classref boost::container::node_allocator node_allocator]. to the system. The overhead can be very low (< 5% for small nodes) and it's nearly as fast as [classref boost::container::node_allocator node_allocator].
It's also suitable for node containers. It's also suitable for node containers.
Use them simply specifying the new allocator in the corresponding template argument of your favourite container:
[import ../example/doc_extended_allocators.cpp]
[doc_extended_allocators]
[endsect] [endsect]
[/ [/
@@ -880,6 +925,11 @@ use [*Boost.Container]? There are several reasons for that:
* Added DlMalloc-based [link container.extended_functionality.extended_allocators Extended Allocators]. * Added DlMalloc-based [link container.extended_functionality.extended_allocators Extended Allocators].
* [link container.extended_functionality.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].
* Fixed bugs: * Fixed bugs:
* [@https://svn.boost.org/trac/boost/ticket/9338 #9338: ['"VS2005 compiler errors in swap() definition after including container/memory_util.hpp"]]. * [@https://svn.boost.org/trac/boost/ticket/9338 #9338: ['"VS2005 compiler errors in swap() definition after including container/memory_util.hpp"]].

View File

@@ -21,7 +21,7 @@ rule test_all
for local fileb in [ glob doc_*.cpp ] for local fileb in [ glob doc_*.cpp ]
{ {
all_rules += [ run $(fileb) all_rules += [ run $(fileb) /boost/container//boost_container /boost/timer//boost_timer
: # additional args : # additional args
: # test-files : # test-files
: # requirements : # requirements

View File

@@ -0,0 +1,64 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
//[doc_custom_tree
#include <boost/container/set.hpp>
#include <cassert>
int main ()
{
using namespace boost::container;
//First define several options
//
//This option specifies an AVL tree based associative container
typedef tree_assoc_options< tree_type<avl_tree> >::type AVLTree;
//This option specifies an AVL tree based associative container
//disabling node size optimization.
typedef tree_assoc_options< tree_type<avl_tree>
, optimize_size<false> >::type AVLTreeNoSizeOpt;
//This option specifies an Splay tree based associative container
typedef tree_assoc_options< tree_type<splay_tree> >::type SplayTree;
//Now define new tree-based associative containers
//
//AVLTree based set container
typedef set<int, std::less<int>, std::allocator<int>, AVLTree> AvlSet;
//AVLTree based set container without size optimization
typedef set<int, std::less<int>, std::allocator<int>, AVLTreeNoSizeOpt> AvlSetNoSizeOpt;
//Splay tree based multiset container
typedef multiset<int, std::less<int>, std::allocator<int>, SplayTree> SplayMultiset;
//Use them
//
AvlSet avl_set;
avl_set.insert(0);
assert(avl_set.find(0) != avl_set.end());
AvlSetNoSizeOpt avl_set_no_szopt;
avl_set_no_szopt.insert(1);
avl_set_no_szopt.insert(1);
assert(avl_set_no_szopt.count(1) == 1);
SplayMultiset splay_mset;
splay_mset.insert(2);
splay_mset.insert(2);
assert(splay_mset.count(2) == 2);
return 0;
}
//]
#include <boost/container/detail/config_end.hpp>

View File

@@ -0,0 +1,54 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
//[doc_extended_allocators
#include <boost/container/vector.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/container/list.hpp>
#include <boost/container/set.hpp>
//"allocator" is a general purpose allocator that can reallocate
//memory, something useful for vector and flat associative containers
#include <boost/container/allocator.hpp>
//"adaptive_pool" is a node allocator, specially suited for
//node-based containers
#include <boost/container/adaptive_pool.hpp>
int main ()
{
using namespace boost::container;
//A vector that can reallocate memory to implement faster insertions
vector<int, allocator<int> > extended_alloc_vector;
//A flat set that can reallocate memory to implement faster insertions
flat_set<int, std::less<int>, allocator<int> > extended_alloc_flat_set;
//A list that can manages nodes to implement faster
//range insertions and deletions
list<int, adaptive_pool<int> > extended_alloc_list;
//A set that can recycle nodes to implement faster
//range insertions and deletions
set<int, std::less<int>, adaptive_pool<int> > extended_alloc_set;
//Now user them as always
extended_alloc_vector.push_back(0);
extended_alloc_flat_set.insert(0);
extended_alloc_list.push_back(0);
extended_alloc_set.insert(0);
//...
return 0;
}
//]
#include <boost/container/detail/config_end.hpp>

View File

@@ -16,7 +16,7 @@
#endif #endif
//! \file //! \file
//! This header file forward declares the following classes: //! This header file forward declares the following containers:
//! - boost::container::vector //! - boost::container::vector
//! - boost::container::stable_vector //! - boost::container::stable_vector
//! - boost::container::static_vector //! - boost::container::static_vector
@@ -33,11 +33,13 @@
//! - boost::container::basic_string //! - boost::container::basic_string
//! - boost::container::string //! - boost::container::string
//! - boost::container::wstring //! - boost::container::wstring
//!
//! It forward declares the following allocators:
//! - boost::container::allocator //! - boost::container::allocator
//! - boost::container::node_allocator //! - boost::container::node_allocator
//! - boost::container::adaptive_pool //! - boost::container::adaptive_pool
//! //!
//! and defines the following types: //! And finally it defines the following types
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Standard predeclarations // Standard predeclarations
@@ -74,7 +76,7 @@ namespace container {
//! Enumeration used to configure ordered associative containers //! Enumeration used to configure ordered associative containers
//! with a concrete tree implementation. //! with a concrete tree implementation.
enum tree_type enum tree_type_enum
{ {
red_black_tree, red_black_tree,
avl_tree, avl_tree,
@@ -107,30 +109,35 @@ template <class T
,class Allocator = std::allocator<T> > ,class Allocator = std::allocator<T> >
class slist; class slist;
template<tree_type_enum TreeType, bool OptimizeSize>
struct tree_opt;
typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
template <class Key template <class Key
,class Compare = std::less<Key> ,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> ,class Allocator = std::allocator<Key>
,tree_type = red_black_tree > ,class Options = tree_assoc_defaults >
class set; class set;
template <class Key template <class Key
,class Compare = std::less<Key> ,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> ,class Allocator = std::allocator<Key>
,tree_type = red_black_tree > ,class Options = tree_assoc_defaults >
class multiset; class multiset;
template <class Key template <class Key
,class T ,class T
,class Compare = std::less<Key> ,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<const Key, T> > ,class Allocator = std::allocator<std::pair<const Key, T> >
,tree_type = red_black_tree > ,class Options = tree_assoc_defaults >
class map; class map;
template <class Key template <class Key
,class T ,class T
,class Compare = std::less<Key> ,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<const Key, T> > ,class Allocator = std::allocator<std::pair<const Key, T> >
,tree_type = red_black_tree > ,class Options = tree_assoc_defaults >
class multimap; class multimap;
template <class Key template <class Key
@@ -198,6 +205,13 @@ template
, std::size_t Version = 2> , std::size_t Version = 2>
class node_allocator; class node_allocator;
#else
//! Default options for tree-based associative containers
//! - tree_type<red_black_tree>
//! - optimize_size<true>
typedef implementation_defined tree_assoc_defaults;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! Type used to tag that the input range is //! Type used to tag that the input range is

View File

@@ -23,6 +23,8 @@
#include <boost/container/detail/pair.hpp> #include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp> #include <boost/container/allocator_traits.hpp>
#include <boost/container/options.hpp>
// //
#include <boost/intrusive/pointer_traits.hpp> #include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/rbtree.hpp> #include <boost/intrusive/rbtree.hpp>
@@ -90,13 +92,44 @@ struct tree_value_compare
{ return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
}; };
template<class VoidPointer> template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
struct intrusive_tree_hook struct intrusive_tree_hook;
template<class VoidPointer, bool OptimizeSize>
struct intrusive_tree_hook<VoidPointer, boost::container::red_black_tree, OptimizeSize>
{ {
typedef typename container_detail::bi::make_set_base_hook typedef typename container_detail::bi::make_set_base_hook
< container_detail::bi::void_pointer<VoidPointer> < container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link> , container_detail::bi::link_mode<container_detail::bi::normal_link>
, container_detail::bi::optimize_size<true> , container_detail::bi::optimize_size<OptimizeSize>
>::type type;
};
template<class VoidPointer, bool OptimizeSize>
struct intrusive_tree_hook<VoidPointer, boost::container::avl_tree, OptimizeSize>
{
typedef typename container_detail::bi::make_avl_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
, container_detail::bi::optimize_size<OptimizeSize>
>::type type;
};
template<class VoidPointer, bool OptimizeSize>
struct intrusive_tree_hook<VoidPointer, boost::container::scapegoat_tree, OptimizeSize>
{
typedef typename container_detail::bi::make_bs_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
>::type type;
};
template<class VoidPointer, bool OptimizeSize>
struct intrusive_tree_hook<VoidPointer, boost::container::splay_tree, OptimizeSize>
{
typedef typename container_detail::bi::make_bs_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
>::type type; >::type type;
}; };
@@ -114,23 +147,23 @@ struct tree_internal_data_type< std::pair<T1, T2> >
typedef pair<T1, T2> type; typedef pair<T1, T2> type;
}; };
//The node to be store in the tree //The node to be store in the tree
template <class T, class VoidPointer> template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
struct tree_node struct tree_node
: public intrusive_tree_hook<VoidPointer>::type : public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type
{ {
private: private:
//BOOST_COPYABLE_AND_MOVABLE(tree_node) //BOOST_COPYABLE_AND_MOVABLE(tree_node)
tree_node(); tree_node();
public: public:
typedef typename intrusive_tree_hook<VoidPointer>::type hook_type; typedef typename intrusive_tree_hook
<VoidPointer, tree_type_value, OptimizeSize>::type hook_type;
typedef T value_type; typedef T value_type;
typedef typename tree_internal_data_type<T>::type internal_type; typedef typename tree_internal_data_type<T>::type internal_type;
typedef tree_node<T, VoidPointer> node_type; typedef tree_node< T, VoidPointer
, tree_type_value, OptimizeSize> node_type;
T &get_data() T &get_data()
{ {
@@ -215,12 +248,67 @@ class push_back_functor
namespace container_detail { namespace container_detail {
template<class A, class ValueCompare, boost::container::tree_type tree_type_value> template< class NodeType, class NodeCompareType
struct intrusive_tree_type; , class SizeType, class HookType
, boost::container::tree_type_enum tree_type_value>
struct intrusive_tree_dispatch;
template<class A, class ValueCompare> template<class NodeType, class NodeCompareType, class SizeType, class HookType>
struct intrusive_tree_type<A, ValueCompare, boost::container::red_black_tree> struct intrusive_tree_dispatch
<NodeType, NodeCompareType, SizeType, HookType, boost::container::red_black_tree>
{ {
typedef typename container_detail::bi::make_rbtree
<NodeType
,container_detail::bi::compare<NodeCompareType>
,container_detail::bi::base_hook<HookType>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<SizeType>
>::type type;
};
template<class NodeType, class NodeCompareType, class SizeType, class HookType>
struct intrusive_tree_dispatch
<NodeType, NodeCompareType, SizeType, HookType, boost::container::avl_tree>
{
typedef typename container_detail::bi::make_avltree
<NodeType
,container_detail::bi::compare<NodeCompareType>
,container_detail::bi::base_hook<HookType>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<SizeType>
>::type type;
};
template<class NodeType, class NodeCompareType, class SizeType, class HookType>
struct intrusive_tree_dispatch
<NodeType, NodeCompareType, SizeType, HookType, boost::container::scapegoat_tree>
{
typedef typename container_detail::bi::make_sgtree
<NodeType
,container_detail::bi::compare<NodeCompareType>
,container_detail::bi::base_hook<HookType>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<SizeType>
>::type type;
};
template<class NodeType, class NodeCompareType, class SizeType, class HookType>
struct intrusive_tree_dispatch
<NodeType, NodeCompareType, SizeType, HookType, boost::container::splay_tree>
{
typedef typename container_detail::bi::make_splaytree
<NodeType
,container_detail::bi::compare<NodeCompareType>
,container_detail::bi::base_hook<HookType>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<SizeType>
>::type type;
};
template<class A, class ValueCompare, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
struct intrusive_tree_type
{
private:
typedef typename boost::container:: typedef typename boost::container::
allocator_traits<A>::value_type value_type; allocator_traits<A>::value_type value_type;
typedef typename boost::container:: typedef typename boost::container::
@@ -228,16 +316,49 @@ struct intrusive_tree_type<A, ValueCompare, boost::container::red_black_tree>
typedef typename boost::container:: typedef typename boost::container::
allocator_traits<A>::size_type size_type; allocator_traits<A>::size_type size_type;
typedef typename container_detail::tree_node typedef typename container_detail::tree_node
<value_type, void_pointer> node_type; < value_type, void_pointer
, tree_type_value, OptimizeSize> node_type;
typedef node_compare<ValueCompare, node_type> node_compare_type; typedef node_compare<ValueCompare, node_type> node_compare_type;
typedef typename container_detail::bi::make_rbtree //Deducing the hook type from node_type (e.g. node_type::hook_type) would
<node_type //provoke an early instantiation of node_type that could ruin recursive
,container_detail::bi::compare<node_compare_type> //tree definitions, so retype the complete type to avoid any problem.
,container_detail::bi::base_hook<typename intrusive_tree_hook<void_pointer>::type> typedef typename intrusive_tree_hook
,container_detail::bi::constant_time_size<true> <void_pointer, tree_type_value
,container_detail::bi::size_type<size_type> , OptimizeSize>::type hook_type;
>::type container_type; public:
typedef container_type type ; typedef typename intrusive_tree_dispatch
< node_type, node_compare_type
, size_type, hook_type
, tree_type_value>::type type;
};
//Trait to detect manually rebalanceable tree types
template<boost::container::tree_type_enum tree_type_value>
struct is_manually_balanceable
{ static const bool value = true; };
template<> struct is_manually_balanceable<red_black_tree>
{ static const bool value = false; };
template<> struct is_manually_balanceable<avl_tree>
{ static const bool value = false; };
//Proxy traits to implement different operations depending on the
//is_manually_balanceable<>::value
template< boost::container::tree_type_enum tree_type_value
, bool IsManuallyRebalanceable = is_manually_balanceable<tree_type_value>::value>
struct intrusive_tree_proxy
{
template<class Icont>
static void rebalance(Icont &) {}
};
template<boost::container::tree_type_enum tree_type_value>
struct intrusive_tree_proxy<tree_type_value, true>
{
template<class Icont>
static void rebalance(Icont &c)
{ c.rebalance(); }
}; };
} //namespace container_detail { } //namespace container_detail {
@@ -326,24 +447,25 @@ struct key_node_compare
template <class Key, class Value, class KeyOfValue, template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A, class KeyCompare, class A,
boost::container::tree_type tree_type_value> class Options>
class tree class tree
: protected container_detail::node_alloc_holder : protected container_detail::node_alloc_holder
< A < A
, typename container_detail::intrusive_tree_type , typename container_detail::intrusive_tree_type
< A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> //ValComp < A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> //ValComp
, tree_type_value>::type , Options::tree_type, Options::optimize_size>::type
> >
{ {
typedef tree_value_compare typedef tree_value_compare
<Key, Value, KeyCompare, KeyOfValue> ValComp; <Key, Value, KeyCompare, KeyOfValue> ValComp;
typedef typename container_detail::intrusive_tree_type typedef typename container_detail::intrusive_tree_type
< A, ValComp, tree_type_value>::type Icont; < A, ValComp, Options::tree_type
, Options::optimize_size>::type Icont;
typedef container_detail::node_alloc_holder typedef container_detail::node_alloc_holder
<A, Icont> AllocHolder; <A, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr; typedef typename AllocHolder::NodePtr NodePtr;
typedef tree < Key, Value, KeyOfValue typedef tree < Key, Value, KeyOfValue
, KeyCompare, A, tree_type_value> ThisType; , KeyCompare, A, Options> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc; typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef typename AllocHolder::ValAlloc ValAlloc; typedef typename AllocHolder::ValAlloc ValAlloc;
typedef typename AllocHolder::Node Node; typedef typename AllocHolder::Node Node;
@@ -353,6 +475,7 @@ class tree
typedef typename AllocHolder::allocator_v1 allocator_v1; typedef typename AllocHolder::allocator_v1 allocator_v1;
typedef typename AllocHolder::allocator_v2 allocator_v2; typedef typename AllocHolder::allocator_v2 allocator_v2;
typedef typename AllocHolder::alloc_version alloc_version; typedef typename AllocHolder::alloc_version alloc_version;
typedef intrusive_tree_proxy<Options::tree_type> intrusive_tree_proxy_t;
BOOST_COPYABLE_AND_MOVABLE(tree) BOOST_COPYABLE_AND_MOVABLE(tree)
@@ -985,6 +1108,9 @@ class tree
(const_iterator(ret.first), const_iterator(ret.second)); (const_iterator(ret.first), const_iterator(ret.second));
} }
void rebalance()
{ intrusive_tree_proxy_t::rebalance(this->icont()); }
friend bool operator==(const tree& x, const tree& y) friend bool operator==(const tree& x, const tree& y)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); } { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }

View File

@@ -39,22 +39,26 @@
namespace boost { namespace boost {
namespace container { namespace container {
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A map is a kind of associative container that supports unique keys (contains at //! A map is a kind of associative container that supports unique keys (contains at
//! most one of each key value) and provides for fast retrieval of values of another //! most one of each key value) and provides for fast retrieval of values of another
//! type T based on the keys. The map class supports bidirectional iterators. //! type T based on the keys. The map class supports bidirectional iterators.
//! //!
//! A map satisfies all of the requirements of a container and of a reversible //! A map satisfies all of the requirements of a container and of a reversible
//! container and of an associative container. For a //! container and of an associative container. The <code>value_type</code> stored
//! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>. //! by this container is the value_type is std::pair<const Key, T>.
//! //!
//! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). //! \tparam Key is the key_type of the map
//! //! \tparam Value is the <code>mapped_type</code>
//! Allocator is the allocator to allocate the value_types //! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! (e.g. <i>allocator< std::pair<const Key, T> > </i>). //! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED //! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > > //! \tparam MapOptions is an packed option type generated using using boost::container::tree_assoc_options.
template < class Key, class T, class Compare = std::less<Key>
, class Allocator = std::allocator< std::pair< const Key, T> >, class MapOptions = tree_assoc_defaults >
#else #else
template <class Key, class T, class Compare, class Allocator, tree_type tree_type_value> template <class Key, class T, class Compare, class Allocator, class MapOptions>
#endif #endif
class map class map
{ {
@@ -64,7 +68,7 @@ class map
typedef std::pair<const Key, T> value_type_impl; typedef std::pair<const Key, T> value_type_impl;
typedef container_detail::tree typedef container_detail::tree
<Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator, tree_type_value> tree_t; <Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator, MapOptions> tree_t;
typedef container_detail::pair <Key, T> movable_value_type_impl; typedef container_detail::pair <Key, T> movable_value_type_impl;
typedef container_detail::tree_value_compare typedef container_detail::tree_value_compare
< Key, value_type_impl, Compare, container_detail::select1st<value_type_impl> < Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
@@ -744,26 +748,53 @@ class map
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return m_tree.equal_range(x); } { return m_tree.equal_range(x); }
//! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
//!
//! <b>Complexity</b>: Linear
void rebalance()
{ return m_tree.rebalance(); }
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const map& x, const map& y) friend bool operator==(const map& x, const map& y)
{ return x.m_tree == y.m_tree; } { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
friend bool operator<(const map& x, const map& y)
{ return x.m_tree < y.m_tree; }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const map& x, const map& y) friend bool operator!=(const map& x, const map& y)
{ return !(x == y); } { return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const map& x, const map& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const map& x, const map& y) friend bool operator>(const map& x, const map& y)
{ return y < x; } { return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const map& x, const map& y) friend bool operator<=(const map& x, const map& y)
{ return !(y < x); } { return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const map& x, const map& y) friend bool operator>=(const map& x, const map& y)
{ return !(x < y); } { return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(map& x, map& y) friend void swap(map& x, map& y)
{ x.swap(y); } { x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
@@ -814,23 +845,27 @@ namespace container {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A multimap is a kind of associative container that supports equivalent keys //! A multimap is a kind of associative container that supports equivalent keys
//! (possibly containing multiple copies of the same key value) and provides for //! (possibly containing multiple copies of the same key value) and provides for
//! fast retrieval of values of another type T based on the keys. The multimap class //! fast retrieval of values of another type T based on the keys. The multimap class
//! supports bidirectional iterators. //! supports bidirectional iterators.
//! //!
//! A multimap satisfies all of the requirements of a container and of a reversible //! A multimap satisfies all of the requirements of a container and of a reversible
//! container and of an associative container. For a //! container and of an associative container. The <code>value_type</code> stored
//! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>. //! by this container is the value_type is std::pair<const Key, T>.
//! //!
//! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). //! \tparam Key is the key_type of the map
//! //! \tparam Value is the <code>mapped_type</code>
//! Allocator is the allocator to allocate the value_types //! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//!(e.g. <i>allocator< std::pair<<b>const</b> Key, T> ></i>). //! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED //! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > > //! \tparam MultiMapOptions is an packed option type generated using using boost::container::tree_assoc_options.
template < class Key, class T, class Compare = std::less<Key>
, class Allocator = std::allocator< std::pair< const Key, T> >, class MultiMapOptions = tree_assoc_defaults>
#else #else
template <class Key, class T, class Compare, class Allocator, tree_type tree_type_value> template <class Key, class T, class Compare, class Allocator, class MultiMapOptions>
#endif #endif
class multimap class multimap
{ {
@@ -840,7 +875,7 @@ class multimap
typedef std::pair<const Key, T> value_type_impl; typedef std::pair<const Key, T> value_type_impl;
typedef container_detail::tree typedef container_detail::tree
<Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator, tree_type_value> tree_t; <Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator, MultiMapOptions> tree_t;
typedef container_detail::pair <Key, T> movable_value_type_impl; typedef container_detail::pair <Key, T> movable_value_type_impl;
typedef container_detail::tree_value_compare typedef container_detail::tree_value_compare
< Key, value_type_impl, Compare, container_detail::select1st<value_type_impl> < Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
@@ -1424,24 +1459,51 @@ class multimap
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return m_tree.equal_range(x); } { return m_tree.equal_range(x); }
//! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
//!
//! <b>Complexity</b>: Linear
void rebalance()
{ return m_tree.rebalance(); }
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const multimap& x, const multimap& y) friend bool operator==(const multimap& x, const multimap& y)
{ return x.m_tree == y.m_tree; } { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
friend bool operator<(const multimap& x, const multimap& y)
{ return x.m_tree < y.m_tree; }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const multimap& x, const multimap& y) friend bool operator!=(const multimap& x, const multimap& y)
{ return !(x == y); } { return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const multimap& x, const multimap& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const multimap& x, const multimap& y) friend bool operator>(const multimap& x, const multimap& y)
{ return y < x; } { return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const multimap& x, const multimap& y) friend bool operator<=(const multimap& x, const multimap& y)
{ return !(y < x); } { return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const multimap& x, const multimap& y) friend bool operator>=(const multimap& x, const multimap& y)
{ return !(x < y); } { return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(multimap& x, multimap& y) friend void swap(multimap& x, multimap& y)
{ x.swap(y); } { x.swap(y); }
}; };

View File

@@ -0,0 +1,72 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_OPTIONS_HPP
#define BOOST_CONTAINER_OPTIONS_HPP
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/intrusive/pack_options.hpp>
namespace boost {
namespace container {
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template<tree_type_enum TreeType, bool OptimizeSize>
struct tree_opt
{
static const boost::container::tree_type_enum tree_type = TreeType;
static const bool optimize_size = OptimizeSize;
};
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!This option setter specifies the underlying tree type
//!(red-black, AVL, Scapegoat or Splay) for ordered associative containers
BOOST_INTRUSIVE_OPTION_CONSTANT(tree_type, tree_type_enum, TreeType, tree_type)
//!This option setter specifies if node size is optimized
//!storing rebalancing data masked into pointers for ordered associative containers
BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size)
//! Helper metafunction to combine options into a single type to be used
//! by \c boost::container::set, \c boost::container::multiset
//! \c boost::container::map and \c boost::container::multimap.
//! Supported options are: \c boost::container::optimize_size and \c boost::container::tree_type
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
#endif
struct tree_assoc_options
{
/// @cond
typedef typename ::boost::intrusive::pack_options
< tree_assoc_defaults,
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
>::type packed_options;
typedef tree_opt<packed_options::tree_type, packed_options::optimize_size> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_OPTIONS_HPP

View File

@@ -35,6 +35,8 @@
namespace boost { namespace boost {
namespace container { namespace container {
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A set is a kind of associative container that supports unique keys (contains at //! A set is a kind of associative container that supports unique keys (contains at
//! most one of each key value) and provides for fast retrieval of the keys themselves. //! most one of each key value) and provides for fast retrieval of the keys themselves.
//! Class set supports bidirectional iterators. //! Class set supports bidirectional iterators.
@@ -42,10 +44,14 @@ namespace container {
//! A set satisfies all of the requirements of a container and of a reversible container //! A set satisfies all of the requirements of a container and of a reversible container
//! , and of an associative container. A set also provides most operations described in //! , and of an associative container. A set also provides most operations described in
//! for unique keys. //! for unique keys.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED //!
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> > //! \tparam Key is the type to be inserted in the set, which is also the key_type
//! \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 SetOptions is an packed option type generated using using boost::container::tree_assoc_options.
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>, class SetOptions = tree_assoc_defaults >
#else #else
template <class Key, class Compare, class Allocator, tree_type tree_type_value> template <class Key, class Compare, class Allocator, class SetOptions>
#endif #endif
class set class set
{ {
@@ -53,7 +59,7 @@ class set
private: private:
BOOST_COPYABLE_AND_MOVABLE(set) BOOST_COPYABLE_AND_MOVABLE(set)
typedef container_detail::tree typedef container_detail::tree
< Key, Key, container_detail::identity<Key>, Compare, Allocator, tree_type_value> tree_t; < Key, Key, container_detail::identity<Key>, Compare, Allocator, SetOptions> tree_t;
tree_t m_tree; // red-black tree representing set tree_t m_tree; // red-black tree representing set
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -589,24 +595,51 @@ class set
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return m_tree.equal_range(x); } { return m_tree.equal_range(x); }
//! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
//!
//! <b>Complexity</b>: Linear
void rebalance()
{ return m_tree.rebalance(); }
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const set& x, const set& y) friend bool operator==(const set& x, const set& y)
{ return x.m_tree == y.m_tree; } { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
friend bool operator<(const set& x, const set& y)
{ return x.m_tree < y.m_tree; }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const set& x, const set& y) friend bool operator!=(const set& x, const set& y)
{ return !(x == y); } { return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const set& x, const set& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const set& x, const set& y) friend bool operator>(const set& x, const set& y)
{ return y < x; } { return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const set& x, const set& y) friend bool operator<=(const set& x, const set& y)
{ return !(y < x); } { return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const set& x, const set& y) friend bool operator>=(const set& x, const set& y)
{ return !(x < y); } { return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(set& x, set& y) friend void swap(set& x, set& y)
{ x.swap(y); } { x.swap(y); }
@@ -628,8 +661,8 @@ class set
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class C, class Allocator> template <class Key, class C, class SetOptions, class Allocator>
struct has_trivial_destructor_after_move<boost::container::set<Key, C, Allocator> > struct has_trivial_destructor_after_move<boost::container::set<Key, C, Allocator, SetOptions> >
{ {
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
}; };
@@ -638,6 +671,8 @@ namespace container {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A multiset is a kind of associative container that supports equivalent keys //! A multiset is a kind of associative container that supports equivalent keys
//! (possibly contains multiple copies of the same key value) and provides for //! (possibly contains multiple copies of the same key value) and provides for
//! fast retrieval of the keys themselves. Class multiset supports bidirectional iterators. //! fast retrieval of the keys themselves. Class multiset supports bidirectional iterators.
@@ -645,10 +680,14 @@ namespace container {
//! A multiset satisfies all of the requirements of a container and of a reversible //! A multiset satisfies all of the requirements of a container and of a reversible
//! container, and of an associative container). multiset also provides most operations //! container, and of an associative container). multiset also provides most operations
//! described for duplicate keys. //! described for duplicate keys.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED //!
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> > //! \tparam Key is the type to be inserted in the set, which is also the key_type
//! \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 MultiSetOptions is an packed option type generated using using boost::container::tree_assoc_options.
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>, class MultiSetOptions = tree_assoc_defaults >
#else #else
template <class Key, class Compare, class Allocator, tree_type tree_type_value> template <class Key, class Compare, class Allocator, class MultiSetOptions>
#endif #endif
class multiset class multiset
{ {
@@ -656,7 +695,7 @@ class multiset
private: private:
BOOST_COPYABLE_AND_MOVABLE(multiset) BOOST_COPYABLE_AND_MOVABLE(multiset)
typedef container_detail::tree typedef container_detail::tree
<Key, Key,container_detail::identity<Key>, Compare, Allocator, tree_type_value> tree_t; <Key, Key,container_detail::identity<Key>, Compare, Allocator, MultiSetOptions> tree_t;
tree_t m_tree; // red-black tree representing multiset tree_t m_tree; // red-black tree representing multiset
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1182,24 +1221,51 @@ class multiset
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return m_tree.equal_range(x); } { return m_tree.equal_range(x); }
//! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
//!
//! <b>Complexity</b>: Linear
void rebalance()
{ return m_tree.rebalance(); }
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const multiset& x, const multiset& y) friend bool operator==(const multiset& x, const multiset& y)
{ return x.m_tree == y.m_tree; } { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
friend bool operator<(const multiset& x, const multiset& y)
{ return x.m_tree < y.m_tree; }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const multiset& x, const multiset& y) friend bool operator!=(const multiset& x, const multiset& y)
{ return !(x == y); } { return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const multiset& x, const multiset& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const multiset& x, const multiset& y) friend bool operator>(const multiset& x, const multiset& y)
{ return y < x; } { return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const multiset& x, const multiset& y) friend bool operator<=(const multiset& x, const multiset& y)
{ return !(y < x); } { return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const multiset& x, const multiset& y) friend bool operator>=(const multiset& x, const multiset& y)
{ return !(x < y); } { return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(multiset& x, multiset& y) friend void swap(multiset& x, multiset& y)
{ x.swap(y); } { x.swap(y); }
@@ -1222,8 +1288,8 @@ class multiset
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class C, class Allocator> template <class Key, class C, class Allocator, class MultiSetOptions>
struct has_trivial_destructor_after_move<boost::container::multiset<Key, C, Allocator> > struct has_trivial_destructor_after_move<boost::container::multiset<Key, C, Allocator, MultiSetOptions> >
{ {
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
}; };

View File

@@ -1423,6 +1423,9 @@ class slist
void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ this->splice(p, static_cast<slist&>(x), first, last); } { this->splice(p, static_cast<slist&>(x), first, last); }
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const slist& x, const slist& y) friend bool operator==(const slist& x, const slist& y)
{ {
if(x.size() != y.size()){ if(x.size() != y.size()){
@@ -1440,26 +1443,41 @@ class slist
return i1 == end1; return i1 == end1;
} }
friend bool operator<(const slist& x, const slist& y) //! <b>Effects</b>: Returns true if x and y are unequal
{ //!
return std::lexicographical_compare //! <b>Complexity</b>: Linear to the number of elements in the container.
(x.begin(), x.end(), y.begin(), y.end());
}
friend bool operator!=(const slist& x, const slist& y) friend bool operator!=(const slist& x, const slist& y)
{ return !(x == y); } { return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const slist& x, const slist& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const slist& x, const slist& y) friend bool operator>(const slist& x, const slist& y)
{ return y < x; } { return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const slist& x, const slist& y) friend bool operator<=(const slist& x, const slist& y)
{ return !(y < x); } { return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const slist& x, const slist& y) friend bool operator>=(const slist& x, const slist& y)
{ return !(x < y); } { return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(slist& x, slist& y) friend void swap(slist& x, slist& y)
{ x.swap(y); } { x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:

View File

@@ -131,6 +131,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scoped_allocator_usage_test
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_custom_tree", "doc_custom_tree.vcproj", "{5E11C8B3-A8C4-4A2F-295A-7951A0EDAA02}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_extended_allocators", "doc_extended_allocators.vcproj", "{5CE11C83-FA84-295A-4FA2-D7921A0BAB02}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfiguration) = preSolution GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug Debug = Debug
@@ -271,6 +279,14 @@ Global
{B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Debug.Build.0 = Debug|Win32 {B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Debug.Build.0 = Debug|Win32
{B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Release.ActiveCfg = Release|Win32 {B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Release.ActiveCfg = Release|Win32
{B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Release.Build.0 = Release|Win32 {B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.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
{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
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection EndGlobalSection

View File

@@ -128,6 +128,9 @@
<File <File
RelativePath="..\..\..\..\boost\container\node_allocator.hpp"> RelativePath="..\..\..\..\boost\container\node_allocator.hpp">
</File> </File>
<File
RelativePath="..\..\..\..\boost\container\options.hpp">
</File>
<File <File
RelativePath="..\..\..\..\boost\container\scoped_allocator.hpp"> RelativePath="..\..\..\..\boost\container\scoped_allocator.hpp">
</File> </File>

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
ProjectType="Visual C++" ProjectType="Visual C++"
Version="7.10" Version="7.10"
Name="doc_recursive_containers" Name="doc_recursive_containers"
ProjectGUID="{5D1C8E13-255A-FA84-4FA2-DA92100BAD42}" ProjectGUID="{1B51C8B2-A832-F55A-4FA2-210AF9D43BD2}"
Keyword="Win32Proj"> Keyword="Win32Proj">
<Platforms> <Platforms>
<Platform <Platform

View File

@@ -171,14 +171,15 @@ class map_propagate_test_wrapper
< T, T, std::less<T> < T, T, std::less<T>
, typename boost::container::allocator_traits<A>::template , typename boost::container::allocator_traits<A>::template
portable_rebind_alloc< std::pair<const T, T> >::type portable_rebind_alloc< std::pair<const T, T> >::type
, red_black_tree> //tree_assoc_defaults
>
{ {
BOOST_COPYABLE_AND_MOVABLE(map_propagate_test_wrapper) BOOST_COPYABLE_AND_MOVABLE(map_propagate_test_wrapper)
typedef boost::container::map typedef boost::container::map
< T, T, std::less<T> < T, T, std::less<T>
, typename boost::container::allocator_traits<A>::template , typename boost::container::allocator_traits<A>::template
portable_rebind_alloc< std::pair<const T, T> >::type portable_rebind_alloc< std::pair<const T, T> >::type
, red_black_tree> Base; > Base;
public: public:
map_propagate_test_wrapper() map_propagate_test_wrapper()
: Base() : Base()
@@ -203,7 +204,7 @@ class map_propagate_test_wrapper
}; };
template<class VoidAllocator> template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
struct GetAllocatorMap struct GetAllocatorMap
{ {
template<class ValueType> template<class ValueType>
@@ -214,6 +215,9 @@ struct GetAllocatorMap
, std::less<ValueType> , std::less<ValueType>
, typename allocator_traits<VoidAllocator> , typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type ::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type
, typename boost::container::tree_assoc_options
< boost::container::tree_type<tree_type_value>
>::type
> map_type; > map_type;
typedef multimap< ValueType typedef multimap< ValueType
@@ -221,22 +225,25 @@ struct GetAllocatorMap
, std::less<ValueType> , std::less<ValueType>
, typename allocator_traits<VoidAllocator> , typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type ::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type
, typename boost::container::tree_assoc_options
< boost::container::tree_type<tree_type_value>
>::type
> multimap_type; > multimap_type;
}; };
}; };
template<class VoidAllocator> template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
int test_map_variants() int test_map_variants()
{ {
typedef typename GetAllocatorMap<VoidAllocator>::template apply<int>::map_type MyMap; typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<int>::map_type MyMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_int>::map_type MyMoveMap; typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::movable_int>::map_type MyMoveMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_and_copyable_int>::map_type MyCopyMoveMap; typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::movable_and_copyable_int>::map_type MyCopyMoveMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::copyable_int>::map_type MyCopyMap; typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::copyable_int>::map_type MyCopyMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<int>::multimap_type MyMultiMap; typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<int>::multimap_type MyMultiMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_int>::multimap_type MyMoveMultiMap; typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::movable_int>::multimap_type MyMoveMultiMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_and_copyable_int>::multimap_type MyCopyMoveMultiMap; typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::movable_and_copyable_int>::multimap_type MyCopyMoveMultiMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::copyable_int>::multimap_type MyCopyMultiMap; typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::copyable_int>::multimap_type MyCopyMultiMap;
typedef std::map<int, int> MyStdMap; typedef std::map<int, int> MyStdMap;
typedef std::multimap<int, int> MyStdMultiMap; typedef std::multimap<int, int> MyStdMultiMap;
@@ -298,34 +305,96 @@ int main ()
test_move<multimap<recursive_multimap, recursive_multimap> >(); test_move<multimap<recursive_multimap, recursive_multimap> >();
} }
if(test_map_variants< std::allocator<void> >()){ ////////////////////////////////////
// Testing allocator implementations
////////////////////////////////////
// std:allocator
if(test_map_variants< std::allocator<void>, red_black_tree >()){
std::cerr << "test_map_variants< std::allocator<void> > failed" << std::endl; std::cerr << "test_map_variants< std::allocator<void> > failed" << std::endl;
return 1; return 1;
} }
// boost::container::allocator
if(test_map_variants< allocator<void> >()){ if(test_map_variants< allocator<void>, red_black_tree >()){
std::cerr << "test_map_variants< allocator<void> > failed" << std::endl; std::cerr << "test_map_variants< allocator<void> > failed" << std::endl;
return 1; return 1;
} }
// boost::container::node_allocator
if(test_map_variants< node_allocator<void> >()){ if(test_map_variants< node_allocator<void>, red_black_tree >()){
std::cerr << "test_map_variants< node_allocator<void> > failed" << std::endl; std::cerr << "test_map_variants< node_allocator<void> > failed" << std::endl;
return 1; return 1;
} }
// boost::container::adaptive_pool
if(test_map_variants< adaptive_pool<void> >()){ if(test_map_variants< adaptive_pool<void>, red_black_tree >()){
std::cerr << "test_map_variants< adaptive_pool<void> > failed" << std::endl; std::cerr << "test_map_variants< adaptive_pool<void> > failed" << std::endl;
return 1; return 1;
} }
////////////////////////////////////
// Tree implementations
////////////////////////////////////
// AVL
if(test_map_variants< std::allocator<void>, avl_tree >()){
std::cerr << "test_map_variants< std::allocator<void>, avl_tree > failed" << std::endl;
return 1;
}
// SCAPEGOAT TREE
if(test_map_variants< std::allocator<void>, scapegoat_tree >()){
std::cerr << "test_map_variants< std::allocator<void>, scapegoat_tree > failed" << std::endl;
return 1;
}
// SPLAY TREE
if(test_map_variants< std::allocator<void>, splay_tree >()){
std::cerr << "test_map_variants< std::allocator<void>, splay_tree > failed" << std::endl;
return 1;
}
////////////////////////////////////
// Emplace testing
////////////////////////////////////
const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR); const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR);
if(!boost::container::test::test_emplace<map<test::EmplaceInt, test::EmplaceInt>, MapOptions>()) if(!boost::container::test::test_emplace<map<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
return 1; return 1;
if(!boost::container::test::test_emplace<multimap<test::EmplaceInt, test::EmplaceInt>, MapOptions>()) if(!boost::container::test::test_emplace<multimap<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
return 1; return 1;
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<map_propagate_test_wrapper>()) if(!boost::container::test::test_propagate_allocator<map_propagate_test_wrapper>())
return 1; return 1;
////////////////////////////////////
// Test optimize_size option
////////////////////////////////////
//
// map
//
typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int const*, int*> >
, tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbmap_size_optimized_no;
typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int const*, int*> >
, tree_assoc_options< optimize_size<true>, tree_type<red_black_tree> >::type > rbmap_size_optimized_yes;
BOOST_STATIC_ASSERT(sizeof(rbmap_size_optimized_yes) < sizeof(rbmap_size_optimized_no));
typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int const*, int*> >
, tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmap_size_optimized_no;
typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int const*, int*> >
, tree_assoc_options< optimize_size<true>, tree_type<avl_tree> >::type > avlmap_size_optimized_yes;
BOOST_STATIC_ASSERT(sizeof(avlmap_size_optimized_yes) < sizeof(avlmap_size_optimized_no));
//
// multimap
//
typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int const*, int*> >
, tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbmmap_size_optimized_no;
typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int const*, int*> >
, tree_assoc_options< optimize_size<true>, tree_type<red_black_tree> >::type > rbmmap_size_optimized_yes;
BOOST_STATIC_ASSERT(sizeof(rbmmap_size_optimized_yes) < sizeof(rbmmap_size_optimized_no));
typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int const*, int*> >
, tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmmap_size_optimized_no;
typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int const*, int*> >
, tree_assoc_options< optimize_size<true>, tree_type<avl_tree> >::type > avlmmap_size_optimized_yes;
BOOST_STATIC_ASSERT(sizeof(avlmmap_size_optimized_yes) < sizeof(avlmmap_size_optimized_no));
return 0; return 0;
} }

View File

@@ -23,6 +23,13 @@
#include <boost/move/utility.hpp> #include <boost/move/utility.hpp>
#include <string> #include <string>
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME rebalance
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace test {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
template<class T1, class T2, class T3, class T4> template<class T1, class T2, class T3, class T4>
bool operator ==(std::pair<T1, T2> &p1, std::pair<T1, T2> &p2) bool operator ==(std::pair<T1, T2> &p1, std::pair<T1, T2> &p2)
{ {
@@ -33,6 +40,16 @@ namespace boost{
namespace container { namespace container {
namespace test{ namespace test{
template<class C>
void map_test_rebalanceable(C &, boost::container::container_detail::false_type)
{}
template<class C>
void map_test_rebalanceable(C &c, boost::container::container_detail::true_type)
{
c.rebalance();
}
template<class MyBoostMap template<class MyBoostMap
,class MyStdMap ,class MyStdMap
,class MyBoostMultiMap ,class MyBoostMultiMap
@@ -501,6 +518,19 @@ int map_test()
return 1; return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
return 1; return 1;
map_test_rebalanceable(*boostmap
, container_detail::bool_<has_member_function_callable_with_rebalance<MyBoostMap>::value>());
if(!CheckEqualContainers(boostmap, stdmap)){
std::cout << "Error in boostmap->rebalance()" << std::endl;
return 1;
}
map_test_rebalanceable(*boostmultimap
, container_detail::bool_<has_member_function_callable_with_rebalance<MyBoostMultiMap>::value>());
if(!CheckEqualContainers(boostmultimap, stdmultimap)){
std::cout << "Error in boostmultimap->rebalance()" << std::endl;
return 1;
}
} }
//Compare count with std containers //Compare count with std containers

View File

@@ -145,10 +145,12 @@ void test_move()
template<class T, class A> template<class T, class A>
class set_propagate_test_wrapper class set_propagate_test_wrapper
: public boost::container::set<T, std::less<T>, A, red_black_tree> : public boost::container::set<T, std::less<T>, A
//tree_assoc_defaults
>
{ {
BOOST_COPYABLE_AND_MOVABLE(set_propagate_test_wrapper) BOOST_COPYABLE_AND_MOVABLE(set_propagate_test_wrapper)
typedef boost::container::set<T, std::less<T>, A, red_black_tree> Base; typedef boost::container::set<T, std::less<T>, A > Base;
public: public:
set_propagate_test_wrapper() set_propagate_test_wrapper()
: Base() : Base()
@@ -172,7 +174,7 @@ class set_propagate_test_wrapper
{ this->Base::swap(x); } { this->Base::swap(x); }
}; };
template<class VoidAllocator> template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
struct GetAllocatorSet struct GetAllocatorSet
{ {
template<class ValueType> template<class ValueType>
@@ -182,28 +184,34 @@ struct GetAllocatorSet
, std::less<ValueType> , std::less<ValueType>
, typename allocator_traits<VoidAllocator> , typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc<ValueType>::type ::template portable_rebind_alloc<ValueType>::type
, typename boost::container::tree_assoc_options
< boost::container::tree_type<tree_type_value>
>::type
> set_type; > set_type;
typedef multiset < ValueType typedef multiset < ValueType
, std::less<ValueType> , std::less<ValueType>
, typename allocator_traits<VoidAllocator> , typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc<ValueType>::type ::template portable_rebind_alloc<ValueType>::type
, typename boost::container::tree_assoc_options
< boost::container::tree_type<tree_type_value>
>::type
> multiset_type; > multiset_type;
}; };
}; };
template<class VoidAllocator> template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
int test_set_variants() int test_set_variants()
{ {
typedef typename GetAllocatorSet<VoidAllocator>::template apply<int>::set_type MySet; typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<int>::set_type MySet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_int>::set_type MyMoveSet; typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::movable_int>::set_type MyMoveSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_and_copyable_int>::set_type MyCopyMoveSet; typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::movable_and_copyable_int>::set_type MyCopyMoveSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::copyable_int>::set_type MyCopySet; typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::copyable_int>::set_type MyCopySet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<int>::multiset_type MyMultiSet; typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<int>::multiset_type MyMultiSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_int>::multiset_type MyMoveMultiSet; typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::movable_int>::multiset_type MyMoveMultiSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_and_copyable_int>::multiset_type MyCopyMoveMultiSet; typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::movable_and_copyable_int>::multiset_type MyCopyMoveMultiSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet; typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet;
typedef std::set<int> MyStdSet; typedef std::set<int> MyStdSet;
typedef std::multiset<int> MyStdMultiSet; typedef std::multiset<int> MyStdMultiSet;
@@ -266,34 +274,95 @@ int main ()
test_move<multiset<recursive_multiset> >(); test_move<multiset<recursive_multiset> >();
} }
if(test_set_variants< std::allocator<void> >()){ ////////////////////////////////////
// Testing allocator implementations
////////////////////////////////////
// std:allocator
if(test_set_variants< std::allocator<void>, red_black_tree >()){
std::cerr << "test_set_variants< std::allocator<void> > failed" << std::endl; std::cerr << "test_set_variants< std::allocator<void> > failed" << std::endl;
return 1; return 1;
} }
// boost::container::allocator
if(test_set_variants< allocator<void> >()){ if(test_set_variants< allocator<void>, red_black_tree>()){
std::cerr << "test_set_variants< allocator<void> > failed" << std::endl; std::cerr << "test_set_variants< allocator<void> > failed" << std::endl;
return 1; return 1;
} }
// boost::container::node_allocator
if(test_set_variants< node_allocator<void> >()){ if(test_set_variants< node_allocator<void>, red_black_tree>()){
std::cerr << "test_set_variants< node_allocator<void> > failed" << std::endl; std::cerr << "test_set_variants< node_allocator<void> > failed" << std::endl;
return 1; return 1;
} }
// boost::container::adaptive_pool
if(test_set_variants< adaptive_pool<void> >()){ if(test_set_variants< adaptive_pool<void>, red_black_tree>()){
std::cerr << "test_set_variants< adaptive_pool<void> > failed" << std::endl; std::cerr << "test_set_variants< adaptive_pool<void> > failed" << std::endl;
return 1; return 1;
} }
////////////////////////////////////
// Tree implementations
////////////////////////////////////
// AVL
if(test_set_variants< std::allocator<void>, avl_tree >()){
std::cerr << "test_set_variants< std::allocator<void>, avl_tree > failed" << std::endl;
return 1;
}
// SCAPEGOAT TREE
if(test_set_variants< std::allocator<void>, scapegoat_tree >()){
std::cerr << "test_set_variants< std::allocator<void>, scapegoat_tree > failed" << std::endl;
return 1;
}
// SPLAY TREE
if(test_set_variants< std::allocator<void>, splay_tree >()){
std::cerr << "test_set_variants< std::allocator<void>, splay_tree > failed" << std::endl;
return 1;
}
////////////////////////////////////
// Emplace testing
////////////////////////////////////
const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC); const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC);
if(!boost::container::test::test_emplace<set<test::EmplaceInt>, SetOptions>()) if(!boost::container::test::test_emplace<set<test::EmplaceInt>, SetOptions>())
return 1; return 1;
if(!boost::container::test::test_emplace<multiset<test::EmplaceInt>, SetOptions>()) if(!boost::container::test::test_emplace<multiset<test::EmplaceInt>, SetOptions>())
return 1; return 1;
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<set_propagate_test_wrapper>()) if(!boost::container::test::test_propagate_allocator<set_propagate_test_wrapper>())
return 1; return 1;
////////////////////////////////////
// Test optimize_size option
////////////////////////////////////
//
// set
//
typedef set< int*, std::less<int*>, std::allocator<int*>
, tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbset_size_optimized_no;
typedef set< int*, std::less<int*>, std::allocator<int*>
, tree_assoc_options< optimize_size<true>, tree_type<red_black_tree> >::type > rbset_size_optimized_yes;
BOOST_STATIC_ASSERT(sizeof(rbset_size_optimized_yes) < sizeof(rbset_size_optimized_no));
typedef set< int*, std::less<int*>, std::allocator<int*>
, tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlset_size_optimized_no;
typedef set< int*, std::less<int*>, std::allocator<int*>
, tree_assoc_options< optimize_size<true>, tree_type<avl_tree> >::type > avlset_size_optimized_yes;
BOOST_STATIC_ASSERT(sizeof(avlset_size_optimized_yes) < sizeof(avlset_size_optimized_no));
//
// multiset
//
typedef multiset< int*, std::less<int*>, std::allocator<int*>
, tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbmset_size_optimized_no;
typedef multiset< int*, std::less<int*>, std::allocator<int*>
, tree_assoc_options< optimize_size<true>, tree_type<red_black_tree> >::type > rbmset_size_optimized_yes;
BOOST_STATIC_ASSERT(sizeof(rbmset_size_optimized_yes) < sizeof(rbmset_size_optimized_no));
typedef multiset< int*, std::less<int*>, std::allocator<int*>
, tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmset_size_optimized_no;
typedef multiset< int*, std::less<int*>, std::allocator<int*>
, tree_assoc_options< optimize_size<true>, tree_type<avl_tree> >::type > avlmset_size_optimized_yes;
BOOST_STATIC_ASSERT(sizeof(avlmset_size_optimized_yes) < sizeof(avlmset_size_optimized_no));
return 0; return 0;
} }

View File

@@ -21,10 +21,28 @@
#include <boost/move/iterator.hpp> #include <boost/move/iterator.hpp>
#include <string> #include <string>
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME rebalance
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace test {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
namespace boost{ namespace boost{
namespace container { namespace container {
namespace test{ namespace test{
template<class C>
void set_test_rebalanceable(C &, boost::container::container_detail::false_type)
{}
template<class C>
void set_test_rebalanceable(C &c, boost::container::container_detail::true_type)
{
c.rebalance();
}
template<class MyBoostSet template<class MyBoostSet
,class MyStdSet ,class MyStdSet
,class MyBoostMultiSet ,class MyBoostMultiSet
@@ -459,6 +477,18 @@ int set_test ()
std::cout << "Error in boostmultiset->insert(boostmultiset->lower_bound(move_me2), boost::move(move_me2))" << std::endl; std::cout << "Error in boostmultiset->insert(boostmultiset->lower_bound(move_me2), boost::move(move_me2))" << std::endl;
return 1; return 1;
} }
set_test_rebalanceable(*boostset
, container_detail::bool_<has_member_function_callable_with_rebalance<MyBoostSet>::value>());
if(!CheckEqualContainers(boostset, stdset)){
std::cout << "Error in boostset->rebalance()" << std::endl;
return 1;
}
set_test_rebalanceable(*boostmultiset
, container_detail::bool_<has_member_function_callable_with_rebalance<MyBoostMultiSet>::value>());
if(!CheckEqualContainers(boostmultiset, stdmultiset)){
std::cout << "Error in boostmultiset->rebalance()" << std::endl;
return 1;
}
} }
} }