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
+21 -7
View File
@@ -16,7 +16,7 @@
#endif
//! \file
//! This header file forward declares the following classes:
//! This header file forward declares the following containers:
//! - boost::container::vector
//! - boost::container::stable_vector
//! - boost::container::static_vector
@@ -33,11 +33,13 @@
//! - boost::container::basic_string
//! - boost::container::string
//! - boost::container::wstring
//!
//! It forward declares the following allocators:
//! - boost::container::allocator
//! - boost::container::node_allocator
//! - boost::container::adaptive_pool
//!
//! and defines the following types:
//! And finally it defines the following types
//////////////////////////////////////////////////////////////////////////////
// Standard predeclarations
@@ -74,7 +76,7 @@ namespace container {
//! Enumeration used to configure ordered associative containers
//! with a concrete tree implementation.
enum tree_type
enum tree_type_enum
{
red_black_tree,
avl_tree,
@@ -107,30 +109,35 @@ template <class T
,class Allocator = std::allocator<T> >
class slist;
template<tree_type_enum TreeType, bool OptimizeSize>
struct tree_opt;
typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key>
,tree_type = red_black_tree >
,class Options = tree_assoc_defaults >
class set;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key>
,tree_type = red_black_tree >
,class Options = tree_assoc_defaults >
class multiset;
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<const Key, T> >
,tree_type = red_black_tree >
,class Options = tree_assoc_defaults >
class map;
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<const Key, T> >
,tree_type = red_black_tree >
,class Options = tree_assoc_defaults >
class multimap;
template <class Key
@@ -198,6 +205,13 @@ template
, std::size_t Version = 2>
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
//! Type used to tag that the input range is
+153 -27
View File
@@ -23,6 +23,8 @@
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/options.hpp>
//
#include <boost/intrusive/pointer_traits.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)); }
};
template<class VoidPointer>
struct intrusive_tree_hook
template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
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
< container_detail::bi::void_pointer<VoidPointer>
, 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;
};
@@ -114,23 +147,23 @@ struct tree_internal_data_type< std::pair<T1, T2> >
typedef pair<T1, T2> type;
};
//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
: public intrusive_tree_hook<VoidPointer>::type
: public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type
{
private:
//BOOST_COPYABLE_AND_MOVABLE(tree_node)
tree_node();
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 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()
{
@@ -215,12 +248,67 @@ class push_back_functor
namespace container_detail {
template<class A, class ValueCompare, boost::container::tree_type tree_type_value>
struct intrusive_tree_type;
template< class NodeType, class NodeCompareType
, class SizeType, class HookType
, boost::container::tree_type_enum tree_type_value>
struct intrusive_tree_dispatch;
template<class A, class ValueCompare>
struct intrusive_tree_type<A, ValueCompare, boost::container::red_black_tree>
template<class NodeType, class NodeCompareType, class SizeType, class HookType>
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::
allocator_traits<A>::value_type value_type;
typedef typename boost::container::
@@ -228,16 +316,49 @@ struct intrusive_tree_type<A, ValueCompare, boost::container::red_black_tree>
typedef typename boost::container::
allocator_traits<A>::size_type size_type;
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 typename container_detail::bi::make_rbtree
<node_type
,container_detail::bi::compare<node_compare_type>
,container_detail::bi::base_hook<typename intrusive_tree_hook<void_pointer>::type>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<size_type>
>::type container_type;
typedef container_type type ;
//Deducing the hook type from node_type (e.g. node_type::hook_type) would
//provoke an early instantiation of node_type that could ruin recursive
//tree definitions, so retype the complete type to avoid any problem.
typedef typename intrusive_tree_hook
<void_pointer, tree_type_value
, OptimizeSize>::type hook_type;
public:
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 {
@@ -326,24 +447,25 @@ struct key_node_compare
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A,
boost::container::tree_type tree_type_value>
class Options>
class tree
: protected container_detail::node_alloc_holder
< A
, typename container_detail::intrusive_tree_type
< A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> //ValComp
, tree_type_value>::type
, Options::tree_type, Options::optimize_size>::type
>
{
typedef tree_value_compare
<Key, Value, KeyCompare, KeyOfValue> ValComp;
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
<A, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
typedef tree < Key, Value, KeyOfValue
, KeyCompare, A, tree_type_value> ThisType;
, KeyCompare, A, Options> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef typename AllocHolder::ValAlloc ValAlloc;
typedef typename AllocHolder::Node Node;
@@ -353,6 +475,7 @@ class tree
typedef typename AllocHolder::allocator_v1 allocator_v1;
typedef typename AllocHolder::allocator_v2 allocator_v2;
typedef typename AllocHolder::alloc_version alloc_version;
typedef intrusive_tree_proxy<Options::tree_type> intrusive_tree_proxy_t;
BOOST_COPYABLE_AND_MOVABLE(tree)
@@ -985,6 +1108,9 @@ class tree
(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)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
+96 -34
View File
@@ -39,22 +39,26 @@
namespace boost {
namespace container {
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! 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
//! 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
//! container and of an associative container. For a
//! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>.
//! container and of an associative container. The <code>value_type</code> stored
//! 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>).
//!
//! Allocator is the allocator to allocate the value_types
//! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > >
//! \tparam Key is the key_type of the map
//! \tparam Value is the <code>mapped_type</code>
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
//! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
//! \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
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
class map
{
@@ -64,7 +68,7 @@ class map
typedef std::pair<const Key, T> value_type_impl;
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::tree_value_compare
< 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
{ 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)
{ return x.m_tree == y.m_tree; }
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()); }
//! <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)
{ 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)
{ 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)
{ 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)
{ return !(x < y); }
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(map& x, map& y)
{ x.swap(y); }
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
@@ -814,23 +845,27 @@ namespace container {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A multimap is a kind of associative container that supports equivalent keys
//! (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
//! supports bidirectional iterators.
//!
//! A multimap satisfies all of the requirements of a container and of a reversible
//! container and of an associative container. For a
//! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>.
//! container and of an associative container. The <code>value_type</code> stored
//! 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>).
//!
//! Allocator is the allocator to allocate the value_types
//!(e.g. <i>allocator< std::pair<<b>const</b> Key, T> ></i>).
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > >
//! \tparam Key is the key_type of the map
//! \tparam Value is the <code>mapped_type</code>
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
//! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
//! \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
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
class multimap
{
@@ -840,7 +875,7 @@ class multimap
typedef std::pair<const Key, T> value_type_impl;
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::tree_value_compare
< 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
{ 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)
{ return x.m_tree == y.m_tree; }
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()); }
//! <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)
{ 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)
{ 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)
{ 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)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(multimap& x, multimap& y)
{ x.swap(y); }
};
+72
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
+90 -24
View File
@@ -35,6 +35,8 @@
namespace boost {
namespace container {
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! 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.
//! 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
//! , and of an associative container. A set also provides most operations described in
//! 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
template <class Key, class Compare, class Allocator, tree_type tree_type_value>
template <class Key, class Compare, class Allocator, class SetOptions>
#endif
class set
{
@@ -53,7 +59,7 @@ class set
private:
BOOST_COPYABLE_AND_MOVABLE(set)
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
#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
{ 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)
{ return x.m_tree == y.m_tree; }
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()); }
//! <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)
{ 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)
{ 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)
{ 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)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(set& x, set& y)
{ x.swap(y); }
@@ -628,8 +661,8 @@ class set
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::set<Key, C, Allocator> >
template <class Key, class C, class SetOptions, class 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;
};
@@ -638,6 +671,8 @@ namespace container {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A multiset is a kind of associative container that supports equivalent keys
//! (possibly contains multiple copies of the same key value) and provides for
//! 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
//! container, and of an associative container). multiset also provides most operations
//! 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
template <class Key, class Compare, class Allocator, tree_type tree_type_value>
template <class Key, class Compare, class Allocator, class MultiSetOptions>
#endif
class multiset
{
@@ -656,7 +695,7 @@ class multiset
private:
BOOST_COPYABLE_AND_MOVABLE(multiset)
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
#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
{ 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)
{ return x.m_tree == y.m_tree; }
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()); }
//! <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)
{ 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)
{ 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)
{ 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)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(multiset& x, multiset& y)
{ x.swap(y); }
@@ -1222,8 +1288,8 @@ class multiset
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::multiset<Key, C, Allocator> >
template <class Key, class C, class Allocator, class MultiSetOptions>
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;
};
+30 -12
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
{ 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)
{
if(x.size() != y.size()){
@@ -1440,26 +1443,41 @@ class slist
return i1 == end1;
}
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 and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
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)
{ 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)
{ 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)
{ return !(x < y); }
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(slist& x, slist& y)
{ x.swap(y); }
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: