forked from boostorg/container
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:
@@ -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
|
||||
|
||||
@@ -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()); }
|
||||
|
||||
|
||||
@@ -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); }
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user