mirror of
https://github.com/boostorg/intrusive.git
synced 2025-08-03 14:34:44 +02:00
Changes introduced by the new intrusive version.
[SVN r39548]
This commit is contained in:
@@ -48,6 +48,7 @@ class circular_slist_algorithms
|
||||
public:
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
||||
typedef NodeTraits node_traits;
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#ifndef BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP
|
||||
#define BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP
|
||||
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
@@ -22,7 +22,7 @@ namespace intrusive {
|
||||
//!This value traits template is used to create value traits
|
||||
//!from user defined node traits where value_traits::value_type will
|
||||
//!derive from node_traits::node
|
||||
template<class T, class NodeTraits, linking_policy Policy>
|
||||
template<class T, class NodeTraits, link_mode_type LinkMode = safe_link>
|
||||
struct derivation_value_traits
|
||||
{
|
||||
public:
|
||||
@@ -35,8 +35,7 @@ struct derivation_value_traits
|
||||
typedef typename boost::pointer_to_other<node_ptr, const T>::type const_pointer;
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
|
||||
enum { linking_policy = Policy };
|
||||
static const link_mode_type link_mode = LinkMode;
|
||||
|
||||
static node_ptr to_node_ptr(reference value)
|
||||
{ return node_ptr(&value); }
|
||||
|
@@ -10,12 +10,10 @@
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_SELECT_COMPILER_INCLUDED
|
||||
#ifndef BOOST_COMPILER_CONFIG
|
||||
#ifndef BOOST_INTRUSIVE_CONFIG_INCLUDED
|
||||
#define BOOST_INTRUSIVE_CONFIG_INCLUDED
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
#define BOOST_INTRUSIVE_SELECT_COMPILER_INCLUDED
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class ebo_functor_holder_impl
|
||||
|
||||
template<typename T>
|
||||
class ebo_functor_holder_impl<T, false>
|
||||
: private T
|
||||
: public T
|
||||
{
|
||||
public:
|
||||
ebo_functor_holder_impl(){}
|
||||
|
185
include/boost/intrusive/detail/generic_hook.hpp
Normal file
185
include/boost/intrusive/detail/generic_hook.hpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007
|
||||
//
|
||||
// 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/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_GENERIC_HOOK_HPP
|
||||
#define BOOST_INTRUSIVE_GENERIC_HOOK_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
/// @cond
|
||||
|
||||
enum
|
||||
{ NoBaseHook
|
||||
, ListBaseHook
|
||||
, SlistBaseHook
|
||||
, SetBaseHook
|
||||
, UsetBaseHook
|
||||
};
|
||||
|
||||
struct no_default_definer{};
|
||||
|
||||
template <class Hook, unsigned int>
|
||||
struct default_definer;
|
||||
|
||||
template <class Hook>
|
||||
struct default_definer<Hook, ListBaseHook>
|
||||
{ typedef Hook default_list_hook; };
|
||||
|
||||
template <class Hook>
|
||||
struct default_definer<Hook, SlistBaseHook>
|
||||
{ typedef Hook default_slist_hook; };
|
||||
|
||||
template <class Hook>
|
||||
struct default_definer<Hook, SetBaseHook>
|
||||
{ typedef Hook default_set_hook; };
|
||||
|
||||
template <class Hook>
|
||||
struct default_definer<Hook, UsetBaseHook>
|
||||
{ typedef Hook default_uset_hook; };
|
||||
|
||||
template <class Hook, unsigned int BaseHookType>
|
||||
struct make_default_definer
|
||||
{
|
||||
typedef typename detail::if_c
|
||||
< BaseHookType != 0
|
||||
, default_definer<Hook, BaseHookType>
|
||||
, no_default_definer>::type type;
|
||||
};
|
||||
|
||||
template
|
||||
< class GetNodeAlgorithms
|
||||
, class Tag
|
||||
, link_mode_type LinkMode
|
||||
, int HookType
|
||||
>
|
||||
struct make_node_holder
|
||||
{
|
||||
typedef typename detail::if_c
|
||||
<!detail::is_same<Tag, member_tag>::value
|
||||
, detail::node_holder
|
||||
< typename GetNodeAlgorithms::type::node_traits::node
|
||||
, Tag
|
||||
, LinkMode
|
||||
, HookType>
|
||||
, typename GetNodeAlgorithms::type::node_traits::node
|
||||
>::type type;
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
template
|
||||
< class GetNodeAlgorithms
|
||||
, class Tag
|
||||
, link_mode_type LinkMode
|
||||
, int HookType
|
||||
>
|
||||
class generic_hook
|
||||
/// @cond
|
||||
|
||||
//If the hook is a base hook, derive generic hook from detail::node_holder
|
||||
//so that a unique base class is created to convert from the node
|
||||
//to the type. This mechanism will be used by base_hook_traits.
|
||||
//
|
||||
//If the hook is a member hook, generic hook will directly derive
|
||||
//from the hook.
|
||||
: public make_default_definer
|
||||
< generic_hook<GetNodeAlgorithms, Tag, LinkMode, HookType>
|
||||
, detail::is_same<Tag, default_tag>::value*HookType
|
||||
>::type
|
||||
, public make_node_holder<GetNodeAlgorithms, Tag, LinkMode, HookType>::type
|
||||
/// @endcond
|
||||
{
|
||||
public:
|
||||
/// @cond
|
||||
struct boost_intrusive_tags
|
||||
{
|
||||
static const int hook_type = HookType;
|
||||
static const link_mode_type link_mode = LinkMode;
|
||||
typedef Tag tag;
|
||||
typedef typename GetNodeAlgorithms::type node_algorithms;
|
||||
typedef typename node_algorithms::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
static const bool is_base_hook = !detail::is_same<Tag, member_tag>::value;
|
||||
enum { safemode_or_autounlink =
|
||||
(int)link_mode == (int)auto_unlink ||
|
||||
(int)link_mode == (int)safe_link };
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
generic_hook()
|
||||
{
|
||||
if(boost_intrusive_tags::safemode_or_autounlink){
|
||||
boost_intrusive_tags::node_algorithms::init
|
||||
(static_cast<typename boost_intrusive_tags::node*>(this));
|
||||
}
|
||||
}
|
||||
|
||||
generic_hook(const generic_hook& )
|
||||
{
|
||||
if(boost_intrusive_tags::safemode_or_autounlink){
|
||||
boost_intrusive_tags::node_algorithms::init
|
||||
(static_cast<typename boost_intrusive_tags::node*>(this));
|
||||
}
|
||||
}
|
||||
|
||||
generic_hook& operator=(const generic_hook& )
|
||||
{ return *this; }
|
||||
|
||||
~generic_hook()
|
||||
{
|
||||
destructor_impl
|
||||
(*this, detail::link_dispatch<boost_intrusive_tags::link_mode>());
|
||||
}
|
||||
|
||||
void swap_nodes(generic_hook &other)
|
||||
{
|
||||
boost_intrusive_tags::node_algorithms::swap_nodes
|
||||
( static_cast<typename boost_intrusive_tags::node*>(this)
|
||||
, static_cast<typename boost_intrusive_tags::node*>(&other));
|
||||
}
|
||||
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT(( boost_intrusive_tags::safemode_or_autounlink ));
|
||||
return !boost_intrusive_tags::node_algorithms::unique
|
||||
(static_cast<const typename boost_intrusive_tags::node*>(this));
|
||||
}
|
||||
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( (int)boost_intrusive_tags::link_mode == (int)auto_unlink ));
|
||||
boost_intrusive_tags::node_algorithms::unlink
|
||||
(static_cast<typename boost_intrusive_tags::node*>(this));
|
||||
boost_intrusive_tags::node_algorithms::init
|
||||
(static_cast<typename boost_intrusive_tags::node*>(this));
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_GENERIC_HOOK_HPP
|
@@ -18,14 +18,9 @@
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#endif
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#endif
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/slist_node.hpp> //remove-me
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
@@ -52,27 +47,34 @@ template<int Dummy>
|
||||
const std::size_t prime_list_holder<Dummy>::prime_list_size
|
||||
= sizeof(prime_list)/sizeof(std::size_t);
|
||||
|
||||
template <class SlistImpl>
|
||||
struct bucket_type_impl
|
||||
: public SlistImpl
|
||||
template <class Slist>
|
||||
struct bucket_impl : public Slist
|
||||
{
|
||||
bucket_type_impl()
|
||||
bucket_impl()
|
||||
{}
|
||||
|
||||
bucket_type_impl(const bucket_type_impl &)
|
||||
bucket_impl(const bucket_impl &)
|
||||
{}
|
||||
|
||||
bucket_type_impl &operator=(const bucket_type_impl&)
|
||||
{ SlistImpl::clear(); }
|
||||
|
||||
static typename std::iterator_traits
|
||||
<typename SlistImpl::const_iterator>::difference_type
|
||||
get_bucket_num
|
||||
( typename SlistImpl::const_iterator it
|
||||
, const bucket_type_impl<SlistImpl> &first_bucket
|
||||
, const bucket_type_impl<SlistImpl> &last_bucket)
|
||||
~bucket_impl()
|
||||
{
|
||||
typename SlistImpl::const_iterator
|
||||
//This bucket is still being used!
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
|
||||
}
|
||||
|
||||
bucket_impl &operator=(const bucket_impl&)
|
||||
{
|
||||
//This bucket is still in use!
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
|
||||
//Slist::clear();
|
||||
}
|
||||
|
||||
static typename Slist::difference_type get_bucket_num
|
||||
( typename Slist::const_iterator it
|
||||
, const bucket_impl<Slist> &first_bucket
|
||||
, const bucket_impl<Slist> &last_bucket)
|
||||
{
|
||||
typename Slist::const_iterator
|
||||
first(first_bucket.cend()), last(last_bucket.cend());
|
||||
|
||||
//The end node is embedded in the singly linked list:
|
||||
@@ -81,252 +83,130 @@ struct bucket_type_impl
|
||||
it.pointed_node() <= last.pointed_node())){
|
||||
++it;
|
||||
}
|
||||
//Now get the bucket_type_impl from the iterator
|
||||
const bucket_type_impl &b = static_cast<const bucket_type_impl&>
|
||||
(SlistImpl::container_from_end_iterator(it));
|
||||
//Now get the bucket_impl from the iterator
|
||||
const bucket_impl &b = static_cast<const bucket_impl&>
|
||||
(Slist::container_from_end_iterator(it));
|
||||
|
||||
//Now just calculate the index b has in the bucket array
|
||||
return &b - &first_bucket;
|
||||
}
|
||||
|
||||
static SlistImpl &bucket_to_slist(bucket_type_impl<SlistImpl> &b)
|
||||
{ return static_cast<SlistImpl &>(b); }
|
||||
|
||||
static const SlistImpl &bucket_to_slist(const bucket_type_impl<SlistImpl> &b)
|
||||
{ return static_cast<const SlistImpl &>(b); }
|
||||
};
|
||||
|
||||
template<class SlistImpl>
|
||||
struct bucket_info_impl
|
||||
template<class Slist>
|
||||
struct bucket_traits_impl
|
||||
{
|
||||
/// @cond
|
||||
typedef typename boost::pointer_to_other
|
||||
< typename SlistImpl::pointer
|
||||
, bucket_type_impl<SlistImpl> >::type bucket_ptr;
|
||||
typedef typename SlistImpl::size_type size_type;
|
||||
< typename Slist::pointer, bucket_impl<Slist> >::type bucket_ptr;
|
||||
typedef typename Slist::size_type size_type;
|
||||
/// @endcond
|
||||
|
||||
bucket_traits_impl(bucket_ptr buckets, size_type len)
|
||||
: buckets_(buckets), buckets_len_(len)
|
||||
{}
|
||||
|
||||
bucket_ptr bucket_begin() const
|
||||
{ return buckets_; }
|
||||
|
||||
size_type bucket_count() const
|
||||
{ return buckets_len_; }
|
||||
|
||||
private:
|
||||
bucket_ptr buckets_;
|
||||
size_type buckets_len_;
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
|
||||
template<class Value, class SlistImpl>
|
||||
template<class Container, bool IsConst>
|
||||
class hashtable_iterator
|
||||
: public boost::iterator_facade
|
||||
< hashtable_iterator<Value, SlistImpl>
|
||||
, Value
|
||||
, boost::forward_traversal_tag
|
||||
, Value&
|
||||
, typename std::iterator_traits<typename SlistImpl::iterator>::difference_type
|
||||
: public std::iterator
|
||||
< std::forward_iterator_tag
|
||||
, typename detail::add_const_if_c
|
||||
<typename Container::value_type, IsConst>::type
|
||||
>
|
||||
{
|
||||
typedef typename SlistImpl::iterator local_iterator;
|
||||
typedef typename SlistImpl::const_iterator const_local_iterator;
|
||||
typedef typename SlistImpl::value_traits::node_ptr node_ptr;
|
||||
typedef typename SlistImpl::value_traits::const_node_ptr const_node_ptr;
|
||||
|
||||
typedef bucket_type_impl<SlistImpl> bucket_type;
|
||||
typedef typename Container::real_value_traits real_value_traits;
|
||||
typedef typename Container::siterator siterator;
|
||||
typedef typename Container::const_siterator const_siterator;
|
||||
typedef typename Container::bucket_type bucket_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
< typename SlistImpl::pointer, bucket_type>::type bucket_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
< typename SlistImpl::pointer, const bucket_type>::type const_bucket_ptr;
|
||||
typedef detail::bucket_info_impl<SlistImpl> bucket_info_t;
|
||||
typedef typename boost::pointer_to_other
|
||||
<bucket_ptr, bucket_info_t>::type bucket_info_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<bucket_ptr, const bucket_info_t>::type const_bucket_info_ptr;
|
||||
typedef typename SlistImpl::size_type size_type;
|
||||
struct enabler {};
|
||||
< typename Container::pointer, const Container>::type const_cont_ptr;
|
||||
typedef typename Container::size_type size_type;
|
||||
|
||||
public:
|
||||
hashtable_iterator ()
|
||||
{}
|
||||
|
||||
explicit hashtable_iterator(local_iterator ptr, const_bucket_info_ptr bucket_info)
|
||||
: local_it_ (ptr), bucket_info_ (bucket_info)
|
||||
{}
|
||||
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
template <class OtherValue>
|
||||
hashtable_iterator(hashtable_iterator<OtherValue, SlistImpl> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,Value*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: local_it_(other.local_it_), bucket_info_(other.bucket_info_)
|
||||
{}
|
||||
#else
|
||||
template <class OtherValue>
|
||||
hashtable_iterator(hashtable_iterator<OtherValue, SlistImpl> const& other,
|
||||
typename enable_if<
|
||||
is_convertible<OtherValue*,T*>
|
||||
>::type* = 0)
|
||||
: local_it_(other.local_it_), bucket_info_(other.bucket_info_)
|
||||
{}
|
||||
#endif
|
||||
|
||||
const local_iterator &local() const
|
||||
{ return local_it_; }
|
||||
|
||||
const_node_ptr pointed_node() const
|
||||
{ return local_it_.pointed_node(); }
|
||||
|
||||
const const_bucket_info_ptr &bucket_info() const
|
||||
{ return bucket_info_; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class, class> friend class hashtable_iterator;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(hashtable_iterator<OtherValue, SlistImpl> const& other) const
|
||||
{ return other.local() == local_it_; }
|
||||
|
||||
void increment()
|
||||
{
|
||||
size_type buckets_len = bucket_info_->buckets_len_;
|
||||
const_bucket_ptr buckets = bucket_info_->buckets_;
|
||||
const_local_iterator first = bucket_type::bucket_to_slist(buckets[0]).cend();
|
||||
const_local_iterator last = bucket_type::bucket_to_slist(buckets[buckets_len]).cend();
|
||||
|
||||
++local_it_;
|
||||
if(first.pointed_node() <= local_it_.pointed_node() &&
|
||||
local_it_.pointed_node() <= last.pointed_node()){
|
||||
size_type n_bucket = (size_type)
|
||||
bucket_type::get_bucket_num(local_it_, buckets[0], buckets[buckets_len]);
|
||||
do{
|
||||
if (++n_bucket == buckets_len){
|
||||
local_it_ = bucket_info_->buckets_->end();
|
||||
break;
|
||||
}
|
||||
local_it_ = bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).begin();
|
||||
}
|
||||
while (local_it_ == bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).end());
|
||||
}
|
||||
}
|
||||
|
||||
Value& dereference() const
|
||||
{ return *local_it_; }
|
||||
|
||||
local_iterator local_it_;
|
||||
const_bucket_info_ptr bucket_info_;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<class T, class SlistImpl>
|
||||
class hashtable_iterator
|
||||
: public std::iterator<std::forward_iterator_tag, T>
|
||||
{
|
||||
typedef typename SlistImpl::iterator local_iterator;
|
||||
typedef typename SlistImpl::const_iterator const_local_iterator;
|
||||
typedef typename SlistImpl::value_traits::node_ptr node_ptr;
|
||||
typedef typename SlistImpl::value_traits::const_node_ptr const_node_ptr;
|
||||
|
||||
typedef bucket_type_impl<SlistImpl> bucket_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
< typename SlistImpl::pointer, bucket_type>::type bucket_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
< typename SlistImpl::pointer, const bucket_type>::type const_bucket_ptr;
|
||||
typedef detail::bucket_info_impl<SlistImpl> bucket_info_t;
|
||||
typedef typename boost::pointer_to_other
|
||||
<bucket_ptr, bucket_info_t>::type bucket_info_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<bucket_ptr, const bucket_info_t>::type const_bucket_info_ptr;
|
||||
typedef typename SlistImpl::size_type size_type;
|
||||
struct enabler {};
|
||||
|
||||
public:
|
||||
typedef T & reference;
|
||||
typedef T * pointer;
|
||||
typedef typename detail::add_const_if_c
|
||||
<typename Container::value_type, IsConst>::type value_type;
|
||||
|
||||
hashtable_iterator ()
|
||||
{}
|
||||
|
||||
explicit hashtable_iterator(local_iterator ptr, const_bucket_info_ptr bucket_info)
|
||||
: local_it_ (ptr), bucket_info_ (bucket_info)
|
||||
explicit hashtable_iterator(siterator ptr, const Container *cont)
|
||||
: slist_it_ (ptr), cont_ (cont)
|
||||
{}
|
||||
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
template <class OtherValue>
|
||||
hashtable_iterator(hashtable_iterator<OtherValue, SlistImpl> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: local_it_(other.local_it_), bucket_info_(other.bucket_info_)
|
||||
hashtable_iterator(const hashtable_iterator<Container, false> &other)
|
||||
: slist_it_(other.slist_it()), cont_(other.get_container())
|
||||
{}
|
||||
#else
|
||||
template <class OtherValue>
|
||||
hashtable_iterator(hashtable_iterator<OtherValue, SlistImpl> const& other,
|
||||
typename enable_if<is_convertible<OtherValue*, T*> >::type* = 0)
|
||||
: local_it_(other.local_it_), bucket_info_(other.bucket_info_)
|
||||
{}
|
||||
#endif
|
||||
|
||||
const local_iterator &local() const
|
||||
{ return local_it_; }
|
||||
|
||||
const_node_ptr pointed_node() const
|
||||
{ return local_it_.pointed_node(); }
|
||||
|
||||
const const_bucket_info_ptr &bucket_info() const
|
||||
{ return bucket_info_; }
|
||||
const siterator &slist_it() const
|
||||
{ return slist_it_; }
|
||||
|
||||
public:
|
||||
hashtable_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
{ this->increment(); return *this; }
|
||||
|
||||
hashtable_iterator operator++(int)
|
||||
{
|
||||
hashtable_iterator result (*this);
|
||||
increment();
|
||||
this->increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2)
|
||||
{ return i.pointed_node() == i2.pointed_node(); }
|
||||
{ return i.slist_it_ == i2.slist_it_; }
|
||||
|
||||
friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
T& operator*() const
|
||||
{ return *local_it_; }
|
||||
value_type& operator*() const
|
||||
{ return *this->operator ->(); }
|
||||
|
||||
pointer operator->() const
|
||||
{ return &(*local_it_); }
|
||||
value_type* operator->() const
|
||||
{ return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(slist_it_.pointed_node())); }
|
||||
|
||||
const Container *get_container() const
|
||||
{ return detail::get_pointer(cont_); }
|
||||
|
||||
const real_value_traits *get_real_value_traits() const
|
||||
{ return &this->get_container()->get_real_value_traits(); }
|
||||
|
||||
private:
|
||||
void increment()
|
||||
{
|
||||
size_type buckets_len = bucket_info_->buckets_len_;
|
||||
const_bucket_ptr buckets = bucket_info_->buckets_;
|
||||
const_local_iterator first = bucket_type::bucket_to_slist(buckets[0]).cend();
|
||||
const_local_iterator last = bucket_type::bucket_to_slist(buckets[buckets_len]).cend();
|
||||
const Container *cont = detail::get_pointer(cont_);
|
||||
bucket_type* buckets = detail::get_pointer(cont->bucket_pointer());
|
||||
size_type buckets_len = cont->bucket_count();
|
||||
const_siterator first(buckets[0].cend());
|
||||
const_siterator last (buckets[buckets_len].cend());
|
||||
|
||||
++local_it_;
|
||||
if(first.pointed_node() <= local_it_.pointed_node() &&
|
||||
local_it_.pointed_node() <= last.pointed_node()){
|
||||
++slist_it_;
|
||||
if(first.pointed_node() <= slist_it_.pointed_node() &&
|
||||
slist_it_.pointed_node()<= last.pointed_node() ){
|
||||
size_type n_bucket = (size_type)
|
||||
bucket_type::get_bucket_num(local_it_, buckets[0], buckets[buckets_len]);
|
||||
bucket_type::get_bucket_num(slist_it_, buckets[0], buckets[buckets_len]);
|
||||
do{
|
||||
if (++n_bucket == buckets_len){
|
||||
local_it_ = bucket_info_->buckets_->end();
|
||||
slist_it_ = buckets->end();
|
||||
break;
|
||||
}
|
||||
local_it_ = bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).begin();
|
||||
slist_it_ = buckets[n_bucket].begin();
|
||||
}
|
||||
while (local_it_ == bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).end());
|
||||
while (slist_it_ == buckets[n_bucket].end());
|
||||
}
|
||||
}
|
||||
|
||||
local_iterator local_it_;
|
||||
const_bucket_info_ptr bucket_info_;
|
||||
siterator slist_it_;
|
||||
const_cont_ptr cont_;
|
||||
};
|
||||
#endif
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace intrusive {
|
||||
|
@@ -19,35 +19,31 @@
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#endif
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
// list_node_traits can be used with circular_list_algorithms and supplies
|
||||
// a list_node holding the pointers needed for a double-linked list
|
||||
// it is used by list_derived_node and list_member_node
|
||||
|
||||
template<class VoidPointer>
|
||||
struct list_node
|
||||
{
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, list_node>::type node_ptr;
|
||||
node_ptr prev_, next_;
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
struct list_node_traits
|
||||
{
|
||||
struct node;
|
||||
typedef list_node<VoidPointer> node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
|
||||
struct node
|
||||
{
|
||||
node_ptr prev_, next_;
|
||||
};
|
||||
|
||||
static node_ptr get_previous(const_node_ptr n)
|
||||
{ return n->prev_; }
|
||||
|
||||
@@ -61,178 +57,126 @@ struct list_node_traits
|
||||
{ n->next_ = next; }
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
|
||||
// list_iterator provides some basic functions for a
|
||||
// node oriented forward iterator:
|
||||
template<class T, class ValueTraits>
|
||||
class list_iterator
|
||||
: public boost::iterator_facade
|
||||
< list_iterator<T, ValueTraits>
|
||||
, T
|
||||
, boost::bidirectional_traversal_tag
|
||||
, T&
|
||||
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
|
||||
>
|
||||
{
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
struct enabler{};
|
||||
|
||||
public:
|
||||
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
|
||||
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
|
||||
|
||||
list_iterator ()
|
||||
: node_ (0)
|
||||
{}
|
||||
|
||||
explicit list_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
{}
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
template <class OtherValue>
|
||||
list_iterator(list_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#else
|
||||
template <class OtherValue>
|
||||
list_iterator(list_iterator<OtherValue, ValueTraits> const& other,
|
||||
typename enable_if<
|
||||
is_convertible<OtherValue*,T*>
|
||||
>::type* = 0)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#endif
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class, class> friend class list_iterator;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(list_iterator<OtherValue, ValueTraits> const& other) const
|
||||
{ return other.pointed_node() == node_; }
|
||||
|
||||
void increment()
|
||||
{ node_ = node_traits::get_next(node_); }
|
||||
|
||||
void decrement()
|
||||
{ node_ = node_traits::get_previous(node_); }
|
||||
|
||||
T& dereference() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
|
||||
node_ptr node_;
|
||||
};
|
||||
|
||||
#else //BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
|
||||
// list_iterator provides some basic functions for a
|
||||
// node oriented bidirectional iterator:
|
||||
template<class T, class ValueTraits>
|
||||
template<class Container, bool IsConst>
|
||||
class list_iterator
|
||||
: public std::iterator<std::bidirectional_iterator_tag, T>
|
||||
: public std::iterator
|
||||
< std::bidirectional_iterator_tag
|
||||
, typename detail::add_const_if_c
|
||||
<typename Container::value_type, IsConst>::type
|
||||
>
|
||||
{
|
||||
struct enabler{};
|
||||
protected:
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
|
||||
typedef typename Container::real_value_traits real_value_traits;
|
||||
typedef typename real_value_traits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, void>::type void_pointer;
|
||||
static const bool store_container_ptr =
|
||||
detail::store_cont_ptr_on_it<Container>::value;
|
||||
|
||||
public:
|
||||
typedef T & reference;
|
||||
typedef T * pointer;
|
||||
typedef typename detail::add_const_if_c
|
||||
<typename Container::value_type, IsConst>
|
||||
::type value_type;
|
||||
typedef value_type & reference;
|
||||
typedef value_type * pointer;
|
||||
|
||||
list_iterator()
|
||||
: node_ (0)
|
||||
: members_ (0, 0)
|
||||
{}
|
||||
|
||||
explicit list_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
explicit list_iterator(node_ptr node, const Container *cont_ptr)
|
||||
: members_ (node, cont_ptr)
|
||||
{}
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
template <class OtherValue>
|
||||
list_iterator(list_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
|
||||
list_iterator(list_iterator<Container, false> const& other)
|
||||
: members_(other.pointed_node(), other.get_container())
|
||||
{}
|
||||
#else
|
||||
template <class OtherValue>
|
||||
list_iterator(list_iterator<OtherValue, ValueTraits> const& other,
|
||||
typename enable_if<
|
||||
is_convertible<OtherValue*,T*>
|
||||
>::type* = 0)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#endif
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
{ return members_.nodeptr_; }
|
||||
|
||||
list_iterator &operator=(const node_ptr &node)
|
||||
{ node_ = node; return static_cast<list_iterator&>(*this); }
|
||||
{ members_.nodeptr_ = node; return static_cast<list_iterator&>(*this); }
|
||||
|
||||
public:
|
||||
list_iterator& operator++()
|
||||
{
|
||||
node_ = node_traits::get_next(node_);
|
||||
members_.nodeptr_ = node_traits::get_next(members_.nodeptr_);
|
||||
return static_cast<list_iterator&> (*this);
|
||||
}
|
||||
|
||||
list_iterator operator++(int)
|
||||
{
|
||||
list_iterator result (node_);
|
||||
node_ = node_traits::get_next(node_);
|
||||
list_iterator result (*this);
|
||||
members_.nodeptr_ = node_traits::get_next(members_.nodeptr_);
|
||||
return result;
|
||||
}
|
||||
|
||||
list_iterator& operator--()
|
||||
{
|
||||
node_ = node_traits::get_previous(node_);
|
||||
members_.nodeptr_ = node_traits::get_previous(members_.nodeptr_);
|
||||
return static_cast<list_iterator&> (*this);
|
||||
}
|
||||
|
||||
list_iterator operator--(int)
|
||||
{
|
||||
list_iterator result (node_);
|
||||
node_ = node_traits::get_previous(node_);
|
||||
list_iterator result (*this);
|
||||
members_.nodeptr_ = node_traits::get_previous(members_.nodeptr_);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator== (const list_iterator& i) const
|
||||
{ return node_ == i.pointed_node(); }
|
||||
{ return members_.nodeptr_ == i.pointed_node(); }
|
||||
|
||||
bool operator!= (const list_iterator& i) const
|
||||
{ return !operator== (i); }
|
||||
{ return !operator== (i); }
|
||||
|
||||
T& operator*() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
value_type& operator*() const
|
||||
{ return *operator->(); }
|
||||
|
||||
pointer operator->() const
|
||||
{ return detail::get_pointer(ValueTraits::to_value_ptr(node_)); }
|
||||
{ return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); }
|
||||
|
||||
const Container *get_container() const
|
||||
{
|
||||
if(store_container_ptr){
|
||||
const Container* c = static_cast<const Container*>(members_.get_ptr());
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(c != 0);
|
||||
return c;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const real_value_traits *get_real_value_traits() const
|
||||
{
|
||||
if(store_container_ptr)
|
||||
return &this->get_container()->get_real_value_traits();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
node_ptr node_;
|
||||
struct members
|
||||
: public detail::select_constptr
|
||||
<void_pointer, store_container_ptr>::type
|
||||
{
|
||||
typedef typename detail::select_constptr
|
||||
<void_pointer, store_container_ptr>::type Base;
|
||||
|
||||
members(const node_ptr &n_ptr, const void *cont)
|
||||
: Base(cont), nodeptr_(n_ptr)
|
||||
{}
|
||||
|
||||
node_ptr nodeptr_;
|
||||
} members_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
|
@@ -17,6 +17,9 @@ namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
typedef char one;
|
||||
struct two {one _[2];};
|
||||
|
||||
template< bool C_ >
|
||||
struct bool_
|
||||
{
|
||||
@@ -55,7 +58,61 @@ class is_convertible
|
||||
static false_t dispatch(...);
|
||||
static T trigger();
|
||||
public:
|
||||
enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
|
||||
static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
|
||||
};
|
||||
|
||||
template<
|
||||
bool C
|
||||
, typename T1
|
||||
, typename T2
|
||||
>
|
||||
struct if_c
|
||||
{
|
||||
typedef T1 type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T1
|
||||
, typename T2
|
||||
>
|
||||
struct if_c<false,T1,T2>
|
||||
{
|
||||
typedef T2 type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename C
|
||||
, typename T1
|
||||
, typename T2
|
||||
>
|
||||
struct if_
|
||||
{
|
||||
typedef typename if_c<0 != C::value, T1, T2>::type type;
|
||||
};
|
||||
|
||||
template<
|
||||
bool C
|
||||
, typename F1
|
||||
, typename F2
|
||||
>
|
||||
struct eval_if_c
|
||||
: if_c<C,F1,F2>::type
|
||||
{};
|
||||
|
||||
template<
|
||||
typename C
|
||||
, typename T1
|
||||
, typename T2
|
||||
>
|
||||
struct eval_if
|
||||
: if_<C,T1,T2>::type
|
||||
{};
|
||||
|
||||
// identity is an extension: it is not part of the standard.
|
||||
template <class T>
|
||||
struct identity
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC) || defined(__BORLANDC_)
|
||||
@@ -130,18 +187,20 @@ yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1));
|
||||
template <typename T>
|
||||
struct is_unary_or_binary_function_impl
|
||||
{
|
||||
static T* t;
|
||||
enum{ value = sizeof(is_function_ptr_tester(t)) == sizeof(yes_type) };
|
||||
static T* t;
|
||||
static const bool value = sizeof(is_function_ptr_tester(t)) == sizeof(yes_type);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_unary_or_binary_function_impl<T&>
|
||||
{ enum {value = false }; };
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_unary_or_binary_function
|
||||
{
|
||||
enum{ value = is_unary_or_binary_function_impl<T>::value };
|
||||
static const bool value = is_unary_or_binary_function_impl<T>::value;
|
||||
};
|
||||
|
||||
//boost::alignment_of yields to 10K lines of preprocessed code, so we
|
||||
@@ -159,15 +218,68 @@ struct alignment_of_hack
|
||||
template <unsigned A, unsigned S>
|
||||
struct alignment_logic
|
||||
{
|
||||
enum{ value = A < S ? A : S };
|
||||
static const std::size_t value = A < S ? A : S;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct alignment_of
|
||||
{
|
||||
enum{ value = alignment_logic
|
||||
static const std::size_t value = alignment_logic
|
||||
< sizeof(alignment_of_hack<T>) - sizeof(T)
|
||||
, sizeof(T)>::value };
|
||||
, sizeof(T)
|
||||
>::value;
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_same
|
||||
{
|
||||
typedef char yes_type;
|
||||
struct no_type
|
||||
{
|
||||
char padding[8];
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
static yes_type is_same_tester(V*, V*);
|
||||
static no_type is_same_tester(...);
|
||||
|
||||
static T *t;
|
||||
static U *u;
|
||||
|
||||
static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct add_const
|
||||
{ typedef const T type; };
|
||||
|
||||
template<class T>
|
||||
struct remove_reference
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class Class>
|
||||
class is_empty_class
|
||||
{
|
||||
template <typename T>
|
||||
struct empty_helper_t1 : public T
|
||||
{
|
||||
empty_helper_t1();
|
||||
int i[256];
|
||||
};
|
||||
|
||||
struct empty_helper_t2
|
||||
{ int i[256]; };
|
||||
|
||||
public:
|
||||
static const bool value = sizeof(empty_helper_t1<Class>) == sizeof(empty_helper_t2);
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
|
28
include/boost/intrusive/detail/no_exceptions_support.hpp
Normal file
28
include/boost/intrusive/detail/no_exceptions_support.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007
|
||||
//
|
||||
// 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/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_NO_EXCEPTION_SUPPORT_HPP
|
||||
|
||||
#if !(defined BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING)
|
||||
# include <boost/detail/no_exceptions_support.hpp>
|
||||
# define BOOST_INTRUSIVE_TRY BOOST_TRY
|
||||
# define BOOST_INTRUSIVE_CATCH(x) BOOST_CATCH(x)
|
||||
# define BOOST_INTRUSIVE_RETHROW BOOST_RETHROW
|
||||
# define BOOST_INTRUSIVE_CATCH_END BOOST_CATCH_END
|
||||
#else
|
||||
# define BOOST_INTRUSIVE_TRY { if (true)
|
||||
# define BOOST_INTRUSIVE_CATCH(x) else if (false)
|
||||
# define BOOST_INTRUSIVE_RETHROW
|
||||
# define BOOST_INTRUSIVE_CATCH_END }
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_NO_EXCEPTION_SUPPORT_HPP
|
@@ -13,6 +13,7 @@
|
||||
#define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
@@ -22,14 +23,18 @@ namespace detail {
|
||||
template<class Parent, class Member>
|
||||
inline std::size_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member)
|
||||
{
|
||||
//BOOST_STATIC_ASSERT(( sizeof(std::ptrdiff_t) == sizeof(ptr_to_member) ));
|
||||
//The implementation of a pointer to member is compiler dependent.
|
||||
#if (defined(_MSC_VER) || defined(__GNUC__) || \
|
||||
defined(BOOST_INTEL) || defined(__HP_aCC))
|
||||
//This works with gcc, msvc, ac++
|
||||
#if defined(BOOST_MSVC) || (defined (BOOST_WINDOWS) && defined(BOOST_INTEL))
|
||||
//This works with gcc, msvc, ac++, ibmcpp
|
||||
return *(const std::ptrdiff_t*)(void*)&ptr_to_member;
|
||||
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || defined (__IBMCPP__)
|
||||
const Parent * const parent = 0;
|
||||
const char *const member = reinterpret_cast<const char*>(&(parent->*ptr_to_member));
|
||||
return std::size_t(member - reinterpret_cast<const char*>(parent));
|
||||
#else
|
||||
//This is the traditional C-front approach: __MWERKS__, __DMC__, __SUNPRO_CC
|
||||
return *(const std::ptrdiff_t*)(void*)&ptr_to_member - 1;
|
||||
return (*(const std::ptrdiff_t*)(void*)&ptr_to_member) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -18,19 +18,11 @@
|
||||
#include <iterator>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/rbtree_algorithms.hpp>
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#endif
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#endif
|
||||
#include <boost/intrusive/pointer_plus_bit.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
@@ -164,14 +156,14 @@ struct rbtree_node_traits_dispatch<VoidPointer, true>
|
||||
: public compact_rbtree_node_traits_impl<VoidPointer>
|
||||
{};
|
||||
|
||||
//Inherit from the dispatcher depending on the embedding capabilities
|
||||
//Inherit from the detail::link_dispatch depending on the embedding capabilities
|
||||
template<class VoidPointer>
|
||||
struct rbtree_node_traits
|
||||
: public rbtree_node_traits_dispatch
|
||||
<VoidPointer
|
||||
,has_pointer_plus_bit
|
||||
<VoidPointer, detail::alignment_of<compact_rbtree_node<VoidPointer>
|
||||
>::value
|
||||
< VoidPointer
|
||||
, has_pointer_plus_bit
|
||||
< VoidPointer
|
||||
, detail::alignment_of<compact_rbtree_node<VoidPointer> >::value
|
||||
>::value
|
||||
>
|
||||
{};
|
||||
@@ -182,179 +174,124 @@ struct rbtree_node_traits
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
|
||||
template<class T, class ValueTraits>
|
||||
class rbtree_iterator
|
||||
: public boost::iterator_facade
|
||||
< rbtree_iterator<T, ValueTraits>
|
||||
, T
|
||||
, boost::bidirectional_traversal_tag
|
||||
, T&
|
||||
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
|
||||
>
|
||||
{
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef rbtree_algorithms<node_traits> node_algorithms;
|
||||
struct enabler{};
|
||||
|
||||
public:
|
||||
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
|
||||
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
|
||||
|
||||
rbtree_iterator ()
|
||||
: node_ (0)
|
||||
{}
|
||||
|
||||
explicit rbtree_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
{}
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
template <class OtherValue>
|
||||
rbtree_iterator(rbtree_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#else
|
||||
template <class OtherValue>
|
||||
rbtree_iterator(rbtree_iterator<OtherValue, ValueTraits> const& other,
|
||||
typename enable_if<
|
||||
is_convertible<OtherValue*,T*>
|
||||
>::type* = 0)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#endif
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class, class> friend class rbtree_iterator;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(rbtree_iterator<OtherValue, ValueTraits> const& other) const
|
||||
{ return other.pointed_node() == node_; }
|
||||
|
||||
void increment()
|
||||
{ node_ = node_algorithms::next_node(node_); }
|
||||
|
||||
void decrement()
|
||||
{ node_ = node_algorithms::prev_node(node_); }
|
||||
|
||||
T& dereference() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
|
||||
node_ptr node_;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// rbtree_iterator provides some basic functions for a
|
||||
// node oriented bidirectional iterator:
|
||||
template<class T, class ValueTraits>
|
||||
template<class Container, bool IsConst>
|
||||
class rbtree_iterator
|
||||
: public std::iterator<std::bidirectional_iterator_tag, T>
|
||||
: public std::iterator
|
||||
< std::bidirectional_iterator_tag
|
||||
, typename detail::add_const_if_c
|
||||
<typename Container::value_type, IsConst>::type
|
||||
>
|
||||
{
|
||||
struct enabler{};
|
||||
protected:
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef rbtree_algorithms<node_traits> node_algorithms;
|
||||
|
||||
typedef typename Container::real_value_traits real_value_traits;
|
||||
typedef typename real_value_traits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef rbtree_algorithms<node_traits> node_algorithms;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, void>::type void_pointer;
|
||||
static const bool store_container_ptr =
|
||||
detail::store_cont_ptr_on_it<Container>::value;
|
||||
|
||||
public:
|
||||
typedef T & reference;
|
||||
typedef T * pointer;
|
||||
public:
|
||||
typedef typename detail::add_const_if_c
|
||||
<typename Container::value_type, IsConst>
|
||||
::type value_type;
|
||||
typedef value_type & reference;
|
||||
typedef value_type * pointer;
|
||||
|
||||
rbtree_iterator()
|
||||
: node_ (0)
|
||||
: members_ (0, 0)
|
||||
{}
|
||||
|
||||
explicit rbtree_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
explicit rbtree_iterator(node_ptr node, const Container *cont_ptr)
|
||||
: members_ (node, cont_ptr)
|
||||
{}
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
template <class OtherValue>
|
||||
rbtree_iterator(rbtree_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
rbtree_iterator(rbtree_iterator<Container, false> const& other)
|
||||
: members_(other.pointed_node(), other.get_container())
|
||||
{}
|
||||
#else
|
||||
template <class OtherValue>
|
||||
rbtree_iterator(rbtree_iterator<OtherValue, ValueTraits> const& other,
|
||||
typename enable_if<
|
||||
is_convertible<OtherValue*,T*>
|
||||
>::type* = 0)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#endif
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
{ return members_.nodeptr_; }
|
||||
|
||||
rbtree_iterator &operator=(const node_ptr &node)
|
||||
{ node_ = node; return static_cast<rbtree_iterator&>(*this); }
|
||||
{ members_.nodeptr_ = node; return static_cast<rbtree_iterator&>(*this); }
|
||||
|
||||
public:
|
||||
rbtree_iterator& operator++()
|
||||
{
|
||||
node_ = node_algorithms::next_node(node_);
|
||||
members_.nodeptr_ = node_algorithms::next_node(members_.nodeptr_);
|
||||
return static_cast<rbtree_iterator&> (*this);
|
||||
}
|
||||
|
||||
rbtree_iterator operator++(int)
|
||||
{
|
||||
rbtree_iterator result (node_);
|
||||
node_ = node_algorithms::next_node(node_);
|
||||
rbtree_iterator result (*this);
|
||||
members_.nodeptr_ = node_algorithms::next_node(members_.nodeptr_);
|
||||
return result;
|
||||
}
|
||||
|
||||
rbtree_iterator& operator--()
|
||||
{
|
||||
node_ = node_algorithms::prev_node(node_);
|
||||
members_.nodeptr_ = node_algorithms::prev_node(members_.nodeptr_);
|
||||
return static_cast<rbtree_iterator&> (*this);
|
||||
}
|
||||
|
||||
rbtree_iterator operator--(int)
|
||||
{
|
||||
rbtree_iterator result (node_);
|
||||
node_ = node_algorithms::prev_node(node_);
|
||||
rbtree_iterator result (*this);
|
||||
members_.nodeptr_ = node_algorithms::prev_node(members_.nodeptr_);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator== (const rbtree_iterator& i) const
|
||||
{ return node_ == i.pointed_node(); }
|
||||
{ return members_.nodeptr_ == i.pointed_node(); }
|
||||
|
||||
bool operator!= (const rbtree_iterator& i) const
|
||||
{ return !operator== (i); }
|
||||
|
||||
T& operator*() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
value_type& operator*() const
|
||||
{ return *operator->(); }
|
||||
|
||||
pointer operator->() const
|
||||
{ return detail::get_pointer(ValueTraits::to_value_ptr(node_)); }
|
||||
{ return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); }
|
||||
|
||||
const Container *get_container() const
|
||||
{
|
||||
if(store_container_ptr)
|
||||
return static_cast<const Container*>(members_.get_ptr());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const real_value_traits *get_real_value_traits() const
|
||||
{
|
||||
if(store_container_ptr)
|
||||
return &this->get_container()->get_real_value_traits();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
node_ptr node_;
|
||||
struct members
|
||||
: public detail::select_constptr
|
||||
<void_pointer, store_container_ptr>::type
|
||||
{
|
||||
typedef typename detail::select_constptr
|
||||
<void_pointer, store_container_ptr>::type Base;
|
||||
|
||||
members(const node_ptr &n_ptr, const void *cont)
|
||||
: Base(cont), nodeptr_(n_ptr)
|
||||
{}
|
||||
|
||||
node_ptr nodeptr_;
|
||||
} members_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
|
@@ -19,17 +19,17 @@
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/circular_slist_algorithms.hpp>
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#endif
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
template<class VoidPointer>
|
||||
struct slist_node
|
||||
{
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, slist_node>::type node_ptr;
|
||||
node_ptr next_;
|
||||
};
|
||||
|
||||
// slist_node_traits can be used with circular_slist_algorithms and supplies
|
||||
// a slist_node holding the pointers needed for a singly-linked list
|
||||
@@ -37,18 +37,12 @@ namespace detail {
|
||||
template<class VoidPointer>
|
||||
struct slist_node_traits
|
||||
{
|
||||
struct node;
|
||||
|
||||
typedef slist_node<VoidPointer> node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
|
||||
struct node
|
||||
{
|
||||
node_ptr next_;
|
||||
};
|
||||
|
||||
static node_ptr get_next(const_node_ptr n)
|
||||
{ return n->next_; }
|
||||
|
||||
@@ -56,163 +50,109 @@ struct slist_node_traits
|
||||
{ n->next_ = next; }
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_FACADE
|
||||
|
||||
// slist_iterator provides some basic functions for a
|
||||
// node oriented forward iterator:
|
||||
template<class T, class ValueTraits>
|
||||
class slist_iterator
|
||||
: public boost::iterator_facade
|
||||
< slist_iterator<T, ValueTraits>
|
||||
, T
|
||||
, boost::forward_traversal_tag
|
||||
, T&
|
||||
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
|
||||
>
|
||||
{
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
struct enabler{};
|
||||
|
||||
public:
|
||||
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
|
||||
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
|
||||
|
||||
slist_iterator ()
|
||||
: node_ (0)
|
||||
{}
|
||||
|
||||
explicit slist_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
{}
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
template <class OtherValue>
|
||||
slist_iterator(slist_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#else
|
||||
template <class OtherValue>
|
||||
slist_iterator(slist_iterator<OtherValue, ValueTraits> const& other,
|
||||
typename enable_if<
|
||||
is_convertible<OtherValue*,T*>
|
||||
>::type* = 0)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#endif
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class, class> friend class slist_iterator;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(slist_iterator<OtherValue, ValueTraits> const& other) const
|
||||
{ return other.pointed_node() == node_; }
|
||||
|
||||
void increment()
|
||||
{ node_ = node_traits::get_next(node_); }
|
||||
|
||||
T& dereference() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
|
||||
node_ptr node_;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// slist_iterator provides some basic functions for a
|
||||
// node oriented bidirectional iterator:
|
||||
template<class T, class ValueTraits>
|
||||
template<class Container, bool IsConst>
|
||||
class slist_iterator
|
||||
: public std::iterator<std::forward_iterator_tag, T>
|
||||
: public std::iterator
|
||||
< std::forward_iterator_tag
|
||||
, typename detail::add_const_if_c
|
||||
<typename Container::value_type, IsConst>::type
|
||||
>
|
||||
{
|
||||
struct enabler{};
|
||||
protected:
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
|
||||
typedef typename Container::real_value_traits real_value_traits;
|
||||
typedef typename real_value_traits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, void>::type void_pointer;
|
||||
static const bool store_container_ptr =
|
||||
detail::store_cont_ptr_on_it<Container>::value;
|
||||
|
||||
public:
|
||||
typedef T & reference;
|
||||
typedef T * pointer;
|
||||
typedef typename detail::add_const_if_c
|
||||
<typename Container::value_type, IsConst>
|
||||
::type value_type;
|
||||
typedef value_type & reference;
|
||||
typedef value_type * pointer;
|
||||
|
||||
slist_iterator()
|
||||
: node_ (0)
|
||||
: members_ (0, 0)
|
||||
{}
|
||||
|
||||
explicit slist_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
explicit slist_iterator(node_ptr node, const Container *cont_ptr)
|
||||
: members_ (node, cont_ptr)
|
||||
{}
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE
|
||||
template <class OtherValue>
|
||||
slist_iterator(slist_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
slist_iterator(slist_iterator<Container, false> const& other)
|
||||
: members_(other.pointed_node(), other.get_container())
|
||||
{}
|
||||
#else
|
||||
template <class OtherValue>
|
||||
slist_iterator(slist_iterator<OtherValue, ValueTraits> const& other,
|
||||
typename enable_if<
|
||||
is_convertible<OtherValue*,T*>
|
||||
>::type* = 0)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
#endif
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
{ return members_.nodeptr_; }
|
||||
|
||||
slist_iterator &operator=(const node_ptr &node)
|
||||
{ node_ = node; return static_cast<slist_iterator&>(*this); }
|
||||
{ members_.nodeptr_ = node; return static_cast<slist_iterator&>(*this); }
|
||||
|
||||
public:
|
||||
slist_iterator& operator++()
|
||||
{
|
||||
node_ = node_traits::get_next(node_);
|
||||
members_.nodeptr_ = node_traits::get_next(members_.nodeptr_);
|
||||
return static_cast<slist_iterator&> (*this);
|
||||
}
|
||||
|
||||
slist_iterator operator++(int)
|
||||
{
|
||||
slist_iterator result (node_);
|
||||
node_ = node_traits::get_next(node_);
|
||||
slist_iterator result (*this);
|
||||
members_.nodeptr_ = node_traits::get_next(members_.nodeptr_);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator== (const slist_iterator& i) const
|
||||
{ return node_ == i.pointed_node(); }
|
||||
{ return members_.nodeptr_ == i.pointed_node(); }
|
||||
|
||||
bool operator!= (const slist_iterator& i) const
|
||||
{ return !operator== (i); }
|
||||
{ return !operator== (i); }
|
||||
|
||||
T& operator*() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
value_type& operator*() const
|
||||
{ return *operator->(); }
|
||||
|
||||
pointer operator->() const
|
||||
{ return detail::get_pointer(ValueTraits::to_value_ptr(node_)); }
|
||||
{ return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); }
|
||||
|
||||
const Container *get_container() const
|
||||
{
|
||||
if(store_container_ptr)
|
||||
return static_cast<const Container*>(members_.get_ptr());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const real_value_traits *get_real_value_traits() const
|
||||
{
|
||||
if(store_container_ptr)
|
||||
return &this->get_container()->get_real_value_traits();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
node_ptr node_;
|
||||
struct members
|
||||
: public detail::select_constptr
|
||||
<void_pointer, store_container_ptr>::type
|
||||
{
|
||||
typedef typename detail::select_constptr
|
||||
<void_pointer, store_container_ptr>::type Base;
|
||||
|
||||
members(const node_ptr &n_ptr, const void *cont)
|
||||
: Base(cont), nodeptr_(n_ptr)
|
||||
{}
|
||||
|
||||
node_ptr nodeptr_;
|
||||
} members_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
|
173
include/boost/intrusive/detail/transform_iterator.hpp
Normal file
173
include/boost/intrusive/detail/transform_iterator.hpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007
|
||||
//
|
||||
// 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/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_DETAIL_TRANSFORM_ITERATOR_HPP
|
||||
#define BOOST_INTRUSIVE_DETAIL_TRANSFORM_ITERATOR_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
template <class PseudoReference>
|
||||
struct operator_arrow_proxy
|
||||
{
|
||||
operator_arrow_proxy(const PseudoReference &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
PseudoReference* operator->() const { return &m_value; }
|
||||
// This function is needed for MWCW and BCC, which won't call operator->
|
||||
// again automatically per 13.3.1.2 para 8
|
||||
// operator T*() const { return &m_value; }
|
||||
mutable PseudoReference m_value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct operator_arrow_proxy<T&>
|
||||
{
|
||||
operator_arrow_proxy(T &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
T* operator->() const { return &m_value; }
|
||||
// This function is needed for MWCW and BCC, which won't call operator->
|
||||
// again automatically per 13.3.1.2 para 8
|
||||
// operator T*() const { return &m_value; }
|
||||
mutable T &m_value;
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunction>
|
||||
class transform_iterator
|
||||
: public std::iterator
|
||||
< typename Iterator::iterator_category
|
||||
, typename detail::remove_reference<typename UnaryFunction::result_type>::type
|
||||
, typename Iterator::difference_type
|
||||
, operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
, typename UnaryFunction::result_type>
|
||||
{
|
||||
public:
|
||||
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
|
||||
: members_(it, f)
|
||||
{}
|
||||
|
||||
explicit transform_iterator()
|
||||
: members_()
|
||||
{}
|
||||
|
||||
Iterator get_it() const
|
||||
{ return members_.m_it; }
|
||||
|
||||
//Constructors
|
||||
transform_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
transform_iterator operator++(int)
|
||||
{
|
||||
transform_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
/*
|
||||
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
*/
|
||||
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
transform_iterator& operator+=(typename Iterator::difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
transform_iterator operator+(typename Iterator::difference_type off) const
|
||||
{
|
||||
transform_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
transform_iterator& operator-=(typename Iterator::difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
transform_iterator operator-(typename Iterator::difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
typename UnaryFunction::result_type operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
operator->() const
|
||||
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
|
||||
|
||||
private:
|
||||
struct members
|
||||
: UnaryFunction
|
||||
{
|
||||
members(const Iterator &it, const UnaryFunction &f)
|
||||
: UnaryFunction(f), m_it(it)
|
||||
{}
|
||||
|
||||
members()
|
||||
{}
|
||||
|
||||
Iterator m_it;
|
||||
} members_;
|
||||
|
||||
|
||||
void increment()
|
||||
{ ++members_.m_it; }
|
||||
|
||||
void decrement()
|
||||
{ --members_.m_it; }
|
||||
|
||||
bool equal(const transform_iterator &other) const
|
||||
{ return members_.m_it == other.members_.m_it; }
|
||||
|
||||
bool less(const transform_iterator &other) const
|
||||
{ return other.members_.m_it < members_.m_it; }
|
||||
|
||||
typename UnaryFunction::result_type dereference() const
|
||||
{ return members_(*members_.m_it); }
|
||||
|
||||
void advance(typename Iterator::difference_type n)
|
||||
{ std::advance(members_.m_it, n); }
|
||||
|
||||
typename Iterator::difference_type distance_to(const transform_iterator &other)const
|
||||
{ return std::distance(other.members_.m_it, members_.m_it); }
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_DETAIL_TRANSFORM_ITERATOR_HPP
|
@@ -17,7 +17,7 @@
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/parent_from_member.hpp>
|
||||
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
@@ -26,6 +26,64 @@ namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct internal_member_value_traits
|
||||
{
|
||||
template <class U> static detail::one test(...);
|
||||
template <class U> static detail::two test(typename U::member_value_traits* = 0);
|
||||
static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct internal_base_hook_bool
|
||||
{
|
||||
template<bool Add>
|
||||
struct two_or_three {one _[2 + Add];};
|
||||
template <class U> static one test(...);
|
||||
template <class U> static two_or_three<U::boost_intrusive_tags::is_base_hook>
|
||||
test (detail::bool_<U::boost_intrusive_tags::is_base_hook>* = 0);
|
||||
static const int value = sizeof(test<T>(0));
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct internal_base_hook_bool_is_true
|
||||
{
|
||||
static const bool value = internal_base_hook_bool<T>::value == 3;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct external_value_traits_bool
|
||||
{
|
||||
template<bool Add>
|
||||
struct two_or_three {one _[2 + Add];};
|
||||
template <class U> static one test(...);
|
||||
template <class U> static two_or_three<U::external_value_traits>
|
||||
test (detail::bool_<U::external_value_traits>* = 0);
|
||||
static const int value = sizeof(test<T>(0));
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct external_bucket_traits_bool
|
||||
{
|
||||
template<bool Add>
|
||||
struct two_or_three {one _[2 + Add];};
|
||||
template <class U> static one test(...);
|
||||
template <class U> static two_or_three<U::external_bucket_traits>
|
||||
test (detail::bool_<U::external_bucket_traits>* = 0);
|
||||
static const int value = sizeof(test<T>(0));
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct external_value_traits_is_true
|
||||
{
|
||||
static const bool value = external_value_traits_bool<T>::value == 3;
|
||||
};
|
||||
|
||||
template<class Node, class Tag, link_mode_type LinkMode, int>
|
||||
struct node_holder
|
||||
: public Node
|
||||
{};
|
||||
|
||||
template<class SmartPtr>
|
||||
struct smart_ptr_type
|
||||
{
|
||||
@@ -49,7 +107,6 @@ template<class Ptr>
|
||||
inline typename smart_ptr_type<Ptr>::pointer
|
||||
get_pointer(const Ptr &ptr)
|
||||
{ return smart_ptr_type<Ptr>::get(ptr); }
|
||||
//{ using boost::get_pointer; return get_pointer(ptr); }
|
||||
|
||||
//This functor compares a stored value
|
||||
//and the one passed as an argument
|
||||
@@ -75,10 +132,20 @@ class null_disposer
|
||||
{}
|
||||
};
|
||||
|
||||
template<class NodeAlgorithms>
|
||||
class init_disposer
|
||||
{
|
||||
typedef typename NodeAlgorithms::node_ptr node_ptr;
|
||||
|
||||
public:
|
||||
void operator()(node_ptr p)
|
||||
{ NodeAlgorithms::init(p); }
|
||||
};
|
||||
|
||||
template<bool ConstantSize, class SizeType>
|
||||
struct size_holder
|
||||
{
|
||||
enum { constant_time_size = ConstantSize };
|
||||
static const bool constant_time_size = ConstantSize;
|
||||
typedef SizeType size_type;
|
||||
|
||||
SizeType get_size() const
|
||||
@@ -99,7 +166,7 @@ struct size_holder
|
||||
template<class SizeType>
|
||||
struct size_holder<false, SizeType>
|
||||
{
|
||||
enum { constant_time_size = false };
|
||||
static const bool constant_time_size = false;
|
||||
typedef SizeType size_type;
|
||||
|
||||
size_type get_size() const
|
||||
@@ -115,11 +182,235 @@ struct size_holder<false, SizeType>
|
||||
{}
|
||||
};
|
||||
|
||||
template<class T, class DerivationHookType, typename Tag>
|
||||
struct derivation_hook_value_traits
|
||||
template<class KeyValueCompare, class Container>
|
||||
struct key_nodeptr_comp
|
||||
: private detail::ebo_functor_holder<KeyValueCompare>
|
||||
{
|
||||
typedef typename Container::real_value_traits real_value_traits;
|
||||
typedef typename real_value_traits::node_ptr node_ptr;
|
||||
typedef detail::ebo_functor_holder<KeyValueCompare> base_t;
|
||||
key_nodeptr_comp(KeyValueCompare kcomp, const Container *cont)
|
||||
: base_t(kcomp), cont_(cont)
|
||||
{}
|
||||
|
||||
template<class KeyType>
|
||||
bool operator()(node_ptr node, const KeyType &key) const
|
||||
{ return base_t::get()(*cont_->get_real_value_traits().to_value_ptr(node), key); }
|
||||
|
||||
template<class KeyType>
|
||||
bool operator()(const KeyType &key, node_ptr node) const
|
||||
{ return base_t::get()(key, *cont_->get_real_value_traits().to_value_ptr(node)); }
|
||||
|
||||
bool operator()(node_ptr node1, node_ptr node2) const
|
||||
{
|
||||
return base_t::get()
|
||||
( *cont_->get_real_value_traits().to_value_ptr(node1)
|
||||
, *cont_->get_real_value_traits().to_value_ptr(node2)
|
||||
);
|
||||
}
|
||||
|
||||
const Container *cont_;
|
||||
};
|
||||
|
||||
template<class F, class Container>
|
||||
struct node_cloner
|
||||
: private detail::ebo_functor_holder<F>
|
||||
{
|
||||
typedef typename Container::real_value_traits real_value_traits;
|
||||
typedef typename Container::node_algorithms node_algorithms;
|
||||
typedef typename real_value_traits::value_type value_type;
|
||||
typedef typename real_value_traits::pointer pointer;
|
||||
typedef typename real_value_traits::node_traits::node node;
|
||||
typedef typename real_value_traits::node_ptr node_ptr;
|
||||
typedef typename real_value_traits::const_node_ptr const_node_ptr;
|
||||
typedef detail::ebo_functor_holder<F> base_t;
|
||||
enum { safemode_or_autounlink =
|
||||
(int)real_value_traits::link_mode == (int)auto_unlink ||
|
||||
(int)real_value_traits::link_mode == (int)safe_link };
|
||||
|
||||
node_cloner(F f, const Container *cont)
|
||||
: base_t(f), cont_(cont)
|
||||
{}
|
||||
|
||||
node_ptr operator()(node_ptr p)
|
||||
{
|
||||
node_ptr n = cont_->get_real_value_traits().to_node_ptr
|
||||
(*base_t::get()(*cont_->get_real_value_traits().to_value_ptr(p)));
|
||||
//Cloned node must be in default mode if the linking mode requires it
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
|
||||
return n;
|
||||
}
|
||||
|
||||
node_ptr operator()(const node &to_clone)
|
||||
{
|
||||
const value_type &v =
|
||||
*cont_->get_real_value_traits().to_value_ptr(const_node_ptr(&to_clone));
|
||||
node_ptr n = cont_->get_real_value_traits().to_node_ptr(*base_t::get()(v));
|
||||
//Cloned node must be in default mode if the linking mode requires it
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
|
||||
return n;
|
||||
}
|
||||
|
||||
const Container *cont_;
|
||||
};
|
||||
|
||||
template<class F, class Container>
|
||||
struct node_disposer
|
||||
: private detail::ebo_functor_holder<F>
|
||||
{
|
||||
typedef typename Container::real_value_traits real_value_traits;
|
||||
typedef typename real_value_traits::node_ptr node_ptr;
|
||||
typedef detail::ebo_functor_holder<F> base_t;
|
||||
typedef typename Container::node_algorithms node_algorithms;
|
||||
enum { safemode_or_autounlink =
|
||||
(int)real_value_traits::link_mode == (int)auto_unlink ||
|
||||
(int)real_value_traits::link_mode == (int)safe_link };
|
||||
|
||||
node_disposer(F f, const Container *cont)
|
||||
: base_t(f), cont_(cont)
|
||||
{}
|
||||
|
||||
void operator()(node_ptr p)
|
||||
{
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(p);
|
||||
base_t::get()(cont_->get_real_value_traits().to_value_ptr(p));
|
||||
}
|
||||
const Container *cont_;
|
||||
};
|
||||
|
||||
struct dummy_constptr
|
||||
{
|
||||
dummy_constptr(const void *)
|
||||
{}
|
||||
|
||||
const void *get_ptr() const
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
struct constptr
|
||||
{
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const void>::type ConstVoidPtr;
|
||||
|
||||
constptr(const void *ptr)
|
||||
: const_void_ptr_(ptr)
|
||||
{}
|
||||
|
||||
const void *get_ptr() const
|
||||
{ return detail::get_pointer(const_void_ptr_); }
|
||||
|
||||
ConstVoidPtr const_void_ptr_;
|
||||
};
|
||||
|
||||
template <class VoidPointer, bool store_ptr>
|
||||
struct select_constptr
|
||||
{
|
||||
typedef typename detail::if_c
|
||||
< store_ptr
|
||||
, constptr<VoidPointer>
|
||||
, dummy_constptr
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Container>
|
||||
struct store_cont_ptr_on_it
|
||||
{
|
||||
typedef typename Container::value_traits value_traits;
|
||||
static const bool value =
|
||||
!detail::is_empty_class<value_traits>::value
|
||||
|| detail::external_value_traits_is_true<value_traits>::value
|
||||
;
|
||||
};
|
||||
|
||||
template<class T, bool Add>
|
||||
struct add_const_if_c
|
||||
{
|
||||
typedef typename detail::if_c
|
||||
< Add
|
||||
, typename detail::add_const<T>::type
|
||||
, T
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<class Container, bool IsConst>
|
||||
struct node_to_value
|
||||
: public detail::select_constptr
|
||||
< typename boost::pointer_to_other
|
||||
<typename Container::pointer, void>::type
|
||||
, detail::store_cont_ptr_on_it<Container>::value
|
||||
>::type
|
||||
{
|
||||
static const bool store_container_ptr =
|
||||
detail::store_cont_ptr_on_it<Container>::value;
|
||||
|
||||
typedef typename Container::real_value_traits real_value_traits;
|
||||
typedef typename real_value_traits::value_type value_type;
|
||||
typedef typename detail::select_constptr
|
||||
< typename boost::pointer_to_other
|
||||
<typename Container::pointer, void>::type
|
||||
, store_container_ptr >::type Base;
|
||||
typedef typename real_value_traits::node_traits::node node;
|
||||
typedef typename detail::add_const_if_c
|
||||
<value_type, IsConst>::type vtype;
|
||||
typedef typename detail::add_const_if_c
|
||||
<node, IsConst>::type ntype;
|
||||
typedef typename boost::pointer_to_other
|
||||
<typename Container::pointer, ntype>::type npointer;
|
||||
|
||||
node_to_value(const Container *cont)
|
||||
: Base(cont)
|
||||
{}
|
||||
|
||||
typedef vtype & result_type;
|
||||
typedef ntype & first_argument_type;
|
||||
|
||||
const Container *get_container() const
|
||||
{
|
||||
if(store_container_ptr)
|
||||
return static_cast<const Container*>(Base::get_ptr());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const real_value_traits *get_real_value_traits() const
|
||||
{
|
||||
if(store_container_ptr)
|
||||
return &this->get_container()->get_real_value_traits();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
result_type operator()(first_argument_type arg) const
|
||||
{ return *(this->get_real_value_traits()->to_value_ptr(npointer(&arg))); }
|
||||
};
|
||||
|
||||
template <link_mode_type LinkMode>
|
||||
struct link_dispatch
|
||||
{};
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &cont, detail::link_dispatch<safe_link>)
|
||||
{ (void)cont; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!cont.is_linked()); }
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &cont, detail::link_dispatch<auto_unlink>)
|
||||
{ cont.unlink(); }
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &, detail::link_dispatch<normal_link>)
|
||||
{}
|
||||
|
||||
template<class T, class NodeTraits, link_mode_type LinkMode, class Tag, int HookType>
|
||||
struct base_hook_traits
|
||||
{
|
||||
public:
|
||||
typedef typename DerivationHookType::node_traits node_traits;
|
||||
typedef detail::node_holder
|
||||
<typename NodeTraits::node, Tag, LinkMode, HookType> node_holder;
|
||||
typedef NodeTraits node_traits;
|
||||
typedef T value_type;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
@@ -127,173 +418,61 @@ struct derivation_hook_value_traits
|
||||
typedef typename boost::pointer_to_other<node_ptr, const T>::type const_pointer;
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
enum { linking_policy = DerivationHookType::linking_policy };
|
||||
static const link_mode_type link_mode = LinkMode;
|
||||
|
||||
static node_ptr to_node_ptr(reference value)
|
||||
{ return static_cast<DerivationHookType &>(value).to_node_ptr(); }
|
||||
{ return static_cast<node_holder*>(&value); }
|
||||
|
||||
static const_node_ptr to_node_ptr(const_reference value)
|
||||
{ return static_cast<const DerivationHookType &>(value).to_node_ptr(); }
|
||||
{ return static_cast<const node_holder*>(&value); }
|
||||
|
||||
static pointer to_value_ptr(node_ptr n)
|
||||
{
|
||||
return static_cast<T*>(detail::get_pointer(DerivationHookType::to_hook_ptr(n)));
|
||||
}
|
||||
{ return static_cast<T*>(static_cast<node_holder*>(&*n)); }
|
||||
|
||||
static const_pointer to_value_ptr(const_node_ptr n)
|
||||
{
|
||||
return static_cast<const T*>(detail::get_pointer(DerivationHookType::to_hook_ptr(n)));
|
||||
}
|
||||
{ return static_cast<const T*>(static_cast<const node_holder*>(&*n)); }
|
||||
};
|
||||
|
||||
|
||||
template<class T, class MemberHookType, MemberHookType T::* P>
|
||||
struct member_hook_value_traits
|
||||
template<class T, class Hook, Hook T::* P>
|
||||
struct member_hook_traits
|
||||
{
|
||||
public:
|
||||
typedef typename MemberHookType::node_traits node_traits;
|
||||
typedef Hook hook_type;
|
||||
typedef typename hook_type::boost_intrusive_tags::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef T value_type;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef typename boost::pointer_to_other<node_ptr, T>::type pointer;
|
||||
typedef typename boost::pointer_to_other<node_ptr, const T>::type const_pointer;
|
||||
typedef value_type & reference;
|
||||
typedef const value_type & const_reference;
|
||||
enum { linking_policy = MemberHookType::linking_policy };
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
static const link_mode_type link_mode = Hook::boost_intrusive_tags::link_mode;
|
||||
|
||||
public:
|
||||
static node_ptr to_node_ptr(reference value)
|
||||
{
|
||||
MemberHookType* result = &(value.*P);
|
||||
return result->to_node_ptr();
|
||||
return reinterpret_cast<node*>(&(value.*P));
|
||||
}
|
||||
|
||||
static const_node_ptr to_node_ptr(const_reference value)
|
||||
{
|
||||
const MemberHookType* result = &(value.*P);
|
||||
return result->to_node_ptr();
|
||||
return static_cast<const node*>(&(value.*P));
|
||||
}
|
||||
|
||||
static pointer to_value_ptr(node_ptr n)
|
||||
{
|
||||
return pointer
|
||||
(
|
||||
parent_from_member<value_type, MemberHookType>
|
||||
(detail::get_pointer(MemberHookType::to_hook_ptr(n)), P)
|
||||
);
|
||||
return detail::parent_from_member<T, Hook>
|
||||
(static_cast<Hook*>(detail::get_pointer(n)), P);
|
||||
}
|
||||
|
||||
static const_pointer to_value_ptr(const_node_ptr n)
|
||||
{
|
||||
return const_pointer
|
||||
(
|
||||
parent_from_member<value_type, MemberHookType>
|
||||
(detail::get_pointer(MemberHookType::to_hook_ptr(n)), P)
|
||||
);
|
||||
return detail::parent_from_member<T, Hook>
|
||||
(static_cast<const Hook*>(detail::get_pointer(n)), P);
|
||||
}
|
||||
};
|
||||
|
||||
template<class KeyValueCompare, class ValueTraits>
|
||||
struct key_node_ptr_compare
|
||||
: private detail::ebo_functor_holder<KeyValueCompare>
|
||||
{
|
||||
typedef typename ValueTraits::node_ptr node_ptr;
|
||||
typedef detail::ebo_functor_holder<KeyValueCompare> base_t;
|
||||
key_node_ptr_compare(KeyValueCompare kcomp)
|
||||
: base_t(kcomp)
|
||||
{}
|
||||
|
||||
template<class KeyType>
|
||||
bool operator()(node_ptr node, const KeyType &key) const
|
||||
{ return base_t::get()(*ValueTraits::to_value_ptr(node), key); }
|
||||
|
||||
template<class KeyType>
|
||||
bool operator()(const KeyType &key, node_ptr node) const
|
||||
{ return base_t::get()(key, *ValueTraits::to_value_ptr(node)); }
|
||||
|
||||
bool operator()(node_ptr node1, node_ptr node2) const
|
||||
{
|
||||
return base_t::get()
|
||||
(*ValueTraits::to_value_ptr(node1), *ValueTraits::to_value_ptr(node2));
|
||||
}
|
||||
};
|
||||
|
||||
template<class F, class ValueTraits>
|
||||
struct value_to_node_cloner
|
||||
: private detail::ebo_functor_holder<F>
|
||||
{
|
||||
typedef typename ValueTraits::node_ptr node_ptr;
|
||||
typedef detail::ebo_functor_holder<F> base_t;
|
||||
|
||||
value_to_node_cloner(F f)
|
||||
: base_t(f)
|
||||
{}
|
||||
|
||||
node_ptr operator()(node_ptr p)
|
||||
{ return ValueTraits::to_node_ptr(*base_t::get()(*ValueTraits::to_value_ptr(p))); }
|
||||
};
|
||||
|
||||
template<class F, class ValueTraits>
|
||||
struct value_to_node_disposer
|
||||
: private detail::ebo_functor_holder<F>
|
||||
{
|
||||
typedef typename ValueTraits::node_ptr node_ptr;
|
||||
typedef detail::ebo_functor_holder<F> base_t;
|
||||
value_to_node_disposer(F f)
|
||||
: base_t(f)
|
||||
{}
|
||||
|
||||
void operator()(node_ptr p)
|
||||
{ base_t::get()(ValueTraits::to_value_ptr(p)); }
|
||||
};
|
||||
|
||||
template <linking_policy Policy>
|
||||
struct dispatcher
|
||||
{};
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &cont, dispatcher<safe_link>)
|
||||
{ (void)cont; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!cont.is_linked()); }
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &cont, dispatcher<auto_unlink>)
|
||||
{ cont.unlink(); }
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &, dispatcher<normal_link>)
|
||||
{}
|
||||
|
||||
template<class Node, class MaybeClass>
|
||||
struct node_plus_pred
|
||||
: public ebo_functor_holder<MaybeClass>
|
||||
, public Node
|
||||
{
|
||||
node_plus_pred()
|
||||
{}
|
||||
|
||||
node_plus_pred(const Node &x, const MaybeClass &y)
|
||||
: Node(x), ebo_functor_holder<MaybeClass>(y) {}
|
||||
|
||||
node_plus_pred(const MaybeClass &y)
|
||||
: ebo_functor_holder<MaybeClass>(y) {}
|
||||
|
||||
Node &first()
|
||||
{ return *this; }
|
||||
const Node &first() const
|
||||
{ return *this; }
|
||||
MaybeClass &second()
|
||||
{ return ebo_functor_holder<MaybeClass>::get(); }
|
||||
const MaybeClass &second() const
|
||||
{ return ebo_functor_holder<MaybeClass>::get(); }
|
||||
|
||||
static node_plus_pred *this_from_node(Node *n)
|
||||
{ return static_cast<node_plus_pred*>(n); }
|
||||
|
||||
static node_plus_pred *this_from_node(const Node *n)
|
||||
{ return static_cast<const node_plus_pred*>(n); }
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,9 @@
|
||||
#define BOOST_INTRUSIVE_FWD_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/tag.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
|
||||
/// @cond
|
||||
|
||||
//std predeclarations
|
||||
namespace std{
|
||||
@@ -36,6 +37,14 @@ struct hash;
|
||||
|
||||
namespace intrusive {
|
||||
|
||||
struct none;
|
||||
|
||||
} //namespace intrusive{
|
||||
} //namespace boost{
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
////////////////////////////
|
||||
// Node algorithms
|
||||
////////////////////////////
|
||||
@@ -55,104 +64,148 @@ class rbtree_algorithms;
|
||||
////////////////////////////
|
||||
|
||||
//slist
|
||||
template < class ValueTraits
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t>
|
||||
template
|
||||
< class T
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class slist;
|
||||
|
||||
template< class Tag = tag
|
||||
, linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *
|
||||
>
|
||||
template
|
||||
< class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class slist_base_hook;
|
||||
|
||||
template< linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *>
|
||||
template
|
||||
< class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class slist_member_hook;
|
||||
|
||||
//list
|
||||
template< class ValueTraits
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t>
|
||||
template
|
||||
< class T
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class list;
|
||||
|
||||
template< class Tag = tag
|
||||
, linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *
|
||||
>
|
||||
template
|
||||
< class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class list_base_hook;
|
||||
|
||||
template< linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *>
|
||||
template
|
||||
< class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class list_member_hook;
|
||||
|
||||
//hash/unordered
|
||||
template< class ValueTraits
|
||||
, class Hash = boost::hash<typename ValueTraits::value_type>
|
||||
, class Equal = std::equal_to<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t
|
||||
>
|
||||
class hashtable;
|
||||
|
||||
template< class ValueTraits
|
||||
, class Hash = boost::hash<typename ValueTraits::value_type>
|
||||
, class Equal = std::equal_to<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t
|
||||
>
|
||||
class unordered_set;
|
||||
|
||||
template< class ValueTraits
|
||||
, class Hash = boost::hash<typename ValueTraits::value_type>
|
||||
, class Equal = std::equal_to<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t
|
||||
>
|
||||
class unordered_multiset;
|
||||
|
||||
template< class Tag = tag
|
||||
, linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *
|
||||
>
|
||||
class unordered_set_base_hook;
|
||||
|
||||
template< linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *>
|
||||
class unordered_set_member_hook;
|
||||
|
||||
|
||||
//rbtree/set
|
||||
template < class ValueTraits
|
||||
, class Compare = std::less<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t
|
||||
>
|
||||
//rbtree/set/multiset
|
||||
template
|
||||
< class T
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
, class O4 = none
|
||||
>
|
||||
class rbtree;
|
||||
|
||||
template < class ValueTraits
|
||||
, class Compare = std::less<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t>
|
||||
template
|
||||
< class T
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
, class O4 = none
|
||||
>
|
||||
class set;
|
||||
|
||||
template < class ValueTraits
|
||||
, class Compare = std::less<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t>
|
||||
template
|
||||
< class T
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
, class O4 = none
|
||||
>
|
||||
class multiset;
|
||||
|
||||
template< class Tag = tag
|
||||
, linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *
|
||||
>
|
||||
template
|
||||
< class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class set_base_hook;
|
||||
|
||||
template< linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *>
|
||||
template
|
||||
< class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class set_member_hook;
|
||||
|
||||
//hash/unordered
|
||||
//rbtree/set/multiset
|
||||
template
|
||||
< class T
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
, class O4 = none
|
||||
, class O5 = none
|
||||
, class O6 = none
|
||||
, class O7 = none
|
||||
>
|
||||
class hashtable;
|
||||
|
||||
template
|
||||
< class T
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
, class O4 = none
|
||||
, class O5 = none
|
||||
, class O6 = none
|
||||
, class O7 = none
|
||||
>
|
||||
class unordered_set;
|
||||
|
||||
template
|
||||
< class T
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
, class O4 = none
|
||||
, class O5 = none
|
||||
, class O6 = none
|
||||
, class O7 = none
|
||||
>
|
||||
class unordered_multiset;
|
||||
|
||||
template
|
||||
< class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class unordered_set_base_hook;
|
||||
|
||||
template
|
||||
< class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
>
|
||||
class unordered_set_member_hook;
|
||||
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
/// @endcond
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_FWD_HPP
|
||||
|
@@ -10,24 +10,24 @@
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_VALUE_LINKING_POLICY_HPP
|
||||
#define BOOST_INTRUSIVE_VALUE_LINKING_POLICY_HPP
|
||||
#ifndef BOOST_INTRUSIVE_VALUE_LINK_TYPE_HPP
|
||||
#define BOOST_INTRUSIVE_VALUE_LINK_TYPE_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//!This enumeration defines the type of value_traits that can be defined
|
||||
//!for Boost.Intrusive containers
|
||||
enum linking_policy{
|
||||
enum link_mode_type{
|
||||
//!If this linking policy is specified in a value_traits class
|
||||
//!as the linking_policy, containers
|
||||
//!as the link_mode, containers
|
||||
//!configured with such value_traits won't set the hooks
|
||||
//!of the erased values to a default state. Containers also won't
|
||||
//!check that the hooks of the new values are default initialized.
|
||||
normal_link,
|
||||
|
||||
//!If this linking policy is specified in a value_traits class
|
||||
//!as the linking_policy, containers
|
||||
//!as the link_mode, containers
|
||||
//!configured with such value_traits will set the hooks
|
||||
//!of the erased values to a default state. Containers also will
|
||||
//!check that the hooks of the new values are default initialized.
|
||||
@@ -43,4 +43,4 @@ enum linking_policy{
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#endif //BOOST_INTRUSIVE_VALUE_LINKING_POLICY_HPP
|
||||
#endif //BOOST_INTRUSIVE_VALUE_LINK_TYPE_HPP
|
@@ -20,79 +20,127 @@
|
||||
#include <boost/intrusive/list_hook.hpp>
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#endif
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
/// @cond
|
||||
|
||||
template <class T>
|
||||
struct internal_default_list_hook
|
||||
{
|
||||
template <class U> static detail::one test(...);
|
||||
template <class U> static detail::two test(typename U::default_list_hook* = 0);
|
||||
static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct get_default_list_hook
|
||||
{
|
||||
typedef typename T::default_list_hook type;
|
||||
};
|
||||
|
||||
template <class ValueTraits, class SizeType, bool ConstantTimeSize>
|
||||
struct listopt
|
||||
{
|
||||
typedef ValueTraits value_traits;
|
||||
typedef SizeType size_type;
|
||||
static const bool constant_time_size = ConstantTimeSize;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct list_defaults
|
||||
: pack_options
|
||||
< none
|
||||
, base_hook
|
||||
< typename detail::eval_if_c
|
||||
< internal_default_list_hook<T>::value
|
||||
, get_default_list_hook<T>
|
||||
, detail::identity<none>
|
||||
>::type
|
||||
>
|
||||
, constant_time_size<true>
|
||||
, size_type<std::size_t>
|
||||
>::type
|
||||
{};
|
||||
|
||||
/// @endcond
|
||||
|
||||
//! The class template list is an intrusive container that mimics most of the
|
||||
//! interface of std::list as described in the C++ standard.
|
||||
//!
|
||||
//! The template parameter ValueTraits is called "value traits". It stores
|
||||
//! information and operations about the type to be stored in the container.
|
||||
//! The template parameter \c T is the type to be managed by the container.
|
||||
//! The user can specify additional options and if no options are provided
|
||||
//! default options are used.
|
||||
//!
|
||||
//! If the user specifies ConstantTimeSize as "true", a member of type SizeType
|
||||
//! will be embedded in the class, that will keep track of the number of stored objects.
|
||||
//! This will allow constant-time O(1) size() member, instead of default O(N) size.
|
||||
template< class ValueTraits
|
||||
, bool ConstantTimeSize //= true
|
||||
, class SizeType //= std::size_t
|
||||
>
|
||||
class list
|
||||
: private detail::size_holder<ConstantTimeSize, SizeType>
|
||||
//! The container supports the following options:
|
||||
//! \c base_hook<>/member_hook<>/value_traits<>,
|
||||
//! \c constant_time_size<> and \c size_type<>.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
class list_impl
|
||||
{
|
||||
/// @cond
|
||||
private:
|
||||
typename ValueTraits::node_traits::node root_;
|
||||
typedef list<ValueTraits, ConstantTimeSize, SizeType> this_type;
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef detail::size_holder<ConstantTimeSize, SizeType> size_traits;
|
||||
|
||||
//! This class is
|
||||
//! non-copyable
|
||||
list (const list&);
|
||||
|
||||
//! This class is
|
||||
//! non-assignable
|
||||
list &operator =(const list&);
|
||||
/// @endcond
|
||||
|
||||
//Public typedefs
|
||||
public:
|
||||
typedef ValueTraits value_traits;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ValueTraits::pointer pointer;
|
||||
typedef typename ValueTraits::const_pointer const_pointer;
|
||||
typedef typename Config::value_traits value_traits;
|
||||
/// @cond
|
||||
static const bool external_value_traits =
|
||||
detail::external_value_traits_is_true<value_traits>::value;
|
||||
typedef typename detail::eval_if_c
|
||||
< external_value_traits
|
||||
, detail::eval_value_traits<value_traits>
|
||||
, detail::identity<value_traits>
|
||||
>::type real_value_traits;
|
||||
/// @endcond
|
||||
typedef typename real_value_traits::pointer pointer;
|
||||
typedef typename real_value_traits::const_pointer const_pointer;
|
||||
typedef typename std::iterator_traits<pointer>::value_type value_type;
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
typedef typename std::iterator_traits<pointer>::difference_type difference_type;
|
||||
typedef SizeType size_type;
|
||||
typedef detail::list_iterator<value_type, ValueTraits> iterator;
|
||||
typedef detail::list_iterator<const value_type, ValueTraits> const_iterator;
|
||||
typedef typename Config::size_type size_type;
|
||||
typedef list_iterator<list_impl, false> iterator;
|
||||
typedef list_iterator<list_impl, true> const_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef typename real_value_traits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef circular_list_algorithms<node_traits> node_algorithms;
|
||||
|
||||
static const bool constant_time_size = Config::constant_time_size;
|
||||
static const bool stateful_value_traits = detail::store_cont_ptr_on_it<list_impl>::value;
|
||||
|
||||
/// @cond
|
||||
|
||||
private:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef circular_list_algorithms<node_traits> node_algorithms;
|
||||
typedef detail::size_holder<constant_time_size, size_type> size_traits;
|
||||
|
||||
//Non-copyable and non-moveable
|
||||
list_impl (const list_impl&);
|
||||
list_impl &operator =(const list_impl&);
|
||||
|
||||
enum { safemode_or_autounlink =
|
||||
(int)ValueTraits::linking_policy == (int)auto_unlink ||
|
||||
(int)ValueTraits::linking_policy == (int)safe_link };
|
||||
(int)real_value_traits::link_mode == (int)auto_unlink ||
|
||||
(int)real_value_traits::link_mode == (int)safe_link };
|
||||
|
||||
//Constant-time size is incompatible with auto-unlink hooks!
|
||||
BOOST_STATIC_ASSERT(!(ConstantTimeSize && ((int)ValueTraits::linking_policy == (int)auto_unlink)));
|
||||
BOOST_STATIC_ASSERT(!(constant_time_size &&
|
||||
((int)real_value_traits::link_mode == (int)auto_unlink)
|
||||
));
|
||||
|
||||
//Const cast emulation for smart pointers
|
||||
static node_ptr uncast(const_node_ptr ptr)
|
||||
@@ -102,22 +150,64 @@ class list
|
||||
}
|
||||
|
||||
node_ptr get_root_node()
|
||||
{ return node_ptr(&root_); }
|
||||
{ return node_ptr(&data_.root_plus_size_.root_); }
|
||||
|
||||
const_node_ptr get_root_node() const
|
||||
{ return const_node_ptr(&root_); }
|
||||
{ return const_node_ptr(&data_.root_plus_size_.root_); }
|
||||
|
||||
struct root_plus_size : public size_traits
|
||||
{
|
||||
node root_;
|
||||
};
|
||||
|
||||
struct data_t : public value_traits
|
||||
{
|
||||
typedef typename list_impl::value_traits value_traits;
|
||||
data_t(const value_traits &val_traits)
|
||||
: value_traits(val_traits)
|
||||
{}
|
||||
|
||||
root_plus_size root_plus_size_;
|
||||
} data_;
|
||||
|
||||
size_traits &priv_size_traits()
|
||||
{ return data_.root_plus_size_; }
|
||||
|
||||
const size_traits &priv_size_traits() const
|
||||
{ return data_.root_plus_size_; }
|
||||
|
||||
const real_value_traits &get_real_value_traits(detail::bool_<false>) const
|
||||
{ return data_; }
|
||||
|
||||
const real_value_traits &get_real_value_traits(detail::bool_<true>) const
|
||||
{ return data_.get_value_traits(*this); }
|
||||
|
||||
real_value_traits &get_real_value_traits(detail::bool_<false>)
|
||||
{ return data_; }
|
||||
|
||||
real_value_traits &get_real_value_traits(detail::bool_<true>)
|
||||
{ return data_.get_value_traits(*this); }
|
||||
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
const real_value_traits &get_real_value_traits() const
|
||||
{ return this->get_real_value_traits(detail::bool_<external_value_traits>()); }
|
||||
|
||||
real_value_traits &get_real_value_traits()
|
||||
{ return this->get_real_value_traits(detail::bool_<external_value_traits>()); }
|
||||
|
||||
//! <b>Effects</b>: constructs an empty list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: If value_traits::node_traits::node
|
||||
//! <b>Throws</b>: If real_value_traits::node_traits::node
|
||||
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
|
||||
list()
|
||||
list_impl(const value_traits &v_traits = value_traits())
|
||||
: data_(v_traits)
|
||||
{
|
||||
size_traits::set_size(size_type(0));
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
node_algorithms::init(this->get_root_node());
|
||||
}
|
||||
|
||||
@@ -127,12 +217,13 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear in std::distance(b, e). No copy constructors are called.
|
||||
//!
|
||||
//! <b>Throws</b>: If value_traits::node_traits::node
|
||||
//! <b>Throws</b>: If real_value_traits::node_traits::node
|
||||
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
|
||||
template<class Iterator>
|
||||
list(Iterator b, Iterator e)
|
||||
list_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
|
||||
: data_(v_traits)
|
||||
{
|
||||
size_traits::set_size(size_type(0));
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
node_algorithms::init(this->get_root_node());
|
||||
this->insert(this->end(), b, e);
|
||||
}
|
||||
@@ -146,7 +237,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the list, if
|
||||
//! it's a safe-mode or auto-unlink value . Otherwise constant.
|
||||
~list()
|
||||
~list_impl()
|
||||
{
|
||||
if(safemode_or_autounlink){
|
||||
this->clear();
|
||||
@@ -165,11 +256,11 @@ class list
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void push_back(reference value)
|
||||
{
|
||||
node_ptr to_insert = ValueTraits::to_node_ptr(value);
|
||||
node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
node_algorithms::link_before(this->get_root_node(), to_insert);
|
||||
size_traits::increment();
|
||||
this->priv_size_traits().increment();
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be an lvalue.
|
||||
@@ -184,11 +275,11 @@ class list
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void push_front(reference value)
|
||||
{
|
||||
node_ptr to_insert = ValueTraits::to_node_ptr(value);
|
||||
node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert);
|
||||
size_traits::increment();
|
||||
this->priv_size_traits().increment();
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Erases the last element of the list.
|
||||
@@ -203,7 +294,7 @@ class list
|
||||
{
|
||||
node_ptr to_erase = node_traits::get_previous(this->get_root_node());
|
||||
node_algorithms::unlink(to_erase);
|
||||
size_traits::decrement();
|
||||
this->priv_size_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
}
|
||||
@@ -224,10 +315,10 @@ class list
|
||||
{
|
||||
node_ptr to_erase = node_traits::get_previous(this->get_root_node());
|
||||
node_algorithms::unlink(to_erase);
|
||||
size_traits::decrement();
|
||||
this->priv_size_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
disposer(ValueTraits::to_value_ptr(to_erase));
|
||||
disposer(get_real_value_traits().to_value_ptr(to_erase));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Erases the first element of the list.
|
||||
@@ -242,7 +333,7 @@ class list
|
||||
{
|
||||
node_ptr to_erase = node_traits::get_next(this->get_root_node());
|
||||
node_algorithms::unlink(to_erase);
|
||||
size_traits::decrement();
|
||||
this->priv_size_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
}
|
||||
@@ -263,10 +354,10 @@ class list
|
||||
{
|
||||
node_ptr to_erase = node_traits::get_next(this->get_root_node());
|
||||
node_algorithms::unlink(to_erase);
|
||||
size_traits::decrement();
|
||||
this->priv_size_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
disposer(ValueTraits::to_value_ptr(to_erase));
|
||||
disposer(get_real_value_traits().to_value_ptr(to_erase));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a reference to the first element of the list.
|
||||
@@ -275,7 +366,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
reference front()
|
||||
{ return *ValueTraits::to_value_ptr(node_traits::get_next(this->get_root_node())); }
|
||||
{ return *get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_reference to the first element of the list.
|
||||
//!
|
||||
@@ -283,7 +374,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_reference front() const
|
||||
{ return *ValueTraits::to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); }
|
||||
{ return *get_real_value_traits().to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); }
|
||||
|
||||
//! <b>Effects</b>: Returns a reference to the last element of the list.
|
||||
//!
|
||||
@@ -291,7 +382,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
reference back()
|
||||
{ return *ValueTraits::to_value_ptr(node_traits::get_previous(this->get_root_node())); }
|
||||
{ return *get_real_value_traits().to_value_ptr(node_traits::get_previous(this->get_root_node())); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_reference to the last element of the list.
|
||||
//!
|
||||
@@ -299,7 +390,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_reference back() const
|
||||
{ return *ValueTraits::to_value_ptr(uncast(node_traits::get_previous(this->get_root_node()))); }
|
||||
{ return *get_real_value_traits().to_value_ptr(uncast(node_traits::get_previous(this->get_root_node()))); }
|
||||
|
||||
//! <b>Effects</b>: Returns an iterator to the first element contained in the list.
|
||||
//!
|
||||
@@ -307,7 +398,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
iterator begin()
|
||||
{ return iterator(node_traits::get_next(this->get_root_node())); }
|
||||
{ return iterator(node_traits::get_next(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
|
||||
//!
|
||||
@@ -323,7 +414,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator cbegin() const
|
||||
{ return const_iterator(node_traits::get_next(this->get_root_node())); }
|
||||
{ return const_iterator(node_traits::get_next(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns an iterator to the end of the list.
|
||||
//!
|
||||
@@ -331,7 +422,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
iterator end()
|
||||
{ return iterator(this->get_root_node()); }
|
||||
{ return iterator(this->get_root_node(), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
|
||||
//!
|
||||
@@ -347,7 +438,7 @@ class list
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator cend() const
|
||||
{ return const_iterator(uncast(this->get_root_node())); }
|
||||
{ return const_iterator(uncast(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
|
||||
//! of the reversed list.
|
||||
@@ -411,11 +502,8 @@ class list
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
static list &container_from_end_iterator(iterator end_iterator)
|
||||
{
|
||||
return *detail::parent_from_member<list, node>
|
||||
( detail::get_pointer(end_iterator.pointed_node()), &list::root_);
|
||||
}
|
||||
static list_impl &container_from_end_iterator(iterator end_iterator)
|
||||
{ return priv_container_from_end_iterator(end_iterator); }
|
||||
|
||||
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator
|
||||
//! of list.
|
||||
@@ -425,24 +513,21 @@ class list
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
static const list &container_from_end_iterator(const_iterator end_iterator)
|
||||
{
|
||||
return *detail::parent_from_member<list, node>
|
||||
( detail::get_pointer(end_iterator.pointed_node()), &list::root_);
|
||||
}
|
||||
static const list_impl &container_from_end_iterator(const_iterator end_iterator)
|
||||
{ return priv_container_from_end_iterator(end_iterator); }
|
||||
|
||||
//! <b>Effects</b>: Returns the number of the elements contained in the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements contained in the list.
|
||||
//! if ConstantTimeSize is false. Constant time otherwise.
|
||||
//! if constant-time size option is disabled. Constant time otherwise.
|
||||
//!
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
size_type size() const
|
||||
{
|
||||
if(ConstantTimeSize)
|
||||
return size_traits::get_size();
|
||||
if(constant_time_size)
|
||||
return this->priv_size_traits().get_size();
|
||||
else
|
||||
return node_algorithms::count(this->get_root_node()) - 1;
|
||||
}
|
||||
@@ -464,13 +549,13 @@ class list
|
||||
//! <b>Complexity</b>: Constant.
|
||||
//!
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void swap(list& other)
|
||||
void swap(list_impl& other)
|
||||
{
|
||||
node_algorithms::swap_nodes(this->get_root_node(), other.get_root_node());
|
||||
if(ConstantTimeSize){
|
||||
size_type backup = size_traits::get_size();
|
||||
size_traits::set_size(other.get_size());
|
||||
other.set_size(backup);
|
||||
if(constant_time_size){
|
||||
size_type backup = this->priv_size_traits().get_size();
|
||||
this->priv_size_traits().set_size(other.priv_size_traits().get_size());
|
||||
other.priv_size_traits().set_size(backup);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +628,7 @@ class list
|
||||
++i;
|
||||
node_ptr to_erase = erase.pointed_node();
|
||||
node_algorithms::unlink(to_erase);
|
||||
size_traits::decrement();
|
||||
this->priv_size_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
return i;
|
||||
@@ -566,7 +651,7 @@ class list
|
||||
//! erased elements.
|
||||
iterator erase(iterator b, iterator e)
|
||||
{
|
||||
if(safemode_or_autounlink || ConstantTimeSize){
|
||||
if(safemode_or_autounlink || constant_time_size){
|
||||
while(b != e){
|
||||
b = this->erase(b);
|
||||
}
|
||||
@@ -599,10 +684,10 @@ class list
|
||||
++i;
|
||||
node_ptr to_erase = erase.pointed_node();
|
||||
node_algorithms::unlink(to_erase);
|
||||
size_traits::decrement();
|
||||
this->priv_size_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
disposer(ValueTraits::to_value_ptr(to_erase));
|
||||
disposer(get_real_value_traits().to_value_ptr(to_erase));
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -645,7 +730,7 @@ class list
|
||||
}
|
||||
else{
|
||||
node_algorithms::init(this->get_root_node());
|
||||
size_traits::set_size(size_type(0));
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,24 +763,20 @@ class list
|
||||
//!
|
||||
//! <b>Throws</b>: If cloner throws. Basic guarantee.
|
||||
template <class Cloner, class Disposer>
|
||||
void clone_from(const list &src, Cloner cloner, Disposer disposer)
|
||||
void clone_from(const list_impl &src, Cloner cloner, Disposer disposer)
|
||||
{
|
||||
this->clear_and_dispose(disposer);
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
BOOST_TRY{
|
||||
#endif
|
||||
BOOST_INTRUSIVE_TRY{
|
||||
const_iterator b(src.begin()), e(src.end());
|
||||
for(; b != e; ++b){
|
||||
this->push_back(*cloner(*b));
|
||||
}
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
clear_and_dispose(disposer);
|
||||
BOOST_RETHROW;
|
||||
BOOST_INTRUSIVE_CATCH(...){
|
||||
this->clear_and_dispose(disposer);
|
||||
BOOST_INTRUSIVE_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
#endif
|
||||
BOOST_INTRUSIVE_CATCH_END
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be an lvalue and p must be a valid iterator of *this.
|
||||
@@ -711,12 +792,12 @@ class list
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
iterator insert(iterator p, reference value)
|
||||
{
|
||||
node_ptr to_insert = ValueTraits::to_node_ptr(value);
|
||||
node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
node_algorithms::link_before(p.pointed_node(), to_insert);
|
||||
size_traits::increment();
|
||||
return iterator(to_insert);
|
||||
this->priv_size_traits().increment();
|
||||
return iterator(to_insert, this);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: Dereferencing iterator must yield
|
||||
@@ -793,13 +874,15 @@ class list
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
|
||||
//! this list. Iterators of this list and all the references are not invalidated.
|
||||
void splice(iterator p, list& x)
|
||||
void splice(iterator p, list_impl& x)
|
||||
{
|
||||
if(!x.empty()){
|
||||
size_traits &thist = this->priv_size_traits();
|
||||
size_traits &xt = x.priv_size_traits();
|
||||
node_algorithms::transfer
|
||||
(p.pointed_node(), x.begin().pointed_node(), x.end().pointed_node());
|
||||
size_traits::set_size(size_traits::get_size() + x.get_size());
|
||||
x.set_size(size_type(0));
|
||||
thist.set_size(thist.get_size() + xt.get_size());
|
||||
xt.set_size(size_type(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -816,11 +899,11 @@ class list
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice(iterator p, list&x, iterator new_ele)
|
||||
void splice(iterator p, list_impl&x, iterator new_ele)
|
||||
{
|
||||
node_algorithms::transfer(p.pointed_node(), new_ele.pointed_node());
|
||||
x.decrement();
|
||||
size_traits::increment();
|
||||
x.priv_size_traits().decrement();
|
||||
this->priv_size_traits().increment();
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: p must be a valid iterator of *this.
|
||||
@@ -832,18 +915,20 @@ class list
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements transferred
|
||||
//! if ConstantTimeSize is true. Constant-time otherwise.
|
||||
//! if constant-time size option is enabled. Constant-time otherwise.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice(iterator p, list&x, iterator start, iterator end)
|
||||
void splice(iterator p, list_impl&x, iterator start, iterator end)
|
||||
{
|
||||
if(start != end){
|
||||
if(ConstantTimeSize){
|
||||
if(constant_time_size){
|
||||
size_traits &thist = this->priv_size_traits();
|
||||
size_traits &xt = x.priv_size_traits();
|
||||
size_type increment = std::distance(start, end);
|
||||
node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node());
|
||||
size_traits::set_size(size_traits::get_size() + increment);
|
||||
x.set_size(x.get_size() - increment);
|
||||
thist.set_size(thist.get_size() + increment);
|
||||
xt.set_size(xt.get_size() - increment);
|
||||
}
|
||||
else{
|
||||
node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node());
|
||||
@@ -864,14 +949,16 @@ class list
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice(iterator p, list&x, iterator start, iterator end, difference_type n)
|
||||
void splice(iterator p, list_impl&x, iterator start, iterator end, difference_type n)
|
||||
{
|
||||
if(n){
|
||||
if(ConstantTimeSize){
|
||||
if(constant_time_size){
|
||||
size_traits &thist = this->priv_size_traits();
|
||||
size_traits &xt = x.priv_size_traits();
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(n == std::distance(start, end));
|
||||
node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node());
|
||||
size_traits::set_size(size_traits::get_size() + n);
|
||||
x.set_size(x.get_size() - n);
|
||||
thist.set_size(thist.get_size() + n);
|
||||
xt.set_size(xt.get_size() - n);
|
||||
}
|
||||
else{
|
||||
node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node());
|
||||
@@ -882,7 +969,7 @@ class list
|
||||
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
|
||||
//! The sort is stable, that is, the relative order of equivalent elements is preserved.
|
||||
//!
|
||||
//! <b>Throws</b>: If value_traits::node_traits::node
|
||||
//! <b>Throws</b>: If real_value_traits::node_traits::node
|
||||
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
|
||||
//! or std::less<value_type> throws. Basic guarantee.
|
||||
//!
|
||||
@@ -898,12 +985,12 @@ class list
|
||||
//! <b>Effects</b>: This function sorts the list *this according to p. The sort is
|
||||
//! stable, that is, the relative order of equivalent elements is preserved.
|
||||
//!
|
||||
//! <b>Throws</b>: If value_traits::node_traits::node
|
||||
//! <b>Throws</b>: If real_value_traits::node_traits::node
|
||||
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
|
||||
//! or the predicate throws. Basic guarantee.
|
||||
//!
|
||||
//! <b>Notes</b>: This won't throw if list_base_hook<>::value_traits or
|
||||
//! list_member_hook::::value_traits are used as value traits.
|
||||
//! <b>Notes</b>: This won't throw if list_base_hook<> or
|
||||
//! list_member_hook are used.
|
||||
//! Iterators and references are not invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
|
||||
@@ -913,8 +1000,8 @@ class list
|
||||
{
|
||||
if(node_traits::get_next(this->get_root_node())
|
||||
!= node_traits::get_previous(this->get_root_node())){
|
||||
list carry;
|
||||
list counter[64];
|
||||
list_impl carry;
|
||||
list_impl counter[64];
|
||||
int fill = 0;
|
||||
while(!this->empty()){
|
||||
carry.splice(carry.begin(), *this, this->begin());
|
||||
@@ -943,7 +1030,7 @@ class list
|
||||
//! size() + x.size() - 1 comparisons.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated
|
||||
void merge(list& x)
|
||||
void merge(list_impl& x)
|
||||
{ merge(x, std::less<value_type>()); }
|
||||
|
||||
//! <b>Requires</b>: p must be a comparison function that induces a strict weak
|
||||
@@ -961,7 +1048,7 @@ class list
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
template<class Predicate>
|
||||
void merge(list& x, Predicate p)
|
||||
void merge(list_impl& x, Predicate p)
|
||||
{
|
||||
iterator e = this->end();
|
||||
iterator bx = x.begin();
|
||||
@@ -1142,10 +1229,13 @@ class list
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
static iterator iterator_to(reference value)
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(ValueTraits::to_node_ptr(value)));
|
||||
return iterator(ValueTraits::to_node_ptr(value));
|
||||
//! This static function is available only if the <i>value traits</i>
|
||||
//! is stateless.
|
||||
static iterator s_iterator_to(reference value)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!stateful_value_traits));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(value)));
|
||||
return iterator(real_value_traits::to_node_ptr(value), 0);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be a const reference to a value inserted in a list.
|
||||
@@ -1157,20 +1247,91 @@ class list
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
static const_iterator iterator_to(const_reference value)
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(ValueTraits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator(ValueTraits::to_node_ptr(const_cast<reference> (value)));
|
||||
//! This static function is available only if the <i>value traits</i>
|
||||
//! is stateless.
|
||||
static const_iterator s_iterator_to(const_reference value)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!stateful_value_traits));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator(real_value_traits::to_node_ptr(const_cast<reference> (value)), 0);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be a reference to a value inserted in a list.
|
||||
//!
|
||||
//! <b>Effects</b>: This function returns a const_iterator pointing to the element
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
iterator iterator_to(reference value)
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(value)));
|
||||
return iterator(real_value_traits::to_node_ptr(value), this);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be a const reference to a value inserted in a list.
|
||||
//!
|
||||
//! <b>Effects</b>: This function returns an iterator pointing to the element.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
const_iterator iterator_to(const_reference value) const
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator(real_value_traits::to_node_ptr(const_cast<reference> (value)), this);
|
||||
}
|
||||
|
||||
/// @cond
|
||||
|
||||
private:
|
||||
static list_impl &priv_container_from_end_iterator(const const_iterator &end_iterator)
|
||||
{
|
||||
root_plus_size *r = detail::parent_from_member<root_plus_size, node>
|
||||
( detail::get_pointer(end_iterator.pointed_node()), &root_plus_size::root_);
|
||||
data_t *d = detail::parent_from_member<data_t, root_plus_size>
|
||||
( r, &data_t::root_plus_size_);
|
||||
list_impl *s = detail::parent_from_member<list_impl, data_t>(d, &list_impl::data_);
|
||||
return *s;
|
||||
}
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator==(const list<V, C, S>& x, const list<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator<
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
|
||||
#else
|
||||
(const list_impl<Config> &x, const list_impl<Config> &y)
|
||||
#endif
|
||||
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
bool operator==
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
|
||||
#else
|
||||
(const list_impl<Config> &x, const list_impl<Config> &y)
|
||||
#endif
|
||||
{
|
||||
typedef list_impl<Config> list_type;
|
||||
typedef typename list_type::const_iterator const_iterator;
|
||||
const bool C = list_type::constant_time_size;
|
||||
if(C && x.size() != y.size()){
|
||||
return false;
|
||||
}
|
||||
typedef typename list<V, C, S>::const_iterator const_iterator;
|
||||
const_iterator end1 = x.end();
|
||||
|
||||
const_iterator i1 = x.begin();
|
||||
@@ -1192,31 +1353,132 @@ inline bool operator==(const list<V, C, S>& x, const list<V, C, S>& y)
|
||||
}
|
||||
}
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator<(const list<V, C, S>& x,
|
||||
const list<V, C, S>& y)
|
||||
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator!=(const list<V, C, S>& x, const list<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator!=
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
|
||||
#else
|
||||
(const list_impl<Config> &x, const list_impl<Config> &y)
|
||||
#endif
|
||||
{ return !(x == y); }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator>(const list<V, C, S>& x, const list<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator>
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
|
||||
#else
|
||||
(const list_impl<Config> &x, const list_impl<Config> &y)
|
||||
#endif
|
||||
{ return y < x; }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator<=(const list<V, C, S>& x, const list<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator<=
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
|
||||
#else
|
||||
(const list_impl<Config> &x, const list_impl<Config> &y)
|
||||
#endif
|
||||
{ return !(y < x); }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator>=(const list<V, C, S>& x, const list<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator>=
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
|
||||
#else
|
||||
(const list_impl<Config> &x, const list_impl<Config> &y)
|
||||
#endif
|
||||
{ return !(x < y); }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline void swap(list<V, C, S>& x, list<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline void swap
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(list_impl<T, Options...> &x, list_impl<T, Options...> &y)
|
||||
#else
|
||||
(list_impl<Config> &x, list_impl<Config> &y)
|
||||
#endif
|
||||
{ x.swap(y); }
|
||||
|
||||
//! Helper metafunction to define a \c list that yields to the same type when the
|
||||
//! same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class T, class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_list
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< list_defaults<T>, O1, O2, O3>::type packed_options;
|
||||
typedef typename detail::get_value_traits
|
||||
<T, typename packed_options::value_traits>::type value_traits;
|
||||
|
||||
typedef list_impl
|
||||
<
|
||||
listopt
|
||||
< value_traits
|
||||
, typename packed_options::size_type
|
||||
, packed_options::constant_time_size
|
||||
>
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class O1, class O2, class O3>
|
||||
class list
|
||||
: public make_list<T, O1, O2, O3>::type
|
||||
{
|
||||
typedef typename make_list
|
||||
<T, O1, O2, O3>::type Base;
|
||||
typedef typename Base::real_value_traits real_value_traits;
|
||||
//Assert if passed value traits are compatible with the type
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
||||
public:
|
||||
typedef typename Base::value_traits value_traits;
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
|
||||
list(const value_traits &v_traits = value_traits())
|
||||
: Base(v_traits)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
list(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
|
||||
: Base(b, e, v_traits)
|
||||
{}
|
||||
|
||||
static list &container_from_end_iterator(iterator end_iterator)
|
||||
{ return static_cast<list &>(Base::container_from_end_iterator(end_iterator)); }
|
||||
|
||||
static const list &container_from_end_iterator(const_iterator end_iterator)
|
||||
{ return static_cast<const list &>(Base::container_from_end_iterator(end_iterator)); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
|
@@ -17,293 +17,104 @@
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/list_node.hpp>
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/tag.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/intrusive/detail/generic_hook.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! Derive a class from list_base_hook in order to store objects in
|
||||
//! in an list. list_base_hook holds the data necessary to maintain the
|
||||
//! list and provides an appropriate value_traits class for list.
|
||||
//!
|
||||
//! The first integer template argument defines a tag to identify the node.
|
||||
//! The same tag value can be used in different classes, but if a class is
|
||||
//! derived from more than one list_base_hook, then each list_base_hook needs its
|
||||
//! unique tag.
|
||||
//!
|
||||
//! The second boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the list configured from this hook.
|
||||
template< class Tag //= tag
|
||||
, linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class list_base_hook
|
||||
: private detail::list_node_traits<VoidPointer>::node
|
||||
/// @cond
|
||||
template<class VoidPointer>
|
||||
struct get_list_node_algo
|
||||
{
|
||||
public:
|
||||
typedef detail::list_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
typedef circular_list_algorithms<list_node_traits<VoidPointer> > type;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
//! Helper metafunction to define a \c \c list_base_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_list_base_hook
|
||||
{
|
||||
/// @cond
|
||||
private:
|
||||
typedef circular_list_algorithms<node_traits> node_algorithms;
|
||||
typedef typename pack_options
|
||||
< hook_defaults, O1, O2, O3>::type packed_options;
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef list_base_hook
|
||||
<Tag, Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
typedef detail::generic_hook
|
||||
< get_list_node_algo<typename packed_options::void_pointer>
|
||||
, typename packed_options::tag
|
||||
, packed_options::link_mode
|
||||
, detail::ListBaseHook
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
list_base_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using list_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
list_base_hook(const list_base_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using list_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
list_base_hook& operator=(const list_base_hook& )
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~list_base_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(list_base_hook &other)
|
||||
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether list::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for list.
|
||||
//! The template argument T defines the class type stored in list. Objects
|
||||
//! of type T and of types derived from T can be stored. T doesn't need to be
|
||||
//! copy-constructible or assignable.
|
||||
template<class T>
|
||||
struct value_traits
|
||||
: detail::derivation_hook_value_traits<T, this_type, Tag>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
return this_type_ptr(static_cast<list_base_hook*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
return const_this_type_ptr(static_cast<const list_base_hook*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Put a public data member list_member_hook in order to store objects of this class in
|
||||
//! an list. list_member_hook holds the data necessary for maintaining the list and
|
||||
//! provides an appropriate value_traits class for list.
|
||||
//! Derive a class from this hook in order to store objects of that class
|
||||
//! in an list.
|
||||
//!
|
||||
//! The first boolean template parameter will specify the linking mode of the hook.
|
||||
//! The hook admits the following options: \c tag<>, \c void_pointer<> and
|
||||
//! \c link_mode<>.
|
||||
//!
|
||||
//! The second argument is the pointer type that will be used internally in the hook
|
||||
//! and the list configured from this hook.
|
||||
template< linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class list_member_hook
|
||||
: private detail::list_node_traits<VoidPointer>::node
|
||||
//! \c tag<> defines a tag to identify the node.
|
||||
//! The same tag value can be used in different classes, but if a class is
|
||||
//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its
|
||||
//! unique tag.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class list_base_hook
|
||||
: public make_list_base_hook<O1, O2, O3>::type
|
||||
{
|
||||
public:
|
||||
typedef detail::list_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef circular_list_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef list_member_hook
|
||||
<Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type >::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type >::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
list_member_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
list_base_hook();
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using list_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
list_member_hook(const list_member_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
list_base_hook(const list_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using list_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
list_member_hook& operator=(const list_member_hook& )
|
||||
{ return *this; }
|
||||
list_base_hook& operator=(const list_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~list_member_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
~list_base_hook();
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
@@ -316,73 +127,133 @@ class list_member_hook
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(list_member_hook& other)
|
||||
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(list_base_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether list::iterator_to
|
||||
//! otherwise. This function can be used to test whether \c list::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
//! The value_traits class is used as the first template argument for list.
|
||||
//! The template argument is a pointer to member pointing to the node in
|
||||
//! the class. Objects of type T and of types derived from T can be stored.
|
||||
//! T doesn't need to be copy-constructible or assignable.
|
||||
template<class T, this_type T::* M>
|
||||
struct value_traits
|
||||
: detail::member_hook_value_traits<T, this_type, M>
|
||||
{};
|
||||
//! Helper metafunction to define a \c \c list_member_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_list_member_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< hook_defaults, O1, O2, O3>::type packed_options;
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
typedef detail::generic_hook
|
||||
< get_list_node_algo<typename packed_options::void_pointer>
|
||||
, member_tag
|
||||
, packed_options::link_mode
|
||||
, detail::NoBaseHook
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Store this hook in a class to be inserted
|
||||
//! in an list.
|
||||
//!
|
||||
//! The hook admits the following options: \c void_pointer<> and
|
||||
//! \c link_mode<>.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class list_member_hook
|
||||
: public make_list_member_hook<O1, O2, O3>::type
|
||||
{
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
return this_type_ptr(static_cast<this_type*> (detail::get_pointer(p)));
|
||||
}
|
||||
list_member_hook();
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
return const_this_type_ptr(static_cast<const this_type*> (detail::get_pointer(p)));
|
||||
}
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
list_member_hook(const list_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
list_member_hook& operator=(const list_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
~list_member_hook();
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(list_member_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether \c list::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#ifndef BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP
|
||||
#define BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP
|
||||
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/intrusive/detail/parent_from_member.hpp>
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace intrusive {
|
||||
//!store a node_traits::node
|
||||
template< class T, class NodeTraits
|
||||
, typename NodeTraits::node T::* PtrToMember
|
||||
, linking_policy Policy>
|
||||
, link_mode_type LinkMode = safe_link>
|
||||
struct member_value_traits
|
||||
{
|
||||
public:
|
||||
@@ -38,8 +38,7 @@ struct member_value_traits
|
||||
typedef typename boost::pointer_to_other<node_ptr, const T>::type const_pointer;
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
|
||||
enum { linking_policy = Policy };
|
||||
static const link_mode_type link_mode = LinkMode;
|
||||
|
||||
static node_ptr to_node_ptr(reference value)
|
||||
{ return node_ptr(&(value.*PtrToMember)); }
|
||||
|
429
include/boost/intrusive/options.hpp
Normal file
429
include/boost/intrusive/options.hpp
Normal file
@@ -0,0 +1,429 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007
|
||||
//
|
||||
// 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/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_OPTIONS_HPP
|
||||
#define BOOST_INTRUSIVE_OPTIONS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
/// @cond
|
||||
|
||||
struct default_tag;
|
||||
struct member_tag;
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class ValueTraits>
|
||||
struct eval_value_traits
|
||||
{
|
||||
typedef typename ValueTraits::value_traits type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct external_bucket_traits_is_true
|
||||
{
|
||||
static const bool value = external_bucket_traits_bool<T>::value == 3;
|
||||
};
|
||||
|
||||
template <class BucketTraits>
|
||||
struct eval_bucket_traits
|
||||
{
|
||||
typedef typename BucketTraits::bucket_traits type;
|
||||
};
|
||||
|
||||
template<class T, class BaseHook>
|
||||
struct get_base_value_traits
|
||||
{
|
||||
typedef detail::base_hook_traits
|
||||
< T
|
||||
, typename BaseHook::boost_intrusive_tags::node_traits
|
||||
, BaseHook::boost_intrusive_tags::link_mode
|
||||
, typename BaseHook::boost_intrusive_tags::tag
|
||||
, BaseHook::boost_intrusive_tags::hook_type> type;
|
||||
};
|
||||
|
||||
template<class T, class MemberHook>
|
||||
struct get_member_value_traits
|
||||
{
|
||||
typedef typename MemberHook::member_value_traits type;
|
||||
};
|
||||
|
||||
template<class T, class SupposedValueTraits>
|
||||
struct get_value_traits
|
||||
{
|
||||
typedef SupposedValueTraits supposed_value_traits;
|
||||
//...if it's a base hook
|
||||
typedef typename detail::eval_if_c
|
||||
< internal_base_hook_bool_is_true<supposed_value_traits>::value
|
||||
//...get it's internal value traits using
|
||||
//the provided T value type.
|
||||
, get_base_value_traits<T, supposed_value_traits>
|
||||
//...else use it's internal value traits tag
|
||||
//(member hooks and custom value traits are in this group)
|
||||
, detail::eval_if_c
|
||||
< internal_member_value_traits<supposed_value_traits>::value
|
||||
, get_member_value_traits<T, supposed_value_traits>
|
||||
, detail::identity<supposed_value_traits>
|
||||
>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<class BaseHook>
|
||||
struct get_base_node_traits
|
||||
{
|
||||
typedef typename BaseHook::boost_intrusive_tags::node_traits type;
|
||||
};
|
||||
|
||||
template<class MemberHook>
|
||||
struct get_member_node_traits
|
||||
{
|
||||
typedef typename MemberHook::member_value_traits::node_traits type;
|
||||
};
|
||||
|
||||
template<class ValueTraits>
|
||||
struct get_explicit_node_traits
|
||||
{
|
||||
typedef typename ValueTraits::node_traits type;
|
||||
};
|
||||
|
||||
|
||||
template<class SupposedValueTraits>
|
||||
struct get_node_traits
|
||||
{
|
||||
typedef SupposedValueTraits supposed_value_traits;
|
||||
//...if it's a base hook
|
||||
typedef typename detail::eval_if_c
|
||||
< internal_base_hook_bool_is_true<supposed_value_traits>::value
|
||||
//...get it's internal value traits using
|
||||
//the provided T value type.
|
||||
, get_base_node_traits<supposed_value_traits>
|
||||
//...else use it's internal value traits tag
|
||||
//(member hooks and custom value traits are in this group)
|
||||
, detail::eval_if_c
|
||||
< internal_member_value_traits<supposed_value_traits>::value
|
||||
, get_member_node_traits<supposed_value_traits>
|
||||
, get_explicit_node_traits<supposed_value_traits>
|
||||
>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
|
||||
} //namespace detail{
|
||||
|
||||
|
||||
//!This type indicates that no option is being used
|
||||
//!and that the default options should be used
|
||||
struct none
|
||||
{
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{ };
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!This option setter specifies if the intrusive
|
||||
//!container stores its size as a member to
|
||||
//!obtain constant-time size() member.
|
||||
template<bool Enabled>
|
||||
struct constant_time_size
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool constant_time_size = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the type that
|
||||
//!the container will use to store its size.
|
||||
template<class SizeType>
|
||||
struct size_type
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef SizeType size_type;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the strict weak ordering
|
||||
//!comparison functor for the value type
|
||||
template<class Compare>
|
||||
struct compare
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef Compare compare;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the equality
|
||||
//!functor for the value type
|
||||
template<class Equal>
|
||||
struct equal
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef Equal equal;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the hash
|
||||
//!functor for the value type
|
||||
template<class Hash>
|
||||
struct hash
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef Hash hash;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the relationship between the type
|
||||
//!to be managed by the container (the value type) and the node to be
|
||||
//!used in the node algorithms. It also specifies the linking policy.
|
||||
template<typename ValueTraits>
|
||||
struct value_traits
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef ValueTraits value_traits;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the member hook the
|
||||
//!container must use.
|
||||
template< typename Parent
|
||||
, typename MemberHook
|
||||
, MemberHook Parent::* PtrToMember>
|
||||
struct member_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef char Parent::* GenericPtrToMember;
|
||||
typedef detail::member_hook_traits
|
||||
< Parent
|
||||
, MemberHook
|
||||
, PtrToMember
|
||||
> member_value_traits;
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef member_value_traits value_traits;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies that the container
|
||||
//!must use the specified base hook
|
||||
template<typename BaseHook>
|
||||
struct base_hook
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef BaseHook value_traits;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the type of
|
||||
//!a void pointer. This will instruct the hook
|
||||
//!to use this type of pointer instead of the
|
||||
//!default one
|
||||
template<class VoidPointer>
|
||||
struct void_pointer
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef VoidPointer void_pointer;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the type of
|
||||
//!the tag of a base hook. A type can not have two
|
||||
//!base hooks of the same type, so a tag can be used
|
||||
//!to differentiate two base hooks with otherwise same type
|
||||
template<class BaseTag>
|
||||
struct tag
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef BaseTag tag;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the type of
|
||||
//!a void pointer. This will instruct the hook
|
||||
//!to use this type of pointer instead of the
|
||||
//!default one
|
||||
template<link_mode_type LinkType>
|
||||
struct link_mode
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const link_mode_type link_mode = LinkType;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the bucket traits
|
||||
//!class for unordered associative containers. When this option is specified,
|
||||
//!instead of using the default bucket traits, a user defined holder will be defined
|
||||
template<class BucketTraits>
|
||||
struct bucket_traits
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef BucketTraits bucket_traits;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies if the bucket array will be always power of two.
|
||||
//!This allows using masks instead of the default modulo operation to determine
|
||||
//!the bucket number from the hash value, leading to better performance.
|
||||
//!In debug mode, if power of two buckets mode is activated, the bucket length
|
||||
//!will be checked to through assertions to assure the bucket length is power of two.
|
||||
template<bool Enabled>
|
||||
struct power_2_buckets
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool power_2_buckets = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
template<class Prev, class Next>
|
||||
struct do_pack
|
||||
{
|
||||
//Use "pack" member template to pack options
|
||||
typedef typename Next::template pack<Prev> type;
|
||||
};
|
||||
|
||||
template<class Prev>
|
||||
struct do_pack<Prev, none>
|
||||
{
|
||||
//Avoid packing "none" to shorten template names
|
||||
typedef Prev type;
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
< class DefaultOptions
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
, class O4 = none
|
||||
, class O5 = none
|
||||
, class O6 = none
|
||||
, class O7 = none
|
||||
, class O8 = none
|
||||
, class O9 = none
|
||||
, class Option10 = none
|
||||
>
|
||||
struct pack_options
|
||||
{
|
||||
// join options
|
||||
typedef
|
||||
typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< DefaultOptions
|
||||
, O1
|
||||
>::type
|
||||
, O2
|
||||
>::type
|
||||
, O3
|
||||
>::type
|
||||
, O4
|
||||
>::type
|
||||
, O5
|
||||
>::type
|
||||
, O6
|
||||
>::type
|
||||
, O7
|
||||
>::type
|
||||
, O8
|
||||
>::type
|
||||
, O9
|
||||
>::type
|
||||
, Option10
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
struct hook_defaults
|
||||
: public pack_options
|
||||
< none
|
||||
, void_pointer<void*>
|
||||
, link_mode<safe_link>
|
||||
, tag<default_tag>
|
||||
>::type
|
||||
{};
|
||||
|
||||
/// @endcond
|
||||
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_OPTIONS_HPP
|
@@ -23,7 +23,7 @@ namespace intrusive {
|
||||
template<class VoidPointer, std::size_t Alignment>
|
||||
struct has_pointer_plus_bit
|
||||
{
|
||||
enum { value = false };
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
//!This is an specialization for raw pointers.
|
||||
@@ -32,7 +32,7 @@ struct has_pointer_plus_bit
|
||||
template<std::size_t N>
|
||||
struct has_pointer_plus_bit<void*, N>
|
||||
{
|
||||
enum { value = N % 2u == 0 };
|
||||
static const bool value = (N % 2u == 0);
|
||||
};
|
||||
|
||||
//!This is class that is supposed to have static methods
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,15 @@
|
||||
// in supporting documentation. Hewlett-Packard Company makes no
|
||||
// representations about the suitability of this software for any
|
||||
// purpose. It is provided "as is" without express or implied warranty.
|
||||
//
|
||||
// The tree destruction algorithm is based on Julienne Walker and The EC Team code:
|
||||
//
|
||||
// This code is in the public domain. Anyone may use it or change it in any way that
|
||||
// they see fit. The author assumes no responsibility for damages incurred through
|
||||
// use of the original code or any variations thereof.
|
||||
//
|
||||
// It is requested, but not required, that due credit is given to the original author
|
||||
// and anyone who has modified the code through a header comment, such as this one.
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
|
||||
#define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
|
||||
@@ -43,9 +52,7 @@
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <cstddef>
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#endif
|
||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
|
||||
|
||||
@@ -67,7 +74,7 @@ namespace intrusive {
|
||||
//! relinked into its place, rather than copied, so that the only
|
||||
//! pointers invalidated are those referring to the deleted node.
|
||||
//!
|
||||
//! rbtree_algorithms is configured with a NodeTraits class, which capsulates the
|
||||
//! rbtree_algorithms is configured with a NodeTraits class, which encapsulates the
|
||||
//! information about the node to be manipulated. NodeTraits must support the
|
||||
//! following interface:
|
||||
//!
|
||||
@@ -111,6 +118,7 @@ class rbtree_algorithms
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef NodeTraits node_traits;
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
||||
typedef typename NodeTraits::color color;
|
||||
@@ -121,6 +129,27 @@ class rbtree_algorithms
|
||||
{
|
||||
return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr)));
|
||||
}
|
||||
|
||||
static void swap_left(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
node_ptr temp(NodeTraits::get_left(this_node));
|
||||
NodeTraits::set_left(this_node, NodeTraits::get_left(other_node));
|
||||
NodeTraits::set_left(other_node, temp);
|
||||
}
|
||||
|
||||
static void swap_right(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
node_ptr temp(NodeTraits::get_right(this_node));
|
||||
NodeTraits::set_right(this_node, NodeTraits::get_right(other_node));
|
||||
NodeTraits::set_right(other_node, temp);
|
||||
}
|
||||
|
||||
static void swap_parent(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
node_ptr temp(NodeTraits::get_parent(this_node));
|
||||
NodeTraits::set_parent(this_node, NodeTraits::get_parent(other_node));
|
||||
NodeTraits::set_parent(other_node, temp);
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
@@ -146,7 +175,14 @@ class rbtree_algorithms
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void swap_tree(node_ptr header1, node_ptr header2)
|
||||
{
|
||||
{/*
|
||||
if(NodeTraits::get_parent(header1)){
|
||||
NodeTraits::node n1;
|
||||
node_ptr n2(NodeTraits::get_parent(header1));
|
||||
init(&n1);
|
||||
swap_nodes(&n1, n2);
|
||||
swap_nodes(&n1, n2);
|
||||
}*/
|
||||
if(header1 == header2)
|
||||
return;
|
||||
|
||||
@@ -185,6 +221,276 @@ class rbtree_algorithms
|
||||
}
|
||||
}
|
||||
|
||||
static node_ptr get_header(const_node_ptr node)
|
||||
{
|
||||
node_ptr h = uncast(node);
|
||||
if(NodeTraits::get_parent(node)){
|
||||
h = NodeTraits::get_parent(node);
|
||||
while(!is_header(h))
|
||||
h = NodeTraits::get_parent(h);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node1 and node2 can't be header nodes
|
||||
//! of two trees.
|
||||
//!
|
||||
//! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
|
||||
//! in the position node2 before the function. node2 will be inserted in the
|
||||
//! position node1 had before the function.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Note</b>: This function will break container ordering invariants if
|
||||
//! node1 and node2 are not equivalent according to the ordering rules.
|
||||
//!
|
||||
//!Experimental function
|
||||
static void swap_nodes(node_ptr node1, node_ptr node2)
|
||||
{
|
||||
if(node1 == node2)
|
||||
return;
|
||||
|
||||
node_ptr header1(get_header(node1)), header2(get_header(node2));
|
||||
swap_nodes(node1, header1, node2, header2);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node1 and node2 can't be header nodes
|
||||
//! of two trees with header header1 and header2.
|
||||
//!
|
||||
//! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
|
||||
//! in the position node2 before the function. node2 will be inserted in the
|
||||
//! position node1 had before the function.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Note</b>: This function will break container ordering invariants if
|
||||
//! node1 and node2 are not equivalent according to the ordering rules.
|
||||
//!
|
||||
//!Experimental function
|
||||
static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2)
|
||||
{
|
||||
if(node1 == node2)
|
||||
return;
|
||||
|
||||
//node1 and node2 must not be header nodes
|
||||
//BOOST_INTRUSIVE_INVARIANT_ASSERT((header1 != node1 && header2 != node2));
|
||||
if(header1 != header2){
|
||||
//Update header1 if necessary
|
||||
if(node1 == NodeTraits::get_left(header1)){
|
||||
NodeTraits::set_left(header1, node2);
|
||||
}
|
||||
|
||||
if(node1 == NodeTraits::get_right(header1)){
|
||||
NodeTraits::set_right(header1, node2);
|
||||
}
|
||||
|
||||
if(node1 == NodeTraits::get_parent(header1)){
|
||||
NodeTraits::set_parent(header1, node2);
|
||||
}
|
||||
|
||||
//Update header2 if necessary
|
||||
if(node2 == NodeTraits::get_left(header2)){
|
||||
NodeTraits::set_left(header2, node1);
|
||||
}
|
||||
|
||||
if(node2 == NodeTraits::get_right(header2)){
|
||||
NodeTraits::set_right(header2, node1);
|
||||
}
|
||||
|
||||
if(node2 == NodeTraits::get_parent(header2)){
|
||||
NodeTraits::set_parent(header2, node1);
|
||||
}
|
||||
}
|
||||
else{
|
||||
//If both nodes are from the same tree
|
||||
//Update header if necessary
|
||||
if(node1 == NodeTraits::get_left(header1)){
|
||||
NodeTraits::set_left(header1, node2);
|
||||
}
|
||||
else if(node2 == NodeTraits::get_left(header2)){
|
||||
NodeTraits::set_left(header2, node1);
|
||||
}
|
||||
|
||||
if(node1 == NodeTraits::get_right(header1)){
|
||||
NodeTraits::set_right(header1, node2);
|
||||
}
|
||||
else if(node2 == NodeTraits::get_right(header2)){
|
||||
NodeTraits::set_right(header2, node1);
|
||||
}
|
||||
|
||||
if(node1 == NodeTraits::get_parent(header1)){
|
||||
NodeTraits::set_parent(header1, node2);
|
||||
}
|
||||
else if(node2 == NodeTraits::get_parent(header2)){
|
||||
NodeTraits::set_parent(header2, node1);
|
||||
}
|
||||
|
||||
//Adjust data in nodes to be swapped
|
||||
//so that final link swap works as expected
|
||||
if(node1 == NodeTraits::get_parent(node2)){
|
||||
NodeTraits::set_parent(node2, node2);
|
||||
|
||||
if(node2 == NodeTraits::get_right(node1)){
|
||||
NodeTraits::set_right(node1, node1);
|
||||
}
|
||||
else{
|
||||
NodeTraits::set_left(node1, node1);
|
||||
}
|
||||
}
|
||||
else if(node2 == NodeTraits::get_parent(node1)){
|
||||
NodeTraits::set_parent(node1, node1);
|
||||
|
||||
if(node1 == NodeTraits::get_right(node2)){
|
||||
NodeTraits::set_right(node2, node2);
|
||||
}
|
||||
else{
|
||||
NodeTraits::set_left(node2, node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Now swap all the links
|
||||
node_ptr temp;
|
||||
//swap left link
|
||||
temp = NodeTraits::get_left(node1);
|
||||
NodeTraits::set_left(node1, NodeTraits::get_left(node2));
|
||||
NodeTraits::set_left(node2, temp);
|
||||
//swap right link
|
||||
temp = NodeTraits::get_right(node1);
|
||||
NodeTraits::set_right(node1, NodeTraits::get_right(node2));
|
||||
NodeTraits::set_right(node2, temp);
|
||||
//swap parent link
|
||||
temp = NodeTraits::get_parent(node1);
|
||||
NodeTraits::set_parent(node1, NodeTraits::get_parent(node2));
|
||||
NodeTraits::set_parent(node2, temp);
|
||||
//Swap color
|
||||
color c = NodeTraits::get_color(node1);
|
||||
NodeTraits::set_color(node1, NodeTraits::get_color(node2));
|
||||
NodeTraits::set_color(node2, c);
|
||||
|
||||
//Now adjust adjacent nodes for newly inserted node 1
|
||||
if((temp = NodeTraits::get_left(node1))){
|
||||
NodeTraits::set_parent(temp, node1);
|
||||
}
|
||||
if((temp = NodeTraits::get_right(node1))){
|
||||
NodeTraits::set_parent(temp, node1);
|
||||
}
|
||||
if((temp = NodeTraits::get_parent(node1)) &&
|
||||
//The header has been already updated so avoid it
|
||||
temp != header2){
|
||||
if(NodeTraits::get_left(temp) == node2){
|
||||
NodeTraits::set_left(temp, node1);
|
||||
}
|
||||
if(NodeTraits::get_right(temp) == node2){
|
||||
NodeTraits::set_right(temp, node1);
|
||||
}
|
||||
}
|
||||
//Now adjust adjacent nodes for newly inserted node 2
|
||||
if((temp = NodeTraits::get_left(node2))){
|
||||
NodeTraits::set_parent(temp, node2);
|
||||
}
|
||||
if((temp = NodeTraits::get_right(node2))){
|
||||
NodeTraits::set_parent(temp, node2);
|
||||
}
|
||||
if((temp = NodeTraits::get_parent(node2)) &&
|
||||
//The header has been already updated so avoid it
|
||||
temp != header1){
|
||||
if(NodeTraits::get_left(temp) == node1){
|
||||
NodeTraits::set_left(temp, node2);
|
||||
}
|
||||
if(NodeTraits::get_right(temp) == node1){
|
||||
NodeTraits::set_right(temp, node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
|
||||
//! and new_node must not be inserted in a tree.
|
||||
//!
|
||||
//! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
|
||||
//! tree with new_node. The tree does not need to be rebalanced
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Note</b>: This function will break container ordering invariants if
|
||||
//! new_node is not equivalent to node_to_be_replaced according to the
|
||||
//! ordering rules. This function is faster than erasing and inserting
|
||||
//! the node, since no rebalancing and comparison is needed.
|
||||
//!
|
||||
//!Experimental function
|
||||
static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node)
|
||||
{
|
||||
if(node_to_be_replaced == new_node)
|
||||
return;
|
||||
replace_node(node_to_be_replaced, get_header(node_to_be_replaced), new_node);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
|
||||
//! with header "header" and new_node must not be inserted in a tree.
|
||||
//!
|
||||
//! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
|
||||
//! tree with new_node. The tree does not need to be rebalanced
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Note</b>: This function will break container ordering invariants if
|
||||
//! new_node is not equivalent to node_to_be_replaced according to the
|
||||
//! ordering rules. This function is faster than erasing and inserting
|
||||
//! the node, since no rebalancing or comparison is needed.
|
||||
//!
|
||||
//!Experimental function
|
||||
static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node)
|
||||
{
|
||||
if(node_to_be_replaced == new_node)
|
||||
return;
|
||||
|
||||
//Update header if necessary
|
||||
if(node_to_be_replaced == NodeTraits::get_left(header)){
|
||||
NodeTraits::set_left(header, new_node);
|
||||
}
|
||||
|
||||
if(node_to_be_replaced == NodeTraits::get_right(header)){
|
||||
NodeTraits::set_right(header, new_node);
|
||||
}
|
||||
|
||||
if(node_to_be_replaced == NodeTraits::get_parent(header)){
|
||||
NodeTraits::set_parent(header, new_node);
|
||||
}
|
||||
|
||||
//Now set data from the original node
|
||||
node_ptr temp;
|
||||
NodeTraits::set_left(new_node, NodeTraits::get_left(node_to_be_replaced));
|
||||
NodeTraits::set_right(new_node, NodeTraits::get_right(node_to_be_replaced));
|
||||
NodeTraits::set_parent(new_node, NodeTraits::get_parent(node_to_be_replaced));
|
||||
NodeTraits::set_color(new_node, NodeTraits::get_color(node_to_be_replaced));
|
||||
|
||||
//Now adjust adjacent nodes for newly inserted node
|
||||
if((temp = NodeTraits::get_left(new_node))){
|
||||
NodeTraits::set_parent(temp, new_node);
|
||||
}
|
||||
if((temp = NodeTraits::get_right(new_node))){
|
||||
NodeTraits::set_parent(temp, new_node);
|
||||
}
|
||||
if((temp = NodeTraits::get_parent(new_node)) &&
|
||||
//The header has been already updated so avoid it
|
||||
temp != header){
|
||||
if(NodeTraits::get_left(temp) == node_to_be_replaced){
|
||||
NodeTraits::set_left(temp, new_node);
|
||||
}
|
||||
if(NodeTraits::get_right(temp) == node_to_be_replaced){
|
||||
NodeTraits::set_right(temp, new_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node is a tree node but not the header.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the node and rebalances the tree.
|
||||
@@ -202,6 +508,10 @@ class rbtree_algorithms
|
||||
}
|
||||
}
|
||||
|
||||
static void unlink(node_ptr node)
|
||||
{ unlink_and_rebalance(node); }
|
||||
|
||||
|
||||
//! <b>Requires</b>: header is the header of a tree.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the leftmost node from the tree, and
|
||||
@@ -508,25 +818,42 @@ class rbtree_algorithms
|
||||
//!
|
||||
//! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
|
||||
template <class Cloner, class Disposer>
|
||||
static void clone_tree
|
||||
static void clone
|
||||
(const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer)
|
||||
{
|
||||
if(!unique(target_header)){
|
||||
node_ptr p;
|
||||
while((p = unlink_leftmost_without_rebalance(target_header))){
|
||||
disposer(p);
|
||||
}
|
||||
clear_and_dispose(target_header, disposer);
|
||||
}
|
||||
|
||||
node_ptr source_root = NodeTraits::get_parent(source_header);
|
||||
node_ptr leftmost, rightmost;
|
||||
node_ptr new_root = clone_subtree
|
||||
(source_header, target_header, cloner, disposer, leftmost, rightmost);
|
||||
|
||||
//Now update header node
|
||||
NodeTraits::set_parent(target_header, new_root);
|
||||
NodeTraits::set_left (target_header, leftmost);
|
||||
NodeTraits::set_right (target_header, rightmost);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: "disposer" must be an object function
|
||||
//! taking a node_ptr parameter and shouldn't throw.
|
||||
//!
|
||||
//! <b>Effects</b>: Empties the target tree calling
|
||||
//! <tt>void disposer::operator()(node_ptr)</tt> for every node of the tree
|
||||
//! except the header.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
|
||||
//! number of elements of tree target tree when calling this function.
|
||||
//!
|
||||
//! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
|
||||
template<class Disposer>
|
||||
static void clear_and_dispose(node_ptr header, Disposer disposer)
|
||||
{
|
||||
node_ptr source_root = NodeTraits::get_parent(header);
|
||||
if(!source_root)
|
||||
return;
|
||||
|
||||
NodeTraits::set_parent
|
||||
( target_header
|
||||
, deep_clone_node(source_root, target_header, cloner, disposer));
|
||||
NodeTraits::set_left(target_header, minimum(NodeTraits::get_parent(target_header)));
|
||||
NodeTraits::set_right(target_header, maximum(NodeTraits::get_parent(target_header)));
|
||||
dispose_subtree(source_root, disposer);
|
||||
init_header(header);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: "header" must be the header node of a tree.
|
||||
@@ -694,6 +1021,17 @@ class rbtree_algorithms
|
||||
bool link_left = (y == h) ||
|
||||
comp(new_node, y);
|
||||
link_and_balance(new_node, y, link_left, h);
|
||||
/*
|
||||
//erase me
|
||||
NodeTraits::node n;
|
||||
init(&n);
|
||||
if(y!=h)
|
||||
x = x;
|
||||
node_ptr n1(y!=h ? y : &n);
|
||||
node_ptr n2(new_node);
|
||||
swap_nodes(n2, n1);
|
||||
swap_nodes(n2, n1);
|
||||
*/
|
||||
return new_node;
|
||||
}
|
||||
|
||||
@@ -725,6 +1063,17 @@ class rbtree_algorithms
|
||||
bool link_left = (y == h) ||
|
||||
!comp(y, new_node);
|
||||
link_and_balance(new_node, y, link_left, h);
|
||||
/*
|
||||
//erase me
|
||||
NodeTraits::node n;
|
||||
init(&n);
|
||||
if(y!=h)
|
||||
x = x;
|
||||
node_ptr n1(y!=h ? y : &n);
|
||||
node_ptr n2(new_node);
|
||||
swap_nodes(n2, n1);
|
||||
swap_nodes(n2, n1);
|
||||
*/
|
||||
return new_node;
|
||||
}
|
||||
|
||||
@@ -752,6 +1101,14 @@ class rbtree_algorithms
|
||||
!comp(new_node, (prev = prev_node(hint)))){
|
||||
bool link_left = unique(header) || !NodeTraits::get_left(hint);
|
||||
link_and_balance(new_node, link_left ? hint : prev, link_left, header);
|
||||
/*
|
||||
//erase me
|
||||
NodeTraits::node n1;
|
||||
node_ptr n2(new_node);
|
||||
init(&n1);
|
||||
swap_nodes(n2, &n1);
|
||||
swap_nodes(&n1, n2);
|
||||
*/
|
||||
return new_node;
|
||||
}
|
||||
else{
|
||||
@@ -922,6 +1279,109 @@ class rbtree_algorithms
|
||||
|
||||
/// @cond
|
||||
|
||||
template <class Cloner, class Disposer>
|
||||
static node_ptr clone_subtree
|
||||
( const_node_ptr source_parent, node_ptr target_parent
|
||||
, Cloner cloner, Disposer disposer
|
||||
, node_ptr &leftmost_out, node_ptr &rightmost_out
|
||||
)
|
||||
{
|
||||
node_ptr target_sub_root = target_parent;
|
||||
node_ptr source_root = NodeTraits::get_parent(source_parent);
|
||||
if(!source_root){
|
||||
leftmost_out = rightmost_out = source_root;
|
||||
}
|
||||
else{
|
||||
//We'll calculate leftmost and rightmost nodes while iterating
|
||||
node_ptr current = source_root;
|
||||
node_ptr insertion_point = target_sub_root = cloner(current);
|
||||
|
||||
//We'll calculate leftmost and rightmost nodes while iterating
|
||||
node_ptr leftmost = target_sub_root;
|
||||
node_ptr rightmost = target_sub_root;
|
||||
|
||||
//First set the subroot
|
||||
NodeTraits::set_left(target_sub_root, 0);
|
||||
NodeTraits::set_right(target_sub_root, 0);
|
||||
NodeTraits::set_parent(target_sub_root, target_parent);
|
||||
NodeTraits::set_color(target_sub_root, NodeTraits::get_color(current));
|
||||
|
||||
try {
|
||||
while(true) {
|
||||
//First clone left nodes
|
||||
if( NodeTraits::get_left(current) &&
|
||||
!NodeTraits::get_left(insertion_point)) {
|
||||
current = NodeTraits::get_left(current);
|
||||
node_ptr temp = insertion_point;
|
||||
//Clone and mark as leaf
|
||||
insertion_point = cloner(current);
|
||||
NodeTraits::set_left (insertion_point, 0);
|
||||
NodeTraits::set_right (insertion_point, 0);
|
||||
NodeTraits::set_color (insertion_point, NodeTraits::get_color(current));
|
||||
//Insert left
|
||||
NodeTraits::set_parent(insertion_point, temp);
|
||||
NodeTraits::set_left (temp, insertion_point);
|
||||
//Update leftmost
|
||||
if(rightmost == target_sub_root)
|
||||
leftmost = insertion_point;
|
||||
}
|
||||
//Then clone right nodes
|
||||
else if( NodeTraits::get_right(current) &&
|
||||
!NodeTraits::get_right(insertion_point)){
|
||||
current = NodeTraits::get_right(current);
|
||||
node_ptr temp = insertion_point;
|
||||
//Clone and mark as leaf
|
||||
insertion_point = cloner(current);
|
||||
NodeTraits::set_left (insertion_point, 0);
|
||||
NodeTraits::set_right (insertion_point, 0);
|
||||
NodeTraits::set_color (insertion_point, NodeTraits::get_color(current));
|
||||
//Insert right
|
||||
NodeTraits::set_parent(insertion_point, temp);
|
||||
NodeTraits::set_right (temp, insertion_point);
|
||||
//Update rightmost
|
||||
rightmost = insertion_point;
|
||||
}
|
||||
//If not, go up
|
||||
else if(current == source_root){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
//Branch completed, go up searching more nodes to clone
|
||||
current = NodeTraits::get_parent(current);
|
||||
insertion_point = NodeTraits::get_parent(insertion_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
dispose_subtree(target_sub_root, disposer);
|
||||
throw;
|
||||
}
|
||||
leftmost_out = leftmost;
|
||||
rightmost_out = rightmost;
|
||||
}
|
||||
return target_sub_root;
|
||||
}
|
||||
|
||||
template<class Disposer>
|
||||
static void dispose_subtree(node_ptr x, Disposer disposer)
|
||||
{
|
||||
node_ptr save;
|
||||
while (x){
|
||||
save = NodeTraits::get_left(x);
|
||||
if (save) {
|
||||
// Right rotation
|
||||
NodeTraits::set_left(x, NodeTraits::get_right(save));
|
||||
NodeTraits::set_right(save, x);
|
||||
}
|
||||
else {
|
||||
save = NodeTraits::get_right(x);
|
||||
init(x);
|
||||
disposer(x);
|
||||
}
|
||||
x = save;
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: z is the node to be inserted, par is its parent,
|
||||
//! left, indicates if z should be a left node of par and header is the header
|
||||
//! of the tree.
|
||||
@@ -1106,59 +1566,6 @@ class rbtree_algorithms
|
||||
}
|
||||
NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black());
|
||||
}
|
||||
|
||||
template <class Cloner, class Disposer>
|
||||
static node_ptr deep_clone_node
|
||||
(node_ptr source_root, node_ptr new_parent, Cloner cloner, Disposer disposer)
|
||||
{
|
||||
// structural copy. source_root and new_parent must be non-null.
|
||||
node_ptr top = cloner(source_root);
|
||||
NodeTraits::set_parent(top, new_parent);
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
BOOST_TRY {
|
||||
#endif
|
||||
if(NodeTraits::get_right(source_root)){
|
||||
NodeTraits::set_right
|
||||
(top, deep_clone_node(NodeTraits::get_right(source_root), top
|
||||
,cloner, disposer));
|
||||
}
|
||||
new_parent = top;
|
||||
source_root = NodeTraits::get_left(source_root);
|
||||
|
||||
while(source_root){
|
||||
node_ptr y = cloner(source_root);
|
||||
NodeTraits::set_left(new_parent, y);
|
||||
NodeTraits::set_parent(y, new_parent);
|
||||
|
||||
if(NodeTraits::get_right(source_root)){
|
||||
NodeTraits::set_right(y, deep_clone_node(NodeTraits::get_right(source_root), y
|
||||
,cloner, disposer));
|
||||
}
|
||||
new_parent = y;
|
||||
source_root = NodeTraits::get_left(source_root);
|
||||
}
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
deep_dispose_node(top, disposer);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
#endif
|
||||
return top;
|
||||
}
|
||||
|
||||
template<class Disposer>
|
||||
static void deep_dispose_node(node_ptr x, Disposer disposer)
|
||||
{
|
||||
// erase without rebalancing
|
||||
while(x){
|
||||
deep_dispose_node(NodeTraits::get_right(x), disposer);
|
||||
node_ptr y = NodeTraits::get_left(x);
|
||||
disposer(x);
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -17,16 +17,45 @@
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/rbtree_node.hpp>
|
||||
#include <boost/intrusive/rbtree_algorithms.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/tag.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/intrusive/detail/generic_hook.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
/// @cond
|
||||
template<class VoidPointer>
|
||||
struct get_set_node_algo
|
||||
{
|
||||
typedef rbtree_algorithms<rbtree_node_traits<VoidPointer> > type;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
//! Helper metafunction to define a \c set_base_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_set_base_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< hook_defaults, O1, O2, O3>::type packed_options;
|
||||
|
||||
typedef detail::generic_hook
|
||||
< get_set_node_algo<typename packed_options::void_pointer>
|
||||
, typename packed_options::tag
|
||||
, packed_options::link_mode
|
||||
, detail::SetBaseHook
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Derive a class from set_base_hook in order to store objects in
|
||||
//! in an set/multiset. set_base_hook holds the data necessary to maintain
|
||||
//! the set/multiset and provides an appropriate value_traits class for set/multiset.
|
||||
@@ -40,160 +69,102 @@ namespace intrusive {
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the set/multiset configured from this hook.
|
||||
template< class Tag //= tag
|
||||
, linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class set_base_hook
|
||||
: private detail::rbtree_node_traits<VoidPointer>::node
|
||||
: public make_set_base_hook<O1, O2, O3>::type
|
||||
{
|
||||
public:
|
||||
typedef detail::rbtree_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef rbtree_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef set_base_hook
|
||||
<Tag, Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
set_base_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
//! <b>Throws</b>: Nothing.
|
||||
set_base_hook();
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using set_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
set_base_hook(const set_base_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
set_base_hook(const set_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using set_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
set_base_hook& operator=(const set_base_hook& )
|
||||
{ return *this; }
|
||||
set_base_hook& operator=(const set_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in an set an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~set_base_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
~set_base_hook();
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(set_base_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether set::iterator_to
|
||||
//! otherwise. This function can be used to test whether \c set::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink_and_rebalance(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
//! The value_traits class is used as the first template argument for multiset.
|
||||
//! The template argument T defines the class type stored in multiset. Objects
|
||||
//! of type T and of types derived from T can be stored. T don't need to be
|
||||
//! copy-constructible or assignable.
|
||||
template<class T>
|
||||
struct value_traits
|
||||
: detail::derivation_hook_value_traits<T, this_type, Tag>
|
||||
{};
|
||||
//! Helper metafunction to define a \c set_member_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_set_member_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< hook_defaults, O1, O2, O3>::type packed_options;
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
return this_type_ptr(static_cast<set_base_hook*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
return const_this_type_ptr(static_cast<const set_base_hook*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
typedef detail::generic_hook
|
||||
< get_set_node_algo<typename packed_options::void_pointer>
|
||||
, member_tag
|
||||
, packed_options::link_mode
|
||||
, detail::NoBaseHook
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Put a public data member set_member_hook in order to store objects of this class in
|
||||
@@ -204,152 +175,79 @@ class set_base_hook
|
||||
//!
|
||||
//! The second argument is the pointer type that will be used internally in the hook
|
||||
//! and the set/multiset configured from this hook.
|
||||
template< linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class set_member_hook
|
||||
: private detail::rbtree_node_traits<VoidPointer>::node
|
||||
: public make_set_member_hook<O1, O2, O3>::type
|
||||
{
|
||||
public:
|
||||
typedef detail::rbtree_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef rbtree_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef set_member_hook
|
||||
<Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type >::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type >::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
set_member_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
set_member_hook();
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using set_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work.
|
||||
set_member_hook(const set_member_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
set_member_hook(const set_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using set_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work.
|
||||
set_member_hook& operator=(const set_member_hook& )
|
||||
{ return *this; }
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
set_member_hook& operator=(const set_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in an set an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~set_member_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
~set_member_hook();
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(set_member_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether \c set::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink_and_rebalance(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for multiset.
|
||||
//! The template argument is a pointer to member pointing to the node in
|
||||
//! the class. Objects of type T and of types derived from T can be stored.
|
||||
//! T don't need to be copy-constructible or assignable.
|
||||
template<class T, this_type T::* P>
|
||||
struct value_traits
|
||||
: detail::member_hook_value_traits<T, this_type, P>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
return this_type_ptr(static_cast<this_type*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
return const_this_type_ptr(static_cast<const this_type*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
|
@@ -16,21 +16,60 @@
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#endif
|
||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/slist_hook.hpp>
|
||||
#include <boost/intrusive/circular_slist_algorithms.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <functional>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
/// @cond
|
||||
|
||||
template <class T>
|
||||
struct internal_default_slist_hook
|
||||
{
|
||||
template <class U> static detail::one test(...);
|
||||
template <class U> static detail::two test(typename U::default_slist_hook* = 0);
|
||||
static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct get_default_slist_hook
|
||||
{ typedef typename T::default_slist_hook type; };
|
||||
|
||||
template <class ValueTraits, class SizeType, bool ConstantTimeSize>
|
||||
struct slistopt
|
||||
{
|
||||
typedef ValueTraits value_traits;
|
||||
typedef SizeType size_type;
|
||||
static const bool constant_time_size = ConstantTimeSize;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct slist_defaults
|
||||
: pack_options
|
||||
< none
|
||||
, base_hook
|
||||
< typename detail::eval_if_c
|
||||
< internal_default_slist_hook<T>::value
|
||||
, get_default_slist_hook<T>
|
||||
, detail::identity<none>
|
||||
>::type
|
||||
>
|
||||
, constant_time_size<true>
|
||||
, size_type<std::size_t>
|
||||
>::type
|
||||
{};
|
||||
|
||||
/// @endcond
|
||||
|
||||
//! The class template slist is an intrusive container, that encapsulates
|
||||
//! a singly-linked list. You can use such a list to squeeze the last bit
|
||||
//! of performance from your application. Unfortunately, the little gains
|
||||
@@ -39,12 +78,13 @@ namespace intrusive {
|
||||
//! this limitation some other member functions with rather unusual semantics
|
||||
//! have to be introduced.
|
||||
//!
|
||||
//! The template parameter ValueTraits is called "value traits". It stores
|
||||
//! information and operations about the type to be stored in the container.
|
||||
//! The template parameter \c T is the type to be managed by the container.
|
||||
//! The user can specify additional options and if no options are provided
|
||||
//! default options are used.
|
||||
//!
|
||||
//! If the user specifies ConstantTimeSize as "true", a member of type SizeType
|
||||
//! will be embedded in the class, that will keep track of the number of stored objects.
|
||||
//! This will allow constant-time O(1) size() member, instead of default O(N) size.
|
||||
//! The container supports the following options:
|
||||
//! \c base_hook<>/member_hook<>/value_traits<>,
|
||||
//! \c constant_time_size<> and \c size_type<>.
|
||||
//!
|
||||
//! The iterators of slist are forward iterators. slist provides a static
|
||||
//! function called "previous" to compute the previous iterator of a given iterator.
|
||||
@@ -53,82 +93,120 @@ namespace intrusive {
|
||||
//! are defined. In addition, whenever you have an end iterator, 'after this
|
||||
//! iterator' means 'at the beginning of the list'. To improve the self-documentation
|
||||
//! a "before_begin()" function is defined, returning the end() iterator.
|
||||
template < class ValueTraits
|
||||
, bool ConstantTimeSize //= true
|
||||
, class SizeType //= std::size_t
|
||||
>
|
||||
class slist
|
||||
: private detail::size_holder<ConstantTimeSize, SizeType>
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
class slist_impl
|
||||
{
|
||||
/// @cond
|
||||
private:
|
||||
typename ValueTraits::node_traits::node root_;
|
||||
|
||||
typedef slist<ValueTraits, ConstantTimeSize, SizeType> this_type;
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef detail::size_holder<ConstantTimeSize, SizeType> size_traits;
|
||||
|
||||
//! This class is
|
||||
//! non-copyable
|
||||
slist (const slist&);
|
||||
|
||||
//! This class is
|
||||
//! non-asignable
|
||||
slist &operator =(const slist&);
|
||||
/// @endcond
|
||||
|
||||
//Public typedefs
|
||||
public:
|
||||
typedef ValueTraits value_traits;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ValueTraits::pointer pointer;
|
||||
typedef typename ValueTraits::const_pointer const_pointer;
|
||||
typedef typename Config::value_traits value_traits;
|
||||
/// @cond
|
||||
static const bool external_value_traits =
|
||||
detail::external_value_traits_is_true<value_traits>::value;
|
||||
typedef typename detail::eval_if_c
|
||||
< external_value_traits
|
||||
, detail::eval_value_traits<value_traits>
|
||||
, detail::identity<value_traits>
|
||||
>::type real_value_traits;
|
||||
/// @endcond
|
||||
typedef typename real_value_traits::pointer pointer;
|
||||
typedef typename real_value_traits::const_pointer const_pointer;
|
||||
typedef typename std::iterator_traits<pointer>::value_type value_type;
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
typedef typename std::iterator_traits<pointer>::difference_type difference_type;
|
||||
typedef SizeType size_type;
|
||||
typedef detail::slist_iterator<value_type, ValueTraits> iterator;
|
||||
typedef detail::slist_iterator<const value_type, ValueTraits> const_iterator;
|
||||
typedef typename Config::size_type size_type;
|
||||
typedef slist_iterator<slist_impl, false> iterator;
|
||||
typedef slist_iterator<slist_impl, true> const_iterator;
|
||||
typedef typename real_value_traits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, const node>::type const_node_ptr;
|
||||
typedef circular_slist_algorithms<node_traits> node_algorithms;
|
||||
|
||||
static const bool constant_time_size = Config::constant_time_size;
|
||||
static const bool stateful_value_traits = detail::store_cont_ptr_on_it<slist_impl>::value;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, const node>::type const_node_ptr;
|
||||
typedef circular_slist_algorithms<node_traits> node_algorithms;
|
||||
typedef detail::size_holder<constant_time_size, size_type> size_traits;
|
||||
|
||||
//! This class is
|
||||
//! non-copyable
|
||||
slist_impl (const slist_impl&);
|
||||
|
||||
//! This class is
|
||||
//! non-asignable
|
||||
slist_impl &operator =(const slist_impl&);
|
||||
|
||||
enum { safemode_or_autounlink =
|
||||
(int)ValueTraits::linking_policy == (int)auto_unlink ||
|
||||
(int)ValueTraits::linking_policy == (int)safe_link };
|
||||
(int)real_value_traits::link_mode == (int)auto_unlink ||
|
||||
(int)real_value_traits::link_mode == (int)safe_link };
|
||||
|
||||
//Constant-time size is incompatible with auto-unlink hooks!
|
||||
BOOST_STATIC_ASSERT(!(ConstantTimeSize && ((int)ValueTraits::linking_policy == (int)auto_unlink)));
|
||||
BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink)));
|
||||
|
||||
node_ptr get_root_node()
|
||||
{ return node_ptr(&root_); }
|
||||
{ return node_ptr(&data_.root_plus_size_.root_); }
|
||||
|
||||
const_node_ptr get_root_node() const
|
||||
{ return const_node_ptr(&root_); }
|
||||
{ return const_node_ptr(&data_.root_plus_size_.root_); }
|
||||
|
||||
static node_ptr uncast(const_node_ptr ptr)
|
||||
{
|
||||
return node_ptr(const_cast<node*>(detail::get_pointer(ptr)));
|
||||
}
|
||||
|
||||
static iterator previous_node(iterator beg, iterator i)
|
||||
struct root_plus_size
|
||||
: public size_traits
|
||||
{
|
||||
return iterator
|
||||
(node_algorithms::get_previous_node(beg.pointed_node(), i.pointed_node()));
|
||||
}
|
||||
node root_;
|
||||
};
|
||||
|
||||
static const_iterator previous_node(const_iterator beg, const_iterator i)
|
||||
struct data_t
|
||||
: public slist_impl::value_traits
|
||||
{
|
||||
return const_iterator
|
||||
(node_algorithms::get_previous_node(beg.pointed_node(), i.pointed_node()));
|
||||
}
|
||||
typedef typename slist_impl::value_traits value_traits;
|
||||
data_t(const value_traits &val_traits)
|
||||
: value_traits(val_traits)
|
||||
{}
|
||||
|
||||
root_plus_size root_plus_size_;
|
||||
} data_;
|
||||
|
||||
size_traits &priv_size_traits()
|
||||
{ return data_.root_plus_size_; }
|
||||
|
||||
const size_traits &priv_size_traits() const
|
||||
{ return data_.root_plus_size_; }
|
||||
|
||||
const real_value_traits &get_real_value_traits(detail::bool_<false>) const
|
||||
{ return data_; }
|
||||
|
||||
const real_value_traits &get_real_value_traits(detail::bool_<true>) const
|
||||
{ return data_.get_value_traits(*this); }
|
||||
|
||||
real_value_traits &get_real_value_traits(detail::bool_<false>)
|
||||
{ return data_; }
|
||||
|
||||
real_value_traits &get_real_value_traits(detail::bool_<true>)
|
||||
{ return data_.get_value_traits(*this); }
|
||||
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
const real_value_traits &get_real_value_traits() const
|
||||
{ return this->get_real_value_traits(detail::bool_<external_value_traits>()); }
|
||||
|
||||
real_value_traits &get_real_value_traits()
|
||||
{ return this->get_real_value_traits(detail::bool_<external_value_traits>()); }
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: constructs an empty list.
|
||||
//!
|
||||
@@ -136,9 +214,10 @@ class slist
|
||||
//!
|
||||
//! <b>Throws</b>: If value_traits::node_traits::node
|
||||
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
|
||||
slist()
|
||||
slist_impl(const value_traits &v_traits = value_traits())
|
||||
: data_(v_traits)
|
||||
{
|
||||
size_traits::set_size(size_type(0));
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
node_algorithms::init(this->get_root_node());
|
||||
}
|
||||
|
||||
@@ -151,9 +230,10 @@ class slist
|
||||
//! <b>Throws</b>: If value_traits::node_traits::node
|
||||
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
|
||||
template<class Iterator>
|
||||
slist(Iterator b, Iterator e)
|
||||
slist_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
|
||||
: data_(v_traits)
|
||||
{
|
||||
size_traits::set_size(size_type(0));
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
node_algorithms::init(this->get_root_node());
|
||||
insert_after(before_begin(), b, e);
|
||||
}
|
||||
@@ -162,12 +242,12 @@ class slist
|
||||
//! or auto-unlink value, the destructor does nothing
|
||||
//! (ie. no code is generated). Otherwise it detaches all elements from this.
|
||||
//! In this case the objects in the list are not deleted (i.e. no destructors
|
||||
//! are called), but the hooks according to the ValueTraits template parameter
|
||||
//! are called), but the hooks according to the value_traits template parameter
|
||||
//! are set to their default value.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the list, if
|
||||
//! it's a safe-mode or auto-unlink value. Otherwise constant.
|
||||
~slist()
|
||||
~slist_impl()
|
||||
{ this->clear(); }
|
||||
|
||||
//! <b>Effects</b>: Erases all the elements of the container.
|
||||
@@ -185,7 +265,7 @@ class slist
|
||||
}
|
||||
else{
|
||||
node_algorithms::init(this->get_root_node());
|
||||
size_traits::set_size(size_type(0));
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,11 +295,11 @@ class slist
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void push_front(reference value)
|
||||
{
|
||||
node_ptr to_insert = ValueTraits::to_node_ptr(value);
|
||||
node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
node_algorithms::link_after(this->get_root_node(), to_insert);
|
||||
size_traits::increment();
|
||||
this->priv_size_traits().increment();
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Erases the first element of the list.
|
||||
@@ -234,7 +314,7 @@ class slist
|
||||
{
|
||||
node_ptr to_erase = node_traits::get_next(this->get_root_node());
|
||||
node_algorithms::unlink_after(this->get_root_node());
|
||||
size_traits::decrement();
|
||||
this->priv_size_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
}
|
||||
@@ -254,7 +334,7 @@ class slist
|
||||
{
|
||||
node_ptr to_erase = node_traits::get_next(this->get_root_node());
|
||||
this->pop_front();
|
||||
disposer(ValueTraits::to_value_ptr(to_erase));
|
||||
disposer(get_real_value_traits().to_value_ptr(to_erase));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a reference to the first element of the list.
|
||||
@@ -263,7 +343,7 @@ class slist
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
reference front()
|
||||
{ return *ValueTraits::to_value_ptr(node_traits::get_next(this->get_root_node())); }
|
||||
{ return *get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_reference to the first element of the list.
|
||||
//!
|
||||
@@ -271,7 +351,7 @@ class slist
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_reference front() const
|
||||
{ return *ValueTraits::to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); }
|
||||
{ return *get_real_value_traits().to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); }
|
||||
|
||||
//! <b>Effects</b>: Returns an iterator to the first element contained in the list.
|
||||
//!
|
||||
@@ -279,7 +359,7 @@ class slist
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
iterator begin()
|
||||
{ return iterator (node_traits::get_next(this->get_root_node())); }
|
||||
{ return iterator (node_traits::get_next(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
|
||||
//!
|
||||
@@ -287,7 +367,7 @@ class slist
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator begin() const
|
||||
{ return const_iterator (node_traits::get_next(this->get_root_node())); }
|
||||
{ return const_iterator (node_traits::get_next(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
|
||||
//!
|
||||
@@ -295,7 +375,7 @@ class slist
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator cbegin() const
|
||||
{ return const_iterator (node_traits::get_next(this->get_root_node())); }
|
||||
{ return const_iterator (node_traits::get_next(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns an iterator to the end of the list.
|
||||
//!
|
||||
@@ -303,7 +383,7 @@ class slist
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
iterator end()
|
||||
{ return iterator (this->get_root_node()); }
|
||||
{ return iterator (this->get_root_node(), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
|
||||
//!
|
||||
@@ -311,7 +391,7 @@ class slist
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator end() const
|
||||
{ return const_iterator (uncast(this->get_root_node())); }
|
||||
{ return const_iterator (uncast(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
|
||||
//!
|
||||
@@ -319,7 +399,7 @@ class slist
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator cend() const
|
||||
{ return const_iterator (uncast(this->get_root_node())); }
|
||||
{ return const_iterator (uncast(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns an iterator that points to a position
|
||||
//! before the first element. Equivalent to "end()"
|
||||
@@ -356,11 +436,8 @@ class slist
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
static slist &container_from_end_iterator(iterator end_iterator)
|
||||
{
|
||||
return *detail::parent_from_member<slist, node>
|
||||
( detail::get_pointer(end_iterator.pointed_node()), &slist::root_);
|
||||
}
|
||||
static slist_impl &container_from_end_iterator(iterator end_iterator)
|
||||
{ return priv_container_from_end_iterator(end_iterator); }
|
||||
|
||||
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator
|
||||
//! of slist.
|
||||
@@ -370,24 +447,21 @@ class slist
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
static const slist &container_from_end_iterator(const_iterator end_iterator)
|
||||
{
|
||||
return *detail::parent_from_member<slist, node>
|
||||
( detail::get_pointer(end_iterator.pointed_node()), &slist::root_);
|
||||
}
|
||||
static const slist_impl &container_from_end_iterator(const_iterator end_iterator)
|
||||
{ return priv_container_from_end_iterator(end_iterator); }
|
||||
|
||||
//! <b>Effects</b>: Returns the number of the elements contained in the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements contained in the list.
|
||||
//! if ConstantTimeSize is false. Constant time otherwise.
|
||||
//! if constant_time_size is false. Constant time otherwise.
|
||||
//!
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
size_type size() const
|
||||
{
|
||||
if(ConstantTimeSize)
|
||||
return size_traits::get_size();
|
||||
if(constant_time_size)
|
||||
return this->priv_size_traits().get_size();
|
||||
else
|
||||
return node_algorithms::count(this->get_root_node()) - 1;
|
||||
}
|
||||
@@ -409,13 +483,13 @@ class slist
|
||||
//! <b>Complexity</b>: Linear to the number of elements of both lists.
|
||||
//!
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void swap(slist& other)
|
||||
void swap(slist_impl& other)
|
||||
{
|
||||
node_algorithms::swap_nodes(this->get_root_node(), other.get_root_node());
|
||||
if(ConstantTimeSize){
|
||||
size_type backup = size_traits::get_size();
|
||||
size_traits::set_size(other.get_size());
|
||||
other.set_size(backup);
|
||||
if(constant_time_size){
|
||||
size_type backup = this->priv_size_traits().get_size();
|
||||
this->priv_size_traits().set_size(other.priv_size_traits().get_size());
|
||||
other.priv_size_traits().set_size(backup);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,25 +607,21 @@ class slist
|
||||
//!
|
||||
//! <b>Throws</b>: If cloner throws.
|
||||
template <class Cloner, class Disposer>
|
||||
void clone_from(const slist &src, Cloner cloner, Disposer disposer)
|
||||
void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer)
|
||||
{
|
||||
this->clear_and_dispose(disposer);
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
BOOST_TRY{
|
||||
#endif
|
||||
BOOST_INTRUSIVE_TRY{
|
||||
iterator prev = this->before_begin();
|
||||
const_iterator b(src.begin()), e(src.end());
|
||||
for(; b != e; ++b, ++prev){
|
||||
this->insert_after(prev, *cloner(*b));
|
||||
}
|
||||
#ifndef BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
BOOST_INTRUSIVE_CATCH(...){
|
||||
this->clear_and_dispose(disposer);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
#endif
|
||||
BOOST_INTRUSIVE_CATCH_END
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be an lvalue and prev_p must point to an element
|
||||
@@ -569,12 +639,12 @@ class slist
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
iterator insert_after(iterator prev_p, reference value)
|
||||
{
|
||||
node_ptr n = ValueTraits::to_node_ptr(value);
|
||||
node_ptr n = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
|
||||
node_algorithms::link_after(prev_p.pointed_node(), n);
|
||||
size_traits::increment();
|
||||
return iterator (n);
|
||||
this->priv_size_traits().increment();
|
||||
return iterator (n, this);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: Dereferencing iterator must yield
|
||||
@@ -644,7 +714,7 @@ class slist
|
||||
iterator it(prev); ++it;
|
||||
node_ptr to_erase(it.pointed_node());
|
||||
node_algorithms::unlink_after(prev.pointed_node());
|
||||
size_traits::decrement();
|
||||
this->priv_size_traits().decrement();
|
||||
iterator ret(++prev);
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
@@ -725,7 +795,7 @@ class slist
|
||||
iterator it(prev); ++it;
|
||||
node_ptr to_erase(it.pointed_node());
|
||||
iterator ret(this->erase_after(prev));
|
||||
disposer(ValueTraits::to_value_ptr(to_erase));
|
||||
disposer(get_real_value_traits().to_value_ptr(to_erase));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -853,7 +923,7 @@ class slist
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
iterator splice_after(iterator prev, slist &x)
|
||||
iterator splice_after(iterator prev, slist_impl &x)
|
||||
{
|
||||
if (!x.empty()){
|
||||
iterator last_x(x.previous(x.end()));
|
||||
@@ -861,8 +931,8 @@ class slist
|
||||
( prev.pointed_node()
|
||||
, x.end().pointed_node()
|
||||
, last_x.pointed_node());
|
||||
size_traits::set_size(size_traits::get_size() + x.get_size());
|
||||
x.set_size(size_type(0));
|
||||
this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size());
|
||||
x.priv_size_traits().set_size(size_type(0));
|
||||
return last_x;
|
||||
}
|
||||
else{
|
||||
@@ -883,15 +953,15 @@ class slist
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice_after(iterator prev, slist &x, iterator prev_ele)
|
||||
void splice_after(iterator prev, slist_impl &x, iterator prev_ele)
|
||||
{
|
||||
iterator nxt = prev_ele;
|
||||
++nxt;
|
||||
if (nxt != prev && prev_ele != prev){
|
||||
node_algorithms::transfer_after
|
||||
(prev.pointed_node(), prev_ele.pointed_node(), nxt.pointed_node());
|
||||
size_traits::increment();
|
||||
x.decrement();
|
||||
this->priv_size_traits().increment();
|
||||
x.priv_size_traits().decrement();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,19 +976,19 @@ class slist
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements transferred
|
||||
//! if ConstantTimeSize is true. Constant-time otherwise.
|
||||
//! if constant_time_size is true. Constant-time otherwise.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice_after(iterator prev_pos, slist &x, iterator before_first, iterator before_last)
|
||||
void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last)
|
||||
{
|
||||
if (before_first != before_last){
|
||||
if(ConstantTimeSize){
|
||||
if(constant_time_size){
|
||||
size_type increment = std::distance(before_first, before_last);
|
||||
node_algorithms::transfer_after
|
||||
(prev_pos.pointed_node(), before_first.pointed_node(), before_last.pointed_node());
|
||||
size_traits::set_size(size_traits::get_size() + increment);
|
||||
x.set_size(x.get_size() - increment);
|
||||
this->priv_size_traits().set_size(this->priv_size_traits().get_size() + increment);
|
||||
x.priv_size_traits().set_size(x.priv_size_traits().get_size() - increment);
|
||||
}
|
||||
else{
|
||||
node_algorithms::transfer_after
|
||||
@@ -941,15 +1011,15 @@ class slist
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice_after(iterator prev_pos, slist &x, iterator before_first, iterator before_last, difference_type n)
|
||||
void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last, difference_type n)
|
||||
{
|
||||
if(n){
|
||||
if(ConstantTimeSize){
|
||||
if(constant_time_size){
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_first, before_last) == n);
|
||||
node_algorithms::transfer_after
|
||||
(prev_pos.pointed_node(), before_first.pointed_node(), before_last.pointed_node());
|
||||
size_traits::set_size(size_traits::get_size() + n);
|
||||
x.set_size(x.get_size() - n);
|
||||
this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n);
|
||||
x.priv_size_traits().set_size(x.priv_size_traits().get_size() - n);
|
||||
}
|
||||
else{
|
||||
node_algorithms::transfer_after
|
||||
@@ -975,7 +1045,7 @@ class slist
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
iterator splice(iterator it, slist &x)
|
||||
iterator splice(iterator it, slist_impl &x)
|
||||
{ return splice_after(this->previous(it), x); }
|
||||
|
||||
//! <b>Requires</b>: it p must be a valid iterator of *this.
|
||||
@@ -991,7 +1061,7 @@ class slist
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice(iterator pos, slist &x, iterator elem)
|
||||
void splice(iterator pos, slist_impl &x, iterator elem)
|
||||
{ return splice_after(this->previous(pos), x, this->previous(elem)); }
|
||||
|
||||
//! <b>Requires</b>: pos must be a dereferenceable iterator in *this
|
||||
@@ -1004,11 +1074,11 @@ class slist
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the sum of elements before pos, first, and last.
|
||||
//! Plus linear to the number of elements transferred if ConstantTimeSize is true.
|
||||
//! Plus linear to the number of elements transferred if constant_time_size is true.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice(iterator pos, slist &x, iterator first, iterator last)
|
||||
void splice(iterator pos, slist_impl &x, iterator first, iterator last)
|
||||
{ return splice_after(this->previous(pos), x, this->previous(first), this->previous(last)); }
|
||||
|
||||
//! <b>Requires</b>: pos must be a dereferenceable iterator in *this
|
||||
@@ -1025,7 +1095,7 @@ class slist
|
||||
//!
|
||||
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
||||
//! list. Iterators of this list and all the references are not invalidated.
|
||||
void splice(iterator pos, slist &x, iterator first, iterator last, difference_type n)
|
||||
void splice(iterator pos, slist_impl &x, iterator first, iterator last, difference_type n)
|
||||
{ return splice_after(this->previous(pos), x, this->previous(first), this->previous(last), n); }
|
||||
|
||||
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
|
||||
@@ -1044,8 +1114,8 @@ class slist
|
||||
{
|
||||
if (node_traits::get_next(node_traits::get_next(this->get_root_node()))
|
||||
!= this->get_root_node()) {
|
||||
slist carry;
|
||||
slist counter[64];
|
||||
slist_impl carry;
|
||||
slist_impl counter[64];
|
||||
int fill = 0;
|
||||
iterator last_inserted;
|
||||
while(!this->empty()){
|
||||
@@ -1057,8 +1127,10 @@ class slist
|
||||
}
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(counter[i].empty());
|
||||
|
||||
iterator last_element(previous_node(last_inserted, carry.end()));
|
||||
if(ConstantTimeSize){
|
||||
node_ptr p = node_algorithms::get_previous_node
|
||||
(last_inserted.pointed_node(), carry.end().pointed_node());
|
||||
iterator last_element(p, this);
|
||||
if(constant_time_size){
|
||||
counter[i].splice_after( counter[i].end(), carry
|
||||
, carry.before_begin(), last_element
|
||||
, carry.size());
|
||||
@@ -1067,19 +1139,18 @@ class slist
|
||||
counter[i].splice_after( counter[i].end(), carry
|
||||
, carry.before_begin(), last_element);
|
||||
}
|
||||
//counter[i].splice_after(counter[i].end(), carry, carry.end(), previous_node(last_inserted, carry.end()));
|
||||
//carry.swap(counter[i]);
|
||||
if(i == fill)
|
||||
++fill;
|
||||
}
|
||||
|
||||
for (int i = 1; i < fill; ++i)
|
||||
last_inserted = counter[i].merge(counter[i-1], p);
|
||||
//this->swap(counter[fill-1]);
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(this->empty());
|
||||
|
||||
iterator last_element(previous_node(last_inserted, counter[--fill].end()));
|
||||
if(ConstantTimeSize){
|
||||
node_ptr p = node_algorithms::get_previous_node
|
||||
(last_inserted.pointed_node(), counter[--fill].end().pointed_node());
|
||||
iterator last_element(p, this);
|
||||
if(constant_time_size){
|
||||
this->splice_after( end(), counter[fill], counter[fill].before_begin()
|
||||
, last_element, counter[fill].size());
|
||||
}
|
||||
@@ -1126,7 +1197,7 @@ class slist
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
template<class Predicate>
|
||||
iterator merge(slist& x, Predicate p)
|
||||
iterator merge(slist_impl& x, Predicate p)
|
||||
{
|
||||
iterator a(before_begin()), e(end()), ax(x.before_begin());
|
||||
iterator last_inserted(e);
|
||||
@@ -1161,7 +1232,7 @@ class slist
|
||||
//! size() + x.size() - 1 comparisons.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated
|
||||
void merge(slist& x)
|
||||
void merge(slist_impl& x)
|
||||
{ this->merge(x, std::less<value_type>()); }
|
||||
|
||||
//! <b>Effects</b>: Reverses the order of elements in the list.
|
||||
@@ -1328,10 +1399,13 @@ class slist
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
static iterator iterator_to(reference value)
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(ValueTraits::to_node_ptr(value)));
|
||||
return iterator (ValueTraits::to_node_ptr(value));
|
||||
//! This static function is available only if the <i>value traits</i>
|
||||
//! is stateless.
|
||||
static iterator s_iterator_to(reference value)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!stateful_value_traits));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(value_traits::to_node_ptr(value)));
|
||||
return iterator (value_traits::to_node_ptr(value), 0);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be a const reference to a value inserted in a list.
|
||||
@@ -1343,10 +1417,43 @@ class slist
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
static const_iterator iterator_to(const_reference value)
|
||||
//! This static function is available only if the <i>value traits</i>
|
||||
//! is stateless.
|
||||
static const_iterator s_iterator_to(const_reference value)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!stateful_value_traits));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator (value_traits::to_node_ptr(const_cast<reference> (value)), 0);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be a reference to a value inserted in a list.
|
||||
//!
|
||||
//! <b>Effects</b>: This function returns a const_iterator pointing to the element
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
iterator iterator_to(reference value)
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(ValueTraits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator (ValueTraits::to_node_ptr(const_cast<reference> (value)));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(value_traits::to_node_ptr(value)));
|
||||
return iterator (value_traits::to_node_ptr(value), this);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be a const reference to a value inserted in a list.
|
||||
//!
|
||||
//! <b>Effects</b>: This function returns an iterator pointing to the element.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
const_iterator iterator_to(const_reference value) const
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator (value_traits::to_node_ptr(const_cast<reference> (value)), this);
|
||||
}
|
||||
|
||||
//! <b>Returns</b>: The iterator to the element before i in the list.
|
||||
@@ -1360,7 +1467,7 @@ class slist
|
||||
{
|
||||
return iterator
|
||||
(node_algorithms::get_previous_node
|
||||
(before_begin().pointed_node(), i.pointed_node()));
|
||||
(before_begin().pointed_node(), i.pointed_node()), 0);
|
||||
}
|
||||
|
||||
//! <b>Returns</b>: The const_iterator to the element before i in the list.
|
||||
@@ -1374,17 +1481,52 @@ class slist
|
||||
{
|
||||
return const_iterator
|
||||
(node_algorithms::get_previous_node
|
||||
(before_begin().pointed_node(), i.pointed_node()));
|
||||
(before_begin().pointed_node(), i.pointed_node()), 0);
|
||||
}
|
||||
|
||||
private:
|
||||
static slist_impl &priv_container_from_end_iterator(const const_iterator &end_iterator)
|
||||
{
|
||||
root_plus_size *r = detail::parent_from_member<root_plus_size, node>
|
||||
( detail::get_pointer(end_iterator.pointed_node()), &root_plus_size::root_);
|
||||
data_t *d = detail::parent_from_member<data_t, root_plus_size>
|
||||
( r, &data_t::root_plus_size_);
|
||||
slist_impl *s = detail::parent_from_member<slist_impl, data_t>(d, &slist_impl::data_);
|
||||
return *s;
|
||||
}
|
||||
};
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator==(const slist<V, C, S>& x, const slist<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator<
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
||||
#else
|
||||
(const slist_impl<Config> &x, const slist_impl<Config> &y)
|
||||
#endif
|
||||
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
bool operator==
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
||||
#else
|
||||
(const slist_impl<Config> &x, const slist_impl<Config> &y)
|
||||
#endif
|
||||
{
|
||||
typedef slist_impl<Config> slist_type;
|
||||
typedef typename slist_type::const_iterator const_iterator;
|
||||
const bool C = slist_type::constant_time_size;
|
||||
if(C && x.size() != y.size()){
|
||||
return false;
|
||||
}
|
||||
typedef typename slist<V, C, S>::const_iterator const_iterator;
|
||||
const_iterator end1 = x.end();
|
||||
|
||||
const_iterator i1 = x.begin();
|
||||
@@ -1406,31 +1548,131 @@ inline bool operator==(const slist<V, C, S>& x, const slist<V, C, S>& y)
|
||||
}
|
||||
}
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator<(const slist<V, C, S>& x,
|
||||
const slist<V, C, S>& y)
|
||||
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator!=(const slist<V, C, S>& x, const slist<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator!=
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
||||
#else
|
||||
(const slist_impl<Config> &x, const slist_impl<Config> &y)
|
||||
#endif
|
||||
{ return !(x == y); }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator>(const slist<V, C, S>& x, const slist<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator>
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
||||
#else
|
||||
(const slist_impl<Config> &x, const slist_impl<Config> &y)
|
||||
#endif
|
||||
{ return y < x; }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator<=(const slist<V, C, S>& x, const slist<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator<=
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
||||
#else
|
||||
(const slist_impl<Config> &x, const slist_impl<Config> &y)
|
||||
#endif
|
||||
{ return !(y < x); }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline bool operator>=(const slist<V, C, S>& x, const slist<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline bool operator>=
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
||||
#else
|
||||
(const slist_impl<Config> &x, const slist_impl<Config> &y)
|
||||
#endif
|
||||
{ return !(x < y); }
|
||||
|
||||
template <class V, bool C, class S>
|
||||
inline void swap(slist<V, C, S>& x, slist<V, C, S>& y)
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class Config>
|
||||
#endif
|
||||
inline void swap
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
(slist_impl<T, Options...> &x, slist_impl<T, Options...> &y)
|
||||
#else
|
||||
(slist_impl<Config> &x, slist_impl<Config> &y)
|
||||
#endif
|
||||
{ x.swap(y); }
|
||||
|
||||
//! Helper metafunction to define a \c slist that yields to the same type when the
|
||||
//! same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class T, class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_slist
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< slist_defaults<T>, O1, O2, O3>::type packed_options;
|
||||
typedef typename detail::get_value_traits
|
||||
<T, typename packed_options::value_traits>::type value_traits;
|
||||
typedef slist_impl
|
||||
<
|
||||
slistopt
|
||||
< value_traits
|
||||
, typename packed_options::size_type
|
||||
, packed_options::constant_time_size
|
||||
>
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class O1, class O2, class O3>
|
||||
class slist
|
||||
: public make_slist<T, O1, O2, O3>::type
|
||||
{
|
||||
typedef typename make_slist
|
||||
<T, O1, O2, O3>::type Base;
|
||||
typedef typename Base::real_value_traits real_value_traits;
|
||||
//Assert if passed value traits are compatible with the type
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
||||
public:
|
||||
typedef typename Base::value_traits value_traits;
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
|
||||
slist(const value_traits &v_traits = value_traits())
|
||||
: Base(v_traits)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
slist(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
|
||||
: Base(b, e, v_traits)
|
||||
{}
|
||||
|
||||
static slist &container_from_end_iterator(iterator end_iterator)
|
||||
{ return static_cast<slist &>(Base::container_from_end_iterator(end_iterator)); }
|
||||
|
||||
static const slist &container_from_end_iterator(const_iterator end_iterator)
|
||||
{ return static_cast<const slist &>(Base::container_from_end_iterator(end_iterator)); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
|
@@ -17,19 +17,48 @@
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/slist_node.hpp>
|
||||
#include <boost/intrusive/circular_slist_algorithms.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/tag.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/intrusive/detail/generic_hook.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
/// @cond
|
||||
template<class VoidPointer>
|
||||
struct get_slist_node_algo
|
||||
{
|
||||
typedef circular_slist_algorithms<slist_node_traits<VoidPointer> > type;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
//! Helper metafunction to define a \c slist_base_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_slist_base_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< hook_defaults, O1, O2, O3>::type packed_options;
|
||||
|
||||
typedef detail::generic_hook
|
||||
< get_slist_node_algo<typename packed_options::void_pointer>
|
||||
, typename packed_options::tag
|
||||
, packed_options::link_mode
|
||||
, detail::SlistBaseHook
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Derive a class from slist_base_hook in order to store objects in
|
||||
//! in an slist. slist_base_hook holds the data necessary to maintain the
|
||||
//! list and provides an appropriate value_traits class for slist.
|
||||
//! in an list. slist_base_hook holds the data necessary to maintain the
|
||||
//! list and provides an appropriate value_traits class for list.
|
||||
//!
|
||||
//! The first integer template argument defines a tag to identify the node.
|
||||
//! The same tag value can be used in different classes, but if a class is
|
||||
@@ -39,97 +68,50 @@ namespace intrusive {
|
||||
//! The second boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the slist configured from this hook.
|
||||
template< class Tag //= tag
|
||||
, linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
//! and the list configured from this hook.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class slist_base_hook
|
||||
: private detail::slist_node_traits<VoidPointer>::node
|
||||
: public make_slist_base_hook<O1, O2, O3>::type
|
||||
{
|
||||
public:
|
||||
typedef detail::slist_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef circular_slist_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef slist_base_hook
|
||||
<Tag, Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
slist_base_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
slist_base_hook();
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using slist_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
slist_base_hook(const slist_base_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
slist_base_hook(const slist_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using slist_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
slist_base_hook& operator=(const slist_base_hook& )
|
||||
{ return *this; }
|
||||
slist_base_hook& operator=(const slist_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in an slist an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~slist_base_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
~slist_base_hook();
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
@@ -143,174 +125,99 @@ class slist_base_hook
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(slist_base_hook &other)
|
||||
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
|
||||
void swap_nodes(slist_base_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether list::iterator_to
|
||||
//! otherwise. This function can be used to test whether \c slist::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
//! The value_traits class is used as the first template argument for list.
|
||||
//! The template argument T defines the class type stored in list. Objects
|
||||
//! of type T and of types derived from T can be stored. T doesn't need to be
|
||||
//! copy-constructible or assignable.
|
||||
template<class T>
|
||||
struct value_traits
|
||||
: detail::derivation_hook_value_traits<T, this_type, Tag>
|
||||
{};
|
||||
//! Helper metafunction to define a \c slist_member_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_slist_member_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< hook_defaults, O1, O2, O3>::type packed_options;
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
return this_type_ptr(static_cast<slist_base_hook*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
return const_this_type_ptr(static_cast<const slist_base_hook*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
typedef detail::generic_hook
|
||||
< get_slist_node_algo<typename packed_options::void_pointer>
|
||||
, member_tag
|
||||
, packed_options::link_mode
|
||||
, detail::NoBaseHook
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Put a public data member slist_member_hook in order to store objects of this class in
|
||||
//! an slist. slist_member_hook holds the data necessary for maintaining the list and
|
||||
//! provides an appropriate value_traits class for slist.
|
||||
//! an list. slist_member_hook holds the data necessary for maintaining the list and
|
||||
//! provides an appropriate value_traits class for list.
|
||||
//!
|
||||
//! The template argument T defines the class type stored in slist. Objects of type
|
||||
//! T and of types derived from T can be stored. T doesn't need to be
|
||||
//! copy-constructible or assignable.
|
||||
//!
|
||||
//! The second boolean template parameter will specify the linking mode of the hook.
|
||||
//! The first boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the slist configured from this hook.
|
||||
template< linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class slist_member_hook
|
||||
: private detail::slist_node_traits<VoidPointer>::node
|
||||
//! The second argument is the pointer type that will be used internally in the hook
|
||||
//! and the list configured from this hook.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class slist_member_hook
|
||||
: public make_slist_member_hook<O1, O2, O3>::type
|
||||
{
|
||||
public:
|
||||
typedef detail::slist_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef circular_slist_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef slist_member_hook
|
||||
<Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type >::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type >::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
slist_member_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
slist_member_hook();
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using slist_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
slist_member_hook(const slist_member_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
slist_member_hook(const slist_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using slist_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
slist_member_hook& operator=(const slist_member_hook& )
|
||||
{ return *this; }
|
||||
slist_member_hook& operator=(const slist_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in an slist an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~slist_member_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
~slist_member_hook();
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
@@ -323,78 +230,29 @@ class slist_member_hook
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(slist_member_hook& other)
|
||||
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(slist_member_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether list::iterator_to
|
||||
//! otherwise. This function can be used to test whether \c slist::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for list.
|
||||
//! The template argument is a pointer to member pointing to the node in
|
||||
//! the class. Objects of type T and of types derived from T can be stored.
|
||||
//! T doesn't need to be copy-constructible or assignable.
|
||||
template<class T, this_type T::* M>
|
||||
struct value_traits
|
||||
: detail::member_hook_value_traits<T, this_type, M>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
return this_type_ptr(static_cast<this_type*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
return const_this_type_ptr(static_cast<const this_type*> (detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include<boost/intrusive/detail/config_end.hpp>
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_SLIST_HOOK_HPP
|
||||
|
@@ -1,26 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007
|
||||
//
|
||||
// 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/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_DEFAULT_TAG_HPP
|
||||
#define BOOST_INTRUSIVE_DEFAULT_TAG_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//!This is the declaration of the default
|
||||
//!hook used by base hooks
|
||||
class tag;
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#endif //BOOST_INTRUSIVE_DEFAULT_TAG_HPP
|
@@ -13,7 +13,7 @@
|
||||
#ifndef BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP
|
||||
#define BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP
|
||||
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
@@ -21,7 +21,7 @@ namespace intrusive {
|
||||
//!This value traits template is used to create value traits
|
||||
//!from user defined node traits where value_traits::value_type and
|
||||
//!node_traits::node should be equal
|
||||
template<class NodeTraits, linking_policy LinkingPolicy = safe_link>
|
||||
template<class NodeTraits, link_mode_type LinkMode = normal_link>
|
||||
struct trivial_value_traits
|
||||
{
|
||||
typedef NodeTraits node_traits;
|
||||
@@ -30,11 +30,11 @@ struct trivial_value_traits
|
||||
typedef typename node_traits::node value_type;
|
||||
typedef node_ptr pointer;
|
||||
typedef const_node_ptr const_pointer;
|
||||
enum { linking_policy = LinkingPolicy };
|
||||
static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); }
|
||||
static const link_mode_type link_mode = LinkMode;
|
||||
static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); }
|
||||
static const_node_ptr to_node_ptr (const value_type &value) { return const_node_ptr(&value); }
|
||||
static pointer to_value_ptr(node_ptr n) { return pointer(n); }
|
||||
static const_pointer to_value_ptr(const_node_ptr n) { return const_pointer(n); }
|
||||
static pointer to_value_ptr(node_ptr n) { return pointer(n); }
|
||||
static const_pointer to_value_ptr(const_node_ptr n) { return const_pointer(n); }
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -11,19 +11,50 @@
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_HASHSET_HOOK_HPP
|
||||
#define BOOST_INTRUSIVE_HASHSET_HOOK_HPP
|
||||
#ifndef BOOST_INTRUSIVE_UNORDERED_SET_HOOK_HPP
|
||||
#define BOOST_INTRUSIVE_UNORDERED_SET_HOOK_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/slist_hook.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/intrusive/detail/generic_hook.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
/// @cond
|
||||
template<class VoidPointer>
|
||||
struct get_uset_node_algo
|
||||
{
|
||||
typedef circular_slist_algorithms<slist_node_traits<VoidPointer> > type;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
//! Helper metafunction to define a \c unordered_set_base_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_unordered_set_base_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< hook_defaults, O1, O2, O3>::type packed_options;
|
||||
|
||||
typedef detail::generic_hook
|
||||
< get_slist_node_algo<typename packed_options::void_pointer>
|
||||
, typename packed_options::tag
|
||||
, packed_options::link_mode
|
||||
, detail::UsetBaseHook
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Derive a class from unordered_set_base_hook in order to store objects in
|
||||
//! in an unordered_set/unordered_multi_set. unordered_set_base_hook holds the data necessary to maintain
|
||||
//! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
|
||||
@@ -37,122 +68,103 @@ namespace intrusive {
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the unordered_set/unordered_multi_set configured from this hook.
|
||||
template< class Tag //= tag
|
||||
, linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class unordered_set_base_hook
|
||||
: public make_unordered_set_base_hook<O1, O2, O3>::type
|
||||
{
|
||||
/// @cond
|
||||
typedef slist_base_hook<Tag, Policy, VoidPointer> IsListHook;
|
||||
IsListHook m_slisthook;
|
||||
typedef IsListHook implementation_defined;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
enum { linking_policy = Policy };
|
||||
typedef typename implementation_defined::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef unordered_set_base_hook
|
||||
<Tag, Policy, VoidPointer> this_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
unordered_set_base_hook()
|
||||
: m_slisthook()
|
||||
{}
|
||||
//! <b>Throws</b>: Nothing.
|
||||
unordered_set_base_hook();
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using unordered_set_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
unordered_set_base_hook(const unordered_set_base_hook &other)
|
||||
: m_slisthook(other.m_slisthook)
|
||||
{}
|
||||
unordered_set_base_hook(const unordered_set_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using unordered_set_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
unordered_set_base_hook& operator=(const unordered_set_base_hook &other)
|
||||
{ return *this; }
|
||||
unordered_set_base_hook& operator=(const unordered_set_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in an unordered_set an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~unordered_set_base_hook()
|
||||
{} //m_slisthook's destructor does the job
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~unordered_set_base_hook();
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(unordered_set_base_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether unordered_set/unordered_multiset::iterator_to
|
||||
//! otherwise. This function can be used to test whether \c unordered_set::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{ return m_slisthook.is_linked(); }
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const;
|
||||
|
||||
//! The value_traits class is used as the first template argument for unordered_set/unordered_multiset.
|
||||
//! The template argument T defines the class type stored in unordered_set/unordered_multiset. Objects
|
||||
//! of type T and of types derived from T can be stored. T doesn't need to be
|
||||
//! copy-constructible or assignable.
|
||||
template<class T>
|
||||
struct value_traits
|
||||
: detail::derivation_hook_value_traits<T, this_type, Tag>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
return this_type_ptr((this_type*)detail::get_pointer(IsListHook::to_hook_ptr(p)));
|
||||
}
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
return const_this_type_ptr((const this_type*)detail::get_pointer(IsListHook::to_hook_ptr(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return m_slisthook.to_node_ptr(); }
|
||||
//! Helper metafunction to define a \c unordered_set_member_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = none, class O2 = none, class O3 = none>
|
||||
#endif
|
||||
struct make_unordered_set_member_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< hook_defaults, O1, O2, O3>::type packed_options;
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return m_slisthook.to_node_ptr(); }
|
||||
typedef detail::generic_hook
|
||||
< get_uset_node_algo<typename packed_options::void_pointer>
|
||||
, member_tag
|
||||
, packed_options::link_mode
|
||||
, detail::NoBaseHook
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Put a public data member unordered_set_member_hook in order to store objects of this class in
|
||||
@@ -163,123 +175,79 @@ class unordered_set_base_hook
|
||||
//!
|
||||
//! The second argument is the pointer type that will be used internally in the hook
|
||||
//! and the unordered_set/unordered_multi_set configured from this hook.
|
||||
template< linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class unordered_set_member_hook
|
||||
: public make_unordered_set_member_hook<O1, O2, O3>::type
|
||||
{
|
||||
/// @cond
|
||||
typedef slist_member_hook<Policy, VoidPointer> IsListHook;
|
||||
IsListHook m_slisthook;
|
||||
typedef IsListHook implementation_defined;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
enum { linking_policy = Policy };
|
||||
typedef typename implementation_defined::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef unordered_set_member_hook
|
||||
<Policy, VoidPointer> this_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
unordered_set_member_hook()
|
||||
: m_slisthook()
|
||||
{}
|
||||
unordered_set_member_hook();
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using unordered_set_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work.
|
||||
unordered_set_member_hook(const unordered_set_member_hook &other)
|
||||
: m_slisthook(other.m_slisthook)
|
||||
{}
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
unordered_set_member_hook(const unordered_set_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using unordered_set_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work.
|
||||
unordered_set_member_hook& operator=(const unordered_set_member_hook &other)
|
||||
{ return *this; }
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
unordered_set_member_hook& operator=(const unordered_set_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in an unordered_set an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~unordered_set_member_hook()
|
||||
{} //m_slisthook's destructor does the job
|
||||
~unordered_set_member_hook();
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{ return m_slisthook.is_linked(); }
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(unordered_set_member_hook &other);
|
||||
|
||||
//! The value_traits class is used as the first template argument for unordered_set/unordered_multiset.
|
||||
//! The template argument is a pointer to member pointing to the node in
|
||||
//! the class. Objects of type T and of types derived from T can be stored.
|
||||
//! T doesn't need to be copy-constructible or assignable.
|
||||
template<class T, this_type T::* M>
|
||||
struct value_traits
|
||||
: detail::member_hook_value_traits<T, this_type, M>
|
||||
{};
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether \c unordered_set::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{ m_slisthook.unlink(); }
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
return this_type_ptr((this_type*)detail::get_pointer(IsListHook::to_hook_ptr(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
return const_this_type_ptr((const this_type*)detail::get_pointer(IsListHook::to_hook_ptr(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return m_slisthook.to_node_ptr(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return m_slisthook.to_node_ptr(); }
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
@@ -287,4 +255,4 @@ class unordered_set_member_hook
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_HASHSET_HOOK_HPP
|
||||
#endif //BOOST_INTRUSIVE_UNORDERED_SET_HOOK_HPP
|
||||
|
Reference in New Issue
Block a user