Merged from trunk for 1.36 release

[SVN r46630]
This commit is contained in:
Ion Gaztañaga
2008-06-23 18:20:30 +00:00
71 changed files with 4684 additions and 1671 deletions

View File

@@ -1,6 +1,6 @@
# Boost.Intrusive library documentation Jamfile # Boost.Intrusive library documentation Jamfile
# #
# Copyright Ion Gazta<EFBFBD>aga 2006. # Copyright Ion Gaztanaga 2006.
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at # (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# Boost Intrusive Library Example Jamfile # Boost Intrusive Library Example Jamfile
# (C) Copyright Ion Gazta<EFBFBD>aga 2006-2007. # (C) Copyright Ion Gaztanaga 2006-2007.
# Use, modification and distribution are subject to the # Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file # Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

62
example/doc_any_hook.cpp Normal file
View File

@@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////
//[doc_any_hook
#include <vector>
#include <boost/intrusive/any_hook.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/list.hpp>
using namespace boost::intrusive;
class MyClass : public any_base_hook<> //Base hook
{
int int_;
public:
any_member_hook<> member_hook_; //Member hook
MyClass(int i = 0) : int_(i)
{}
};
int main()
{
//Define a base hook option that converts any_base_hook to a slist hook
typedef any_to_slist_hook < base_hook< any_base_hook<> > > BaseSlistOption;
typedef slist<MyClass, BaseSlistOption> BaseSList;
//Define a member hook option that converts any_base_hook to a list hook
typedef any_to_list_hook< member_hook
< MyClass, any_member_hook<>, &MyClass::member_hook_> > MemberListOption;
typedef list<MyClass, MemberListOption> MemberList;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i){ values.push_back(MyClass(i)); }
BaseSList base_slist; MemberList member_list;
//Now insert them in reverse order in the slist and in order in the list
for(std::vector<MyClass>::iterator it(values.begin()), itend(values.end()); it != itend; ++it)
base_slist.push_front(*it), member_list.push_back(*it);
//Now test lists
BaseSList::iterator bit(base_slist.begin()), bitend(base_slist.end());
MemberList::reverse_iterator mrit(member_list.rbegin()), mritend(member_list.rend());
std::vector<MyClass>::reverse_iterator rit(values.rbegin()), ritend(values.rend());
//Test the objects inserted in the base hook list
for(; rit != ritend; ++rit, ++bit, ++mrit)
if(&*bit != &*rit || &*mrit != &*rit) return 1;
return 0;
}
//]

View File

@@ -0,0 +1,320 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2008
//
// 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_ANY_HOOK_HPP
#define BOOST_INTRUSIVE_ANY_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/any_node_and_algorithms.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/generic_hook.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
namespace boost {
namespace intrusive {
/// @cond
template<class VoidPointer>
struct get_any_node_algo
{
typedef any_algorithms<VoidPointer> type;
};
/// @endcond
//! Helper metafunction to define a \c \c any_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_any_base_hook
{
/// @cond
typedef typename pack_options
< hook_defaults, O1, O2, O3>::type packed_options;
typedef detail::generic_hook
< get_any_node_algo<typename packed_options::void_pointer>
, typename packed_options::tag
, packed_options::link_mode
, detail::AnyBaseHook
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
//! Derive a class from this hook in order to store objects of that class
//! in an intrusive container.
//!
//! The hook admits the following options: \c tag<>, \c void_pointer<> and
//! \c link_mode<>.
//!
//! \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 any_base_hook, then each \c any_base_hook needs its
//! unique tag.
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, \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 any_base_hook
: public make_any_base_hook<O1, O2, O3>::type
{
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
public:
//! <b>Effects</b>: If link_mode is or \c safe_link
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
any_base_hook();
//! <b>Effects</b>: If link_mode is 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 the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
any_base_hook(const any_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 the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
any_base_hook& operator=(const any_base_hook& );
//! <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 a container an assertion is raised.
//!
//! <b>Throws</b>: Nothing.
~any_base_hook();
//! <b>Precondition</b>: link_mode must be \c safe_link.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether \c container::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const;
#endif
};
//! Helper metafunction to define a \c \c any_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_any_member_hook
{
/// @cond
typedef typename pack_options
< hook_defaults, O1, O2, O3>::type packed_options;
typedef detail::generic_hook
< get_any_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 intrusive container.
//!
//! 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 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 any_member_hook
: public make_any_member_hook<O1, O2, O3>::type
{
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
public:
//! <b>Effects</b>: If link_mode is or \c safe_link
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
any_member_hook();
//! <b>Effects</b>: If link_mode is 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 the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
any_member_hook(const any_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 the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
any_member_hook& operator=(const any_member_hook& );
//! <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 a container an assertion is raised.
//!
//! <b>Throws</b>: Nothing.
~any_member_hook();
//! <b>Precondition</b>: link_mode must be \c safe_link.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether \c container::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const;
#endif
};
/// @cond
namespace detail{
template<class ValueTraits>
struct any_to_get_base_pointer_type
{
typedef typename pointer_to_other
<typename ValueTraits::boost_intrusive_tags::node_traits::node_ptr, void>::type type;
};
template<class ValueTraits>
struct any_to_get_member_pointer_type
{
typedef typename pointer_to_other
<typename ValueTraits::node_ptr, void>::type type;
};
//!This option setter specifies that the container
//!must use the specified base hook
template<class BaseHook, template <class> class NodeTraits>
struct any_to_some_hook
{
typedef typename BaseHook::template pack<none>::value_traits old_value_traits;
template<class Base>
struct pack : public Base
{
struct value_traits : public old_value_traits
{
static const bool is_any_hook = true;
typedef typename detail::eval_if_c
< detail::internal_base_hook_bool_is_true<old_value_traits>::value
, any_to_get_base_pointer_type<old_value_traits>
, any_to_get_member_pointer_type<old_value_traits>
>::type void_pointer;
typedef NodeTraits<void_pointer> node_traits;
};
};
};
} //namespace detail{
/// @endcond
//!This option setter specifies that
//!any hook should behave as an slist hook
template<class BaseHook>
struct any_to_slist_hook
/// @cond
: public detail::any_to_some_hook<BaseHook, any_slist_node_traits>
/// @endcond
{};
//!This option setter specifies that
//!any hook should behave as an list hook
template<class BaseHook>
struct any_to_list_hook
/// @cond
: public detail::any_to_some_hook<BaseHook, any_list_node_traits>
/// @endcond
{};
//!This option setter specifies that
//!any hook should behave as a set hook
template<class BaseHook>
struct any_to_set_hook
/// @cond
: public detail::any_to_some_hook<BaseHook, any_rbtree_node_traits>
/// @endcond
{};
//!This option setter specifies that
//!any hook should behave as a set hook
template<class BaseHook>
struct any_to_avl_set_hook
/// @cond
: public detail::any_to_some_hook<BaseHook, any_avltree_node_traits>
/// @endcond
{};
//!This option setter specifies that any
//!hook should behave as a set hook
template<class BaseHook>
struct any_to_bs_set_hook
/// @cond
: public detail::any_to_some_hook<BaseHook, any_tree_node_traits>
/// @endcond
{};
//!This option setter specifies that any hook
//!should behave as an unordered set hook
template<class BaseHook>
struct any_to_unordered_set_hook
/// @cond
: public detail::any_to_some_hook<BaseHook, any_unordered_node_traits>
/// @endcond
{};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_ANY_HOOK_HPP

View File

@@ -240,7 +240,7 @@ class avl_set_impl
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
//! of avl_set. //! of avl_set.
//! //!
//! <b>Effects</b>: Returns a const reference to the avl_set associated to the end iterator //! <b>Effects</b>: Returns a const reference to the set associated to the end iterator
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
@@ -252,6 +252,34 @@ class avl_set_impl
, &avl_set_impl::tree_); , &avl_set_impl::tree_);
} }
//! <b>Precondition</b>: it must be a valid iterator of set.
//!
//! <b>Effects</b>: Returns a reference to the set associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static avl_set_impl &container_from_iterator(iterator it)
{
return *detail::parent_from_member<avl_set_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &avl_set_impl::tree_);
}
//! <b>Precondition</b>: it must be a valid const_iterator of set.
//!
//! <b>Effects</b>: Returns a const reference to the set associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const avl_set_impl &container_from_iterator(const_iterator it)
{
return *detail::parent_from_member<avl_set_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &avl_set_impl::tree_);
}
//! <b>Effects</b>: Returns the key_compare object used by the avl_set. //! <b>Effects</b>: Returns the key_compare object used by the avl_set.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1085,6 +1113,12 @@ class avl_set
static const avl_set &container_from_end_iterator(const_iterator end_iterator) static const avl_set &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const avl_set &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const avl_set &>(Base::container_from_end_iterator(end_iterator)); }
static avl_set &container_from_iterator(iterator end_iterator)
{ return static_cast<avl_set &>(Base::container_from_iterator(end_iterator)); }
static const avl_set &container_from_iterator(const_iterator end_iterator)
{ return static_cast<const avl_set &>(Base::container_from_iterator(end_iterator)); }
}; };
#endif #endif
@@ -1317,6 +1351,34 @@ class avl_multiset_impl
, &avl_multiset_impl::tree_); , &avl_multiset_impl::tree_);
} }
//! <b>Precondition</b>: it must be a valid iterator of multiset.
//!
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static avl_multiset_impl &container_from_iterator(iterator it)
{
return *detail::parent_from_member<avl_multiset_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &avl_multiset_impl::tree_);
}
//! <b>Precondition</b>: it must be a valid const_iterator of multiset.
//!
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const avl_multiset_impl &container_from_iterator(const_iterator it)
{
return *detail::parent_from_member<avl_multiset_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &avl_multiset_impl::tree_);
}
//! <b>Effects</b>: Returns the key_compare object used by the avl_multiset. //! <b>Effects</b>: Returns the key_compare object used by the avl_multiset.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -2057,6 +2119,12 @@ class avl_multiset
static const avl_multiset &container_from_end_iterator(const_iterator end_iterator) static const avl_multiset &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const avl_multiset &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const avl_multiset &>(Base::container_from_end_iterator(end_iterator)); }
static avl_multiset &container_from_iterator(iterator end_iterator)
{ return static_cast<avl_multiset &>(Base::container_from_iterator(end_iterator)); }
static const avl_multiset &container_from_iterator(const_iterator end_iterator)
{ return static_cast<const avl_multiset &>(Base::container_from_iterator(end_iterator)); }
}; };
#endif #endif

View File

@@ -387,6 +387,28 @@ class avltree_impl
static const avltree_impl &container_from_end_iterator(const_iterator end_iterator) static const avltree_impl &container_from_end_iterator(const_iterator end_iterator)
{ return priv_container_from_end_iterator(end_iterator); } { return priv_container_from_end_iterator(end_iterator); }
//! <b>Precondition</b>: it must be a valid iterator
//! of rbtree.
//!
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static avltree_impl &container_from_iterator(iterator it)
{ return priv_container_from_iterator(it); }
//! <b>Precondition</b>: it must be a valid end const_iterator
//! of rbtree.
//!
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const avltree_impl &container_from_iterator(const_iterator it)
{ return priv_container_from_iterator(it); }
//! <b>Effects</b>: Returns the value_compare object used by the tree. //! <b>Effects</b>: Returns the value_compare object used by the tree.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1233,6 +1255,9 @@ class avltree_impl
avltree_impl *avl = detail::parent_from_member<avltree_impl, data_t>(d, &avltree_impl::data_); avltree_impl *avl = detail::parent_from_member<avltree_impl, data_t>(d, &avltree_impl::data_);
return *avl; return *avl;
} }
static avltree_impl &priv_container_from_iterator(const const_iterator &it)
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
}; };
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
@@ -1426,6 +1451,12 @@ class avltree
static const avltree &container_from_end_iterator(const_iterator end_iterator) static const avltree &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const avltree &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const avltree &>(Base::container_from_end_iterator(end_iterator)); }
static avltree &container_from_iterator(iterator it)
{ return static_cast<avltree &>(Base::container_from_iterator(it)); }
static const avltree &container_from_iterator(const_iterator it)
{ return static_cast<const avltree &>(Base::container_from_iterator(it)); }
}; };
#endif #endif

View File

@@ -20,7 +20,6 @@
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/no_exceptions_support.hpp>
#include <boost/intrusive/detail/utilities.hpp> #include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/tree_algorithms.hpp> #include <boost/intrusive/detail/tree_algorithms.hpp>
@@ -69,6 +68,7 @@ template<class NodeTraits>
class avltree_algorithms class avltree_algorithms
{ {
public: public:
typedef typename NodeTraits::node node;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
@@ -76,8 +76,6 @@ class avltree_algorithms
/// @cond /// @cond
private: private:
typedef typename NodeTraits::node node;
typedef detail::tree_algorithms<NodeTraits> tree_algorithms; typedef detail::tree_algorithms<NodeTraits> tree_algorithms;
template<class F> template<class F>
@@ -641,6 +639,16 @@ class avltree_algorithms
rebalance_after_insertion(header, new_value); rebalance_after_insertion(header, new_value);
} }
//! <b>Requires</b>: "n" must be a node inserted in a tree.
//!
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
//!
//! <b>Complexity</b>: Logarithmic.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_header(node_ptr n)
{ return tree_algorithms::get_header(n); }
/// @cond /// @cond
private: private:

View File

@@ -50,6 +50,7 @@ template<class NodeTraits>
class circular_list_algorithms class circular_list_algorithms
{ {
public: public:
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
@@ -62,8 +63,8 @@ class circular_list_algorithms
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static void init(node_ptr this_node) static void init(node_ptr this_node)
{ {
NodeTraits::set_next(this_node, 0); NodeTraits::set_next(this_node, node_ptr(0));
NodeTraits::set_previous(this_node, 0); NodeTraits::set_previous(this_node, node_ptr(0));
} }
//! <b>Effects</b>: Returns true is "this_node" is in a non-used state //! <b>Effects</b>: Returns true is "this_node" is in a non-used state

View File

@@ -54,6 +54,7 @@ class circular_slist_algorithms
typedef detail::common_slist_algorithms<NodeTraits> base_t; typedef detail::common_slist_algorithms<NodeTraits> base_t;
/// @endcond /// @endcond
public: public:
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
@@ -305,12 +306,12 @@ class circular_slist_algorithms
static node_ptr move_backwards(node_ptr p, std::size_t n) static node_ptr move_backwards(node_ptr p, std::size_t n)
{ {
//Null shift, nothing to do //Null shift, nothing to do
if(!n) return 0; if(!n) return node_ptr(0);
node_ptr first = NodeTraits::get_next(p); node_ptr first = NodeTraits::get_next(p);
//count() == 1 or 2, nothing to do //count() == 1 or 2, nothing to do
if(NodeTraits::get_next(first) == p) if(NodeTraits::get_next(first) == p)
return 0; return node_ptr(0);
bool end_found = false; bool end_found = false;
node_ptr new_last(0); node_ptr new_last(0);
@@ -326,7 +327,7 @@ class circular_slist_algorithms
//Shortcut the shift with the modulo of the size of the list //Shortcut the shift with the modulo of the size of the list
n %= i; n %= i;
if(!n) if(!n)
return 0; return node_ptr(0);
i = 0; i = 0;
//Unlink p and continue the new first node search //Unlink p and continue the new first node search
first = NodeTraits::get_next(p); first = NodeTraits::get_next(p);
@@ -357,11 +358,11 @@ class circular_slist_algorithms
static node_ptr move_forward(node_ptr p, std::size_t n) static node_ptr move_forward(node_ptr p, std::size_t n)
{ {
//Null shift, nothing to do //Null shift, nothing to do
if(!n) return 0; if(!n) return node_ptr(0);
node_ptr first = node_traits::get_next(p); node_ptr first = node_traits::get_next(p);
//count() == 1 or 2, nothing to do //count() == 1 or 2, nothing to do
if(node_traits::get_next(first) == p) return 0; if(node_traits::get_next(first) == p) return node_ptr(0);
//Iterate until p is found to know where the current last node is. //Iterate until p is found to know where the current last node is.
//If the shift count is less than the size of the list, we can also obtain //If the shift count is less than the size of the list, we can also obtain
@@ -380,7 +381,7 @@ class circular_slist_algorithms
//Shortcut the shift with the modulo of the size of the list //Shortcut the shift with the modulo of the size of the list
std::size_t new_before_last_pos = (distance - (n % distance))% distance; std::size_t new_before_last_pos = (distance - (n % distance))% distance;
//If the shift is a multiple of the size there is nothing to do //If the shift is a multiple of the size there is nothing to do
if(!new_before_last_pos) return 0; if(!new_before_last_pos) return node_ptr(0);
for( new_last = p for( new_last = p
; new_before_last_pos-- ; new_before_last_pos--

View File

@@ -0,0 +1,292 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2008
//
// 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_ANY_NODE_HPP
#define BOOST_INTRUSIVE_ANY_NODE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <iterator>
#include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
template<class VoidPointer>
struct any_node
{
typedef typename boost::pointer_to_other
<VoidPointer, any_node>::type node_ptr;
node_ptr node_ptr_1;
node_ptr node_ptr_2;
node_ptr node_ptr_3;
std::size_t size_t_1;
};
template<class VoidPointer>
struct any_list_node_traits
{
typedef any_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;
static node_ptr get_next(const_node_ptr n)
{ return n->node_ptr_1; }
static void set_next(node_ptr n, node_ptr next)
{ n->node_ptr_1 = next; }
static node_ptr get_previous(const_node_ptr n)
{ return n->node_ptr_2; }
static void set_previous(node_ptr n, node_ptr prev)
{ n->node_ptr_2 = prev; }
};
template<class VoidPointer>
struct any_slist_node_traits
{
typedef any_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;
static node_ptr get_next(const_node_ptr n)
{ return n->node_ptr_1; }
static void set_next(node_ptr n, node_ptr next)
{ n->node_ptr_1 = next; }
};
template<class VoidPointer>
struct any_unordered_node_traits
: public any_slist_node_traits<VoidPointer>
{
typedef any_slist_node_traits<VoidPointer> reduced_slist_node_traits;
typedef typename reduced_slist_node_traits::node node;
typedef typename reduced_slist_node_traits::node_ptr node_ptr;
typedef typename reduced_slist_node_traits::const_node_ptr const_node_ptr;
static const bool store_hash = true;
static const bool optimize_multikey = true;
static node_ptr get_next(const_node_ptr n)
{ return node_ptr(&static_cast<node &>(*n->node_ptr_1)); }
static void set_next(node_ptr n, node_ptr next)
{ n->node_ptr_1 = next; }
static node_ptr get_prev_in_group(const_node_ptr n)
{ return n->node_ptr_2; }
static void set_prev_in_group(node_ptr n, node_ptr prev)
{ n->node_ptr_2 = prev; }
static std::size_t get_hash(const_node_ptr n)
{ return n->size_t_1; }
static void set_hash(node_ptr n, std::size_t h)
{ n->size_t_1 = h; }
};
template<class VoidPointer>
struct any_rbtree_node_traits
{
typedef any_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;
typedef std::size_t color;
static node_ptr get_parent(const_node_ptr n)
{ return n->node_ptr_1; }
static void set_parent(node_ptr n, node_ptr p)
{ n->node_ptr_1 = p; }
static node_ptr get_left(const_node_ptr n)
{ return n->node_ptr_2; }
static void set_left(node_ptr n, node_ptr l)
{ n->node_ptr_2 = l; }
static node_ptr get_right(const_node_ptr n)
{ return n->node_ptr_3; }
static void set_right(node_ptr n, node_ptr r)
{ n->node_ptr_3 = r; }
static color get_color(const_node_ptr n)
{ return n->size_t_1; }
static void set_color(node_ptr n, color c)
{ n->size_t_1 = c; }
static color black()
{ return 0u; }
static color red()
{ return 1u; }
};
template<class VoidPointer>
struct any_avltree_node_traits
{
typedef any_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;
typedef std::size_t balance;
static node_ptr get_parent(const_node_ptr n)
{ return n->node_ptr_1; }
static void set_parent(node_ptr n, node_ptr p)
{ n->node_ptr_1 = p; }
static node_ptr get_left(const_node_ptr n)
{ return n->node_ptr_2; }
static void set_left(node_ptr n, node_ptr l)
{ n->node_ptr_2 = l; }
static node_ptr get_right(const_node_ptr n)
{ return n->node_ptr_3; }
static void set_right(node_ptr n, node_ptr r)
{ n->node_ptr_3 = r; }
static balance get_balance(const_node_ptr n)
{ return n->size_t_1; }
static void set_balance(node_ptr n, balance b)
{ n->size_t_1 = b; }
static balance negative()
{ return 0u; }
static balance zero()
{ return 1u; }
static balance positive()
{ return 2u; }
};
template<class VoidPointer>
struct any_tree_node_traits
{
typedef any_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;
static node_ptr get_parent(const_node_ptr n)
{ return n->node_ptr_1; }
static void set_parent(node_ptr n, node_ptr p)
{ n->node_ptr_1 = p; }
static node_ptr get_left(const_node_ptr n)
{ return n->node_ptr_2; }
static void set_left(node_ptr n, node_ptr l)
{ n->node_ptr_2 = l; }
static node_ptr get_right(const_node_ptr n)
{ return n->node_ptr_3; }
static void set_right(node_ptr n, node_ptr r)
{ n->node_ptr_3 = r; }
};
template<class VoidPointer>
class any_node_traits
{
public:
typedef any_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;
};
template<class VoidPointer>
class any_algorithms
{
public:
typedef any_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;
typedef any_node_traits<VoidPointer> node_traits;
//! <b>Requires</b>: node must not be part of any tree.
//!
//! <b>Effects</b>: After the function unique(node) == true.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
static void init(node_ptr node)
{ node->node_ptr_1 = 0; };
//! <b>Effects</b>: Returns true if node is in the same state as if called init(node)
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr node)
{ return !node->node_ptr_1; };
static bool unique(const_node_ptr node)
{ return 0 == node->node_ptr_1; }
static void unlink(node_ptr)
{
//Auto-unlink hooks and unlink() call for safe hooks are not
//available for any hooks!!!
any_algorithms<VoidPointer>::unlink_not_available_for_any_hooks();
}
static void swap_nodes(node_ptr l, node_ptr r)
{
//Any nodes have no swap_nodes capability because they don't know
//what algorithm they must use from unlink them from the container
any_algorithms<VoidPointer>::swap_nodes_not_available_for_any_hooks();
}
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_ANY_NODE_HPP

View File

@@ -17,7 +17,7 @@
#include <iterator> #include <iterator>
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/avltree_algorithms.hpp> #include <boost/intrusive/avltree_algorithms.hpp>
#include <boost/intrusive/pointer_plus_2_bits.hpp> #include <boost/intrusive/pointer_plus_bits.hpp>
#include <boost/intrusive/detail/mpl.hpp> #include <boost/intrusive/detail/mpl.hpp>
namespace boost { namespace boost {
@@ -111,7 +111,7 @@ struct compact_avltree_node_traits_impl
<VoidPointer, const node>::type const_node_ptr; <VoidPointer, const node>::type const_node_ptr;
typedef typename node::balance balance; typedef typename node::balance balance;
typedef pointer_plus_2_bits<node_ptr> ptr_bit; typedef pointer_plus_bits<node_ptr, 2> ptr_bit;
static node_ptr get_parent(const_node_ptr n) static node_ptr get_parent(const_node_ptr n)
{ return ptr_bit::get_pointer(n->parent_); } { return ptr_bit::get_pointer(n->parent_); }
@@ -148,7 +148,7 @@ struct compact_avltree_node_traits_impl
}; };
//Dispatches the implementation based on the boolean //Dispatches the implementation based on the boolean
template<class VoidPointer, bool compact> template<class VoidPointer, bool Compact>
struct avltree_node_traits_dispatch struct avltree_node_traits_dispatch
: public default_avltree_node_traits_impl<VoidPointer> : public default_avltree_node_traits_impl<VoidPointer>
{}; {};
@@ -164,10 +164,10 @@ struct avltree_node_traits
: public avltree_node_traits_dispatch : public avltree_node_traits_dispatch
< VoidPointer < VoidPointer
, OptimizeSize && , OptimizeSize &&
has_pointer_plus_2_bits max_pointer_plus_bits
< VoidPointer < VoidPointer
, detail::alignment_of<compact_avltree_node<VoidPointer> >::value , detail::alignment_of<compact_avltree_node<VoidPointer> >::value
>::value >::value >= 2u
> >
{}; {};

View File

@@ -26,6 +26,7 @@ template<class NodeTraits>
class common_slist_algorithms class common_slist_algorithms
{ {
public: public:
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
@@ -47,13 +48,13 @@ class common_slist_algorithms
{ NodeTraits::set_next(this_node, this_node); } { NodeTraits::set_next(this_node, this_node); }
static void init(node_ptr this_node) static void init(node_ptr this_node)
{ NodeTraits::set_next(this_node, 0); } { NodeTraits::set_next(this_node, node_ptr(0)); }
static bool unique(const_node_ptr this_node) static bool unique(const_node_ptr this_node)
{ {
node_ptr next = NodeTraits::get_next(this_node); node_ptr next = NodeTraits::get_next(this_node);
return !next || next == this_node; return !next || next == this_node;
} }
static bool inited(const_node_ptr this_node) static bool inited(const_node_ptr this_node)
{ return !NodeTraits::get_next(this_node); } { return !NodeTraits::get_next(this_node); }

View File

@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// (C) Copyright Joaqu<EFBFBD>n M L<EFBFBD>pez Mu<EFBFBD>oz 2006-2007 // (C) Copyright Joaquin M Lopez Munoz 2006-2007
// //
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
@@ -23,8 +23,15 @@ template<typename T, bool IsEmpty = true>
class ebo_functor_holder_impl class ebo_functor_holder_impl
{ {
public: public:
ebo_functor_holder_impl(){} ebo_functor_holder_impl()
ebo_functor_holder_impl(const T& t):t(t){} {}
ebo_functor_holder_impl(const T& t)
: t(t)
{}
template<class Arg1, class Arg2>
ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2)
: t(arg1, arg2)
{}
T& get(){return t;} T& get(){return t;}
const T& get()const{return t;} const T& get()const{return t;}
@@ -38,8 +45,15 @@ class ebo_functor_holder_impl<T, false>
: public T : public T
{ {
public: public:
ebo_functor_holder_impl(){} ebo_functor_holder_impl()
ebo_functor_holder_impl(const T& t):T(t){} {}
ebo_functor_holder_impl(const T& t)
: T(t)
{}
template<class Arg1, class Arg2>
ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2)
: T(arg1, arg2)
{}
T& get(){return *this;} T& get(){return *this;}
const T& get()const{return *this;} const T& get()const{return *this;}
@@ -54,7 +68,14 @@ class ebo_functor_holder
public: public:
ebo_functor_holder(){} ebo_functor_holder(){}
ebo_functor_holder(const T& t):super(t){} ebo_functor_holder(const T& t)
: super(t)
{}
template<class Arg1, class Arg2>
ebo_functor_holder(const Arg1& arg1, const Arg2& arg2)
: super(arg1, arg2)
{}
ebo_functor_holder& operator=(const ebo_functor_holder& x) ebo_functor_holder& operator=(const ebo_functor_holder& x)
{ {

View File

@@ -18,6 +18,7 @@
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/link_mode.hpp> #include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/detail/utilities.hpp> #include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
namespace boost { namespace boost {
@@ -35,6 +36,7 @@ enum
, SplaySetBaseHook , SplaySetBaseHook
, AvlSetBaseHook , AvlSetBaseHook
, BsSetBaseHook , BsSetBaseHook
, AnyBaseHook
}; };
struct no_default_definer{}; struct no_default_definer{};
@@ -70,6 +72,10 @@ template <class Hook>
struct default_definer<Hook, BsSetBaseHook> struct default_definer<Hook, BsSetBaseHook>
{ typedef Hook default_bs_set_hook; }; { typedef Hook default_bs_set_hook; };
template <class Hook>
struct default_definer<Hook, AnyBaseHook>
{ typedef Hook default_any_hook; };
template <class Hook, unsigned int BaseHookType> template <class Hook, unsigned int BaseHookType>
struct make_default_definer struct make_default_definer
{ {
@@ -90,11 +96,11 @@ struct make_node_holder
typedef typename detail::if_c typedef typename detail::if_c
<!detail::is_same<Tag, member_tag>::value <!detail::is_same<Tag, member_tag>::value
, detail::node_holder , detail::node_holder
< typename GetNodeAlgorithms::type::node_traits::node < typename GetNodeAlgorithms::type::node
, Tag , Tag
, LinkMode , LinkMode
, HookType> , HookType>
, typename GetNodeAlgorithms::type::node_traits::node , typename GetNodeAlgorithms::type::node
>::type type; >::type type;
}; };
@@ -122,38 +128,38 @@ class generic_hook
, public make_node_holder<GetNodeAlgorithms, Tag, LinkMode, HookType>::type , public make_node_holder<GetNodeAlgorithms, Tag, LinkMode, HookType>::type
/// @endcond /// @endcond
{ {
public:
/// @cond /// @cond
typedef typename GetNodeAlgorithms::type node_algorithms;
typedef typename node_algorithms::node node;
typedef typename node_algorithms::node_ptr node_ptr;
typedef typename node_algorithms::const_node_ptr const_node_ptr;
public:
struct boost_intrusive_tags struct boost_intrusive_tags
{ {
static const int hook_type = HookType; static const int hook_type = HookType;
static const link_mode_type link_mode = LinkMode; static const link_mode_type link_mode = LinkMode;
typedef Tag tag; typedef Tag tag;
typedef typename GetNodeAlgorithms::type node_algorithms; typedef typename GetNodeAlgorithms::type::node_traits node_traits;
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; static const bool is_base_hook = !detail::is_same<Tag, member_tag>::value;
enum { safemode_or_autounlink = static const bool safemode_or_autounlink =
(int)link_mode == (int)auto_unlink || (int)link_mode == (int)auto_unlink || (int)link_mode == (int)safe_link;
(int)link_mode == (int)safe_link };
}; };
public:
/// @endcond /// @endcond
generic_hook() generic_hook()
{ {
if(boost_intrusive_tags::safemode_or_autounlink){ if(boost_intrusive_tags::safemode_or_autounlink){
boost_intrusive_tags::node_algorithms::init node_algorithms::init(static_cast<node*>(this));
(static_cast<typename boost_intrusive_tags::node*>(this));
} }
} }
generic_hook(const generic_hook& ) generic_hook(const generic_hook& )
{ {
if(boost_intrusive_tags::safemode_or_autounlink){ if(boost_intrusive_tags::safemode_or_autounlink){
boost_intrusive_tags::node_algorithms::init node_algorithms::init(static_cast<node*>(this));
(static_cast<typename boost_intrusive_tags::node*>(this));
} }
} }
@@ -168,26 +174,23 @@ class generic_hook
void swap_nodes(generic_hook &other) void swap_nodes(generic_hook &other)
{ {
boost_intrusive_tags::node_algorithms::swap_nodes node_algorithms::swap_nodes
( static_cast<typename boost_intrusive_tags::node*>(this) ( static_cast<node*>(this), static_cast<node*>(&other));
, static_cast<typename boost_intrusive_tags::node*>(&other));
} }
bool is_linked() const bool is_linked() const
{ {
//is_linked() can be only used in safe-mode or auto-unlink //is_linked() can be only used in safe-mode or auto-unlink
BOOST_STATIC_ASSERT(( boost_intrusive_tags::safemode_or_autounlink )); BOOST_STATIC_ASSERT(( boost_intrusive_tags::safemode_or_autounlink ));
return !boost_intrusive_tags::node_algorithms::unique return !node_algorithms::unique
(static_cast<const typename boost_intrusive_tags::node*>(this)); (static_cast<const node*>(this));
} }
void unlink() void unlink()
{ {
BOOST_STATIC_ASSERT(( (int)boost_intrusive_tags::link_mode == (int)auto_unlink )); BOOST_STATIC_ASSERT(( (int)boost_intrusive_tags::link_mode == (int)auto_unlink ));
boost_intrusive_tags::node_algorithms::unlink node_algorithms::unlink(static_cast<node*>(this));
(static_cast<typename boost_intrusive_tags::node*>(this)); node_algorithms::init(static_cast<node*>(this));
boost_intrusive_tags::node_algorithms::init
(static_cast<typename boost_intrusive_tags::node*>(this));
} }
}; };

View File

@@ -50,6 +50,7 @@ const std::size_t prime_list_holder<Dummy>::prime_list_size
template <class Slist> template <class Slist>
struct bucket_impl : public Slist struct bucket_impl : public Slist
{ {
typedef Slist slist_type;
bucket_impl() bucket_impl()
{} {}
@@ -69,28 +70,6 @@ struct bucket_impl : public Slist
//Slist::clear(); //Slist::clear();
return *this; return *this;
} }
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:
//iterate until we reach it.
while(!(first.pointed_node() <= it.pointed_node() &&
it.pointed_node() <= last.pointed_node())){
++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;
}
}; };
template<class Slist> template<class Slist>
@@ -125,13 +104,16 @@ class hashtable_iterator
<typename Container::value_type, IsConst>::type <typename Container::value_type, IsConst>::type
> >
{ {
typedef typename Container::real_value_traits real_value_traits; typedef typename Container::real_value_traits real_value_traits;
typedef typename Container::siterator siterator; typedef typename Container::siterator siterator;
typedef typename Container::const_siterator const_siterator; typedef typename Container::const_siterator const_siterator;
typedef typename Container::bucket_type bucket_type; typedef typename Container::bucket_type bucket_type;
typedef typename boost::pointer_to_other typedef typename boost::pointer_to_other
< typename Container::pointer, const Container>::type const_cont_ptr; < typename Container::pointer, const Container>::type const_cont_ptr;
typedef typename Container::size_type size_type; typedef typename Container::size_type size_type;
static typename Container::node_ptr downcast_bucket(typename bucket_type::node_ptr p)
{ return typename Container::node_ptr(&static_cast<typename Container::node&>(*p)); }
public: public:
typedef typename detail::add_const_if_c typedef typename detail::add_const_if_c
@@ -172,7 +154,7 @@ class hashtable_iterator
{ return *this->operator ->(); } { return *this->operator ->(); }
value_type* operator->() const value_type* operator->() const
{ return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(slist_it_.pointed_node())); } { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); }
const Container *get_container() const const Container *get_container() const
{ return detail::get_pointer(cont_); } { return detail::get_pointer(cont_); }
@@ -186,17 +168,19 @@ class hashtable_iterator
const Container *cont = detail::get_pointer(cont_); const Container *cont = detail::get_pointer(cont_);
bucket_type* buckets = detail::get_pointer(cont->bucket_pointer()); bucket_type* buckets = detail::get_pointer(cont->bucket_pointer());
size_type buckets_len = cont->bucket_count(); size_type buckets_len = cont->bucket_count();
const_siterator first(buckets[0].cend());
const_siterator last (buckets[buckets_len].cend());
++slist_it_; ++slist_it_;
if(first.pointed_node() <= slist_it_.pointed_node() && if(buckets[0].cend().pointed_node() <= slist_it_.pointed_node() &&
slist_it_.pointed_node()<= last.pointed_node() ){ slist_it_.pointed_node()<= buckets[buckets_len].cend().pointed_node() ){
size_type n_bucket = (size_type) //Now get the bucket_impl from the iterator
bucket_type::get_bucket_num(slist_it_, buckets[0], buckets[buckets_len]); const bucket_type &b = static_cast<const bucket_type&>
(bucket_type::slist_type::container_from_end_iterator(slist_it_));
//Now just calculate the index b has in the bucket array
size_type n_bucket = static_cast<size_type>(&b - &buckets[0]);
do{ do{
if (++n_bucket == buckets_len){ if (++n_bucket == buckets_len){
slist_it_ = buckets->end(); slist_it_ = (&buckets[0] + buckets_len)->end();
break; break;
} }
slist_it_ = buckets[n_bucket].begin(); slist_it_ = buckets[n_bucket].begin();

View File

@@ -18,7 +18,6 @@
#include <iterator> #include <iterator>
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/circular_list_algorithms.hpp>
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
@@ -32,7 +31,8 @@ struct list_node
{ {
typedef typename boost::pointer_to_other typedef typename boost::pointer_to_other
<VoidPointer, list_node>::type node_ptr; <VoidPointer, list_node>::type node_ptr;
node_ptr prev_, next_; node_ptr next_;
node_ptr prev_;
}; };
template<class VoidPointer> template<class VoidPointer>
@@ -85,7 +85,7 @@ class list_iterator
typedef value_type * pointer; typedef value_type * pointer;
list_iterator() list_iterator()
: members_ (0, 0) : members_ (node_ptr(0), 0)
{} {}
explicit list_iterator(node_ptr node, const Container *cont_ptr) explicit list_iterator(node_ptr node, const Container *cont_ptr)

View File

@@ -13,6 +13,8 @@
#ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP #ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP
#define BOOST_INTRUSIVE_DETAIL_MPL_HPP #define BOOST_INTRUSIVE_DETAIL_MPL_HPP
#include <cstddef>
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
namespace detail { namespace detail {
@@ -290,6 +292,24 @@ class is_empty_class
static const bool value = sizeof(empty_helper_t1<Class>) == sizeof(empty_helper_t2); static const bool value = sizeof(empty_helper_t1<Class>) == sizeof(empty_helper_t2);
}; };
template<std::size_t S>
struct ls_zeros
{
static const std::size_t value = (S & std::size_t(1)) ? 0 : (1 + ls_zeros<(S>>1u)>::value);
};
template<>
struct ls_zeros<0>
{
static const std::size_t value = 0;
};
template<>
struct ls_zeros<1>
{
static const std::size_t value = 0;
};
} //namespace detail } //namespace detail
} //namespace intrusive } //namespace intrusive
} //namespace boost } //namespace boost

View File

@@ -1,28 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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

View File

@@ -13,25 +13,30 @@
#define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP #define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP
#include <boost/intrusive/detail/config_begin.hpp> #include <boost/intrusive/detail/config_begin.hpp>
#include <boost/static_assert.hpp>
#include <cstddef> #include <cstddef>
#if defined(BOOST_MSVC) || (defined (BOOST_WINDOWS) && defined(BOOST_INTEL))
#define BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER
#include <boost/cstdint.hpp>
#endif
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
namespace detail { namespace detail {
template<class Parent, class Member> template<class Parent, class Member>
inline std::size_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member) inline std::ptrdiff_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. //The implementation of a pointer to member is compiler dependent.
#if defined(BOOST_MSVC) || (defined (BOOST_WINDOWS) && defined(BOOST_INTEL)) #if defined(BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER)
//msvc compliant compilers use their the first 32 bits as offset (even in 64 bit mode)
return *(const boost::int32_t*)(void*)&ptr_to_member;
//This works with gcc, msvc, ac++, ibmcpp //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) || \
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || defined (__IBMCPP__) || defined (__DECCXX) defined(__IBMCPP__) || defined(__DECCXX)
const Parent * const parent = 0; const Parent * const parent = 0;
const char *const member = reinterpret_cast<const char*>(&(parent->*ptr_to_member)); const char *const member = reinterpret_cast<const char*>(&(parent->*ptr_to_member));
return std::size_t(member - reinterpret_cast<const char*>(parent)); return std::ptrdiff_t(member - reinterpret_cast<const char*>(parent));
#else #else
//This is the traditional C-front approach: __MWERKS__, __DMC__, __SUNPRO_CC //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;
@@ -56,6 +61,10 @@ inline const Parent *parent_from_member(const Member *member, const Member Paren
} //namespace intrusive { } //namespace intrusive {
} //namespace boost { } //namespace boost {
#ifdef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER
#undef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER
#endif
#include <boost/intrusive/detail/config_end.hpp> #include <boost/intrusive/detail/config_end.hpp>
#endif //#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP #endif //#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP

View File

@@ -18,7 +18,7 @@
#include <iterator> #include <iterator>
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/rbtree_algorithms.hpp> #include <boost/intrusive/rbtree_algorithms.hpp>
#include <boost/intrusive/pointer_plus_bit.hpp> #include <boost/intrusive/pointer_plus_bits.hpp>
#include <boost/intrusive/detail/mpl.hpp> #include <boost/intrusive/detail/mpl.hpp>
namespace boost { namespace boost {
@@ -110,7 +110,7 @@ struct compact_rbtree_node_traits_impl
typedef typename boost::pointer_to_other typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr; <VoidPointer, const node>::type const_node_ptr;
typedef pointer_plus_bit<node_ptr> ptr_bit; typedef pointer_plus_bits<node_ptr, 1> ptr_bit;
typedef typename node::color color; typedef typename node::color color;
@@ -133,10 +133,10 @@ struct compact_rbtree_node_traits_impl
{ n->right_ = r; } { n->right_ = r; }
static color get_color(const_node_ptr n) static color get_color(const_node_ptr n)
{ return (color)ptr_bit::get_bit(n->parent_); } { return (color)ptr_bit::get_bits(n->parent_); }
static void set_color(node_ptr n, color c) static void set_color(node_ptr n, color c)
{ ptr_bit::set_bit(n->parent_, c != 0); } { ptr_bit::set_bits(n->parent_, c != 0); }
static color black() static color black()
{ return node::black_t; } { return node::black_t; }
@@ -146,7 +146,7 @@ struct compact_rbtree_node_traits_impl
}; };
//Dispatches the implementation based on the boolean //Dispatches the implementation based on the boolean
template<class VoidPointer, bool compact> template<class VoidPointer, bool Compact>
struct rbtree_node_traits_dispatch struct rbtree_node_traits_dispatch
: public default_rbtree_node_traits_impl<VoidPointer> : public default_rbtree_node_traits_impl<VoidPointer>
{}; {};
@@ -161,11 +161,11 @@ template<class VoidPointer, bool OptimizeSize = false>
struct rbtree_node_traits struct rbtree_node_traits
: public rbtree_node_traits_dispatch : public rbtree_node_traits_dispatch
< VoidPointer < VoidPointer
, OptimizeSize && , OptimizeSize &&
has_pointer_plus_bit (max_pointer_plus_bits
< VoidPointer < VoidPointer
, detail::alignment_of<compact_rbtree_node<VoidPointer> >::value , detail::alignment_of<compact_rbtree_node<VoidPointer> >::value
>::value >::value >= 1)
> >
{}; {};

View File

@@ -18,7 +18,6 @@
#include <iterator> #include <iterator>
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/circular_slist_algorithms.hpp>
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
@@ -78,7 +77,7 @@ class slist_iterator
typedef value_type * pointer; typedef value_type * pointer;
slist_iterator() slist_iterator()
: members_ (0, 0) : members_ (node_ptr(0), 0)
{} {}
explicit slist_iterator(node_ptr node, const Container *cont_ptr) explicit slist_iterator(node_ptr node, const Container *cont_ptr)

View File

@@ -17,7 +17,6 @@
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <cstddef> #include <cstddef>
#include <boost/intrusive/detail/no_exceptions_support.hpp>
#include <boost/intrusive/detail/utilities.hpp> #include <boost/intrusive/detail/utilities.hpp>
namespace boost { namespace boost {
@@ -95,12 +94,8 @@ namespace detail {
template<class NodeTraits> template<class NodeTraits>
class tree_algorithms class tree_algorithms
{ {
/// @cond
private:
typedef typename NodeTraits::node node;
/// @endcond
public: public:
typedef typename NodeTraits::node node;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
@@ -123,6 +118,26 @@ class tree_algorithms
/// @cond /// @cond
private: private:
template<class Disposer>
struct dispose_subtree_disposer
{
dispose_subtree_disposer(Disposer &disp, node_ptr subtree)
: disposer_(&disp), subtree_(subtree)
{}
void release()
{ disposer_ = 0; }
~dispose_subtree_disposer()
{
if(disposer_){
dispose_subtree(subtree_, *disposer_);
}
}
Disposer *disposer_;
node_ptr subtree_;
};
static node_ptr uncast(const_node_ptr ptr) static node_ptr uncast(const_node_ptr ptr)
{ {
return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr))); return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr)));
@@ -505,9 +520,21 @@ class tree_algorithms
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree. //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
static void init(node_ptr node) static void init(node_ptr node)
{ {
NodeTraits::set_parent(node, 0); NodeTraits::set_parent(node, node_ptr(0));
NodeTraits::set_left(node, 0); NodeTraits::set_left(node, node_ptr(0));
NodeTraits::set_right(node, 0); NodeTraits::set_right(node, node_ptr(0));
};
//! <b>Effects</b>: Returns true if node is in the same state as if called init(node)
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr node)
{
return !NodeTraits::get_parent(node) &&
!NodeTraits::get_left(node) &&
!NodeTraits::get_right(node) ;
}; };
//! <b>Requires</b>: node must not be part of any tree. //! <b>Requires</b>: node must not be part of any tree.
@@ -522,7 +549,7 @@ class tree_algorithms
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree. //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
static void init_header(node_ptr header) static void init_header(node_ptr header)
{ {
NodeTraits::set_parent(header, 0); NodeTraits::set_parent(header, node_ptr(0));
NodeTraits::set_left(header, header); NodeTraits::set_left(header, header);
NodeTraits::set_right(header, header); NodeTraits::set_right(header, header);
} }
@@ -565,7 +592,7 @@ class tree_algorithms
{ {
node_ptr leftmost = NodeTraits::get_left(header); node_ptr leftmost = NodeTraits::get_left(header);
if (leftmost == header) if (leftmost == header)
return 0; return node_ptr(0);
node_ptr leftmost_parent(NodeTraits::get_parent(leftmost)); node_ptr leftmost_parent(NodeTraits::get_parent(leftmost));
node_ptr leftmost_right (NodeTraits::get_right(leftmost)); node_ptr leftmost_right (NodeTraits::get_right(leftmost));
bool is_root = leftmost_parent == header; bool is_root = leftmost_parent == header;
@@ -580,12 +607,12 @@ class tree_algorithms
NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right); NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right);
} }
else if (is_root){ else if (is_root){
NodeTraits::set_parent(header, 0); NodeTraits::set_parent(header, node_ptr(0));
NodeTraits::set_left(header, header); NodeTraits::set_left(header, header);
NodeTraits::set_right(header, header); NodeTraits::set_right(header, header);
} }
else{ else{
NodeTraits::set_left(leftmost_parent, 0); NodeTraits::set_left(leftmost_parent, node_ptr(0));
NodeTraits::set_left(header, leftmost_parent); NodeTraits::set_left(header, leftmost_parent);
} }
return leftmost; return leftmost;
@@ -1143,58 +1170,54 @@ class tree_algorithms
node_ptr rightmost = target_sub_root; node_ptr rightmost = target_sub_root;
//First set the subroot //First set the subroot
NodeTraits::set_left(target_sub_root, 0); NodeTraits::set_left(target_sub_root, node_ptr(0));
NodeTraits::set_right(target_sub_root, 0); NodeTraits::set_right(target_sub_root, node_ptr(0));
NodeTraits::set_parent(target_sub_root, target_parent); NodeTraits::set_parent(target_sub_root, target_parent);
try { dispose_subtree_disposer<Disposer> rollback(disposer, target_sub_root);
while(true) { while(true) {
//First clone left nodes //First clone left nodes
if( NodeTraits::get_left(current) && if( NodeTraits::get_left(current) &&
!NodeTraits::get_left(insertion_point)) { !NodeTraits::get_left(insertion_point)) {
current = NodeTraits::get_left(current); current = NodeTraits::get_left(current);
node_ptr temp = insertion_point; node_ptr temp = insertion_point;
//Clone and mark as leaf //Clone and mark as leaf
insertion_point = cloner(current); insertion_point = cloner(current);
NodeTraits::set_left (insertion_point, 0); NodeTraits::set_left (insertion_point, node_ptr(0));
NodeTraits::set_right (insertion_point, 0); NodeTraits::set_right (insertion_point, node_ptr(0));
//Insert left //Insert left
NodeTraits::set_parent(insertion_point, temp); NodeTraits::set_parent(insertion_point, temp);
NodeTraits::set_left (temp, insertion_point); NodeTraits::set_left (temp, insertion_point);
//Update leftmost //Update leftmost
if(rightmost == target_sub_root) if(rightmost == target_sub_root)
leftmost = insertion_point; leftmost = insertion_point;
} }
//Then clone right nodes //Then clone right nodes
else if( NodeTraits::get_right(current) && else if( NodeTraits::get_right(current) &&
!NodeTraits::get_right(insertion_point)){ !NodeTraits::get_right(insertion_point)){
current = NodeTraits::get_right(current); current = NodeTraits::get_right(current);
node_ptr temp = insertion_point; node_ptr temp = insertion_point;
//Clone and mark as leaf //Clone and mark as leaf
insertion_point = cloner(current); insertion_point = cloner(current);
NodeTraits::set_left (insertion_point, 0); NodeTraits::set_left (insertion_point, node_ptr(0));
NodeTraits::set_right (insertion_point, 0); NodeTraits::set_right (insertion_point, node_ptr(0));
//Insert right //Insert right
NodeTraits::set_parent(insertion_point, temp); NodeTraits::set_parent(insertion_point, temp);
NodeTraits::set_right (temp, insertion_point); NodeTraits::set_right (temp, insertion_point);
//Update rightmost //Update rightmost
rightmost = insertion_point; rightmost = insertion_point;
} }
//If not, go up //If not, go up
else if(current == source_root){ else if(current == source_root){
break; break;
} }
else{ else{
//Branch completed, go up searching more nodes to clone //Branch completed, go up searching more nodes to clone
current = NodeTraits::get_parent(current); current = NodeTraits::get_parent(current);
insertion_point = NodeTraits::get_parent(insertion_point); insertion_point = NodeTraits::get_parent(insertion_point);
}
} }
} }
catch(...) { rollback.release();
dispose_subtree(target_sub_root, disposer);
throw;
}
leftmost_out = leftmost; leftmost_out = leftmost;
rightmost_out = rightmost; rightmost_out = rightmost;
} }
@@ -1321,8 +1344,8 @@ class tree_algorithms
NodeTraits::set_right(header, z); NodeTraits::set_right(header, z);
} }
NodeTraits::set_parent(z, par); NodeTraits::set_parent(z, par);
NodeTraits::set_right(z, 0); NodeTraits::set_right(z, node_ptr(0));
NodeTraits::set_left(z, 0); NodeTraits::set_left(z, node_ptr(0));
} }
static void erase(node_ptr header, node_ptr z) static void erase(node_ptr header, node_ptr z)
@@ -1384,7 +1407,7 @@ class tree_algorithms
{ {
std::size_t len; std::size_t len;
len = 0; len = 0;
if(!old_root) return 0; if(!old_root) return node_ptr(0);
//To avoid irregularities in the algorithm (old_root can be a //To avoid irregularities in the algorithm (old_root can be a
//left or right child or even the root of the tree) just put the //left or right child or even the root of the tree) just put the
@@ -1392,8 +1415,8 @@ class tree_algorithms
//information to restore the original relationship after //information to restore the original relationship after
//the algorithm is applied. //the algorithm is applied.
node_ptr super_root = NodeTraits::get_parent(old_root); node_ptr super_root = NodeTraits::get_parent(old_root);
assert(super_root); BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
//Get info //Get info
node_ptr super_root_right_backup = NodeTraits::get_right(super_root); node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
bool super_root_is_header = is_header(super_root); bool super_root_is_header = is_header(super_root);
@@ -1464,7 +1487,7 @@ class tree_algorithms
//information to restore the original relationship after //information to restore the original relationship after
//the algorithm is applied. //the algorithm is applied.
node_ptr super_root = NodeTraits::get_parent(old_root); node_ptr super_root = NodeTraits::get_parent(old_root);
assert(super_root); BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
//Get info //Get info
node_ptr super_root_right_backup = NodeTraits::get_right(super_root); node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
@@ -1511,6 +1534,28 @@ class tree_algorithms
return new_root; return new_root;
} }
//! <b>Requires</b>: "n" must be a node inserted in a tree.
//!
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
//!
//! <b>Complexity</b>: Logarithmic.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_root(node_ptr node)
{
BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node)));
node_ptr x = NodeTraits::get_parent(node);
if(x){
while(!is_header(x)){
x = NodeTraits::get_parent(x);
}
return x;
}
else{
return node;
}
}
private: private:
static void erase_impl(node_ptr header, node_ptr z, data_for_rebalance &info) static void erase_impl(node_ptr header, node_ptr z, data_for_rebalance &info)
{ {
@@ -1569,7 +1614,6 @@ class tree_algorithms
info.x_parent = x_parent; info.x_parent = x_parent;
info.y = y; info.y = y;
} }
}; };
} //namespace detail { } //namespace detail {

View File

@@ -168,6 +168,11 @@ class tree_iterator
return 0; return 0;
} }
tree_iterator end_iterator_from_it() const
{
return tree_iterator(node_algorithms::get_header(this->pointed_node()), this->get_container());
}
private: private:
struct members struct members
: public detail::select_constptr : public detail::select_constptr

View File

@@ -25,6 +25,7 @@
#include <climits> #include <climits>
#include <iterator> #include <iterator>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
@@ -55,6 +56,24 @@ struct internal_base_hook_bool_is_true
static const bool value = internal_base_hook_bool<T>::value > sizeof(one)*2; static const bool value = internal_base_hook_bool<T>::value > sizeof(one)*2;
}; };
template <class T>
struct internal_any_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::is_any_hook>
test (detail::bool_<U::is_any_hook>* = 0);
static const std::size_t value = sizeof(test<T>(0));
};
template <class T>
struct internal_any_hook_bool_is_true
{
static const bool value = internal_any_hook_bool<T>::value > sizeof(one)*2;
};
template <class T> template <class T>
struct external_value_traits_bool struct external_value_traits_bool
{ {
@@ -235,16 +254,9 @@ struct node_cloner
node_cloner(F f, const Container *cont) node_cloner(F f, const Container *cont)
: base_t(f), cont_(cont) : base_t(f), cont_(cont)
{} {}
node_ptr operator()(node_ptr p) node_ptr operator()(node_ptr p)
{ { return this->operator()(*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) node_ptr operator()(const node &to_clone)
{ {
@@ -396,16 +408,20 @@ template <link_mode_type LinkMode>
struct link_dispatch struct link_dispatch
{}; {};
template<class Container> template<class Hook>
void destructor_impl(Container &cont, detail::link_dispatch<safe_link>) void destructor_impl(Hook &hook, detail::link_dispatch<safe_link>)
{ (void)cont; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!cont.is_linked()); } { //If this assertion raises, you might have destroyed an object
//while it was still inserted in a container that is alive.
//If so, remove the object from the container before destroying it.
(void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked());
}
template<class Container> template<class Hook>
void destructor_impl(Container &cont, detail::link_dispatch<auto_unlink>) void destructor_impl(Hook &hook, detail::link_dispatch<auto_unlink>)
{ cont.unlink(); } { hook.unlink(); }
template<class Container> template<class Hook>
void destructor_impl(Container &, detail::link_dispatch<normal_link>) void destructor_impl(Hook &, detail::link_dispatch<normal_link>)
{} {}
template<class T, class NodeTraits, link_mode_type LinkMode, class Tag, int HookType> template<class T, class NodeTraits, link_mode_type LinkMode, class Tag, int HookType>
@@ -548,6 +564,62 @@ inline std::size_t sqrt2_pow_2xplus1 (std::size_t x)
return (value >> (pow - x)) + 1; return (value >> (pow - x)) + 1;
} }
template<class Container, class Disposer>
class exception_disposer
{
Container *cont_;
Disposer &disp_;
exception_disposer(const exception_disposer&);
exception_disposer &operator=(const exception_disposer&);
public:
exception_disposer(Container &cont, Disposer &disp)
: cont_(&cont), disp_(disp)
{}
void release()
{ cont_ = 0; }
~exception_disposer()
{
if(cont_){
cont_->clear_and_dispose(disp_);
}
}
};
template<class Container, class Disposer>
class exception_array_disposer
{
Container *cont_;
Disposer &disp_;
typename Container::size_type &constructed_;
exception_array_disposer(const exception_array_disposer&);
exception_array_disposer &operator=(const exception_array_disposer&);
public:
typedef typename Container::size_type size_type;
exception_array_disposer
(Container &cont, Disposer &disp, size_type &constructed)
: cont_(&cont), disp_(disp), constructed_(constructed)
{}
void release()
{ cont_ = 0; }
~exception_array_disposer()
{
size_type n = constructed_;
if(cont_){
while(n--){
cont_[n].clear_and_dispose(disp_);
}
}
}
};
} //namespace detail } //namespace detail
} //namespace intrusive } //namespace intrusive
} //namespace boost } //namespace boost

File diff suppressed because it is too large Load Diff

View File

@@ -283,8 +283,7 @@ template
> >
class bs_set_member_hook; class bs_set_member_hook;
//hash/unordered //hashtable/unordered_set/unordered_multiset
//rbtree/set/multiset
template template
< class T < class T
, class O1 = none , class O1 = none
@@ -294,6 +293,8 @@ template
, class O5 = none , class O5 = none
, class O6 = none , class O6 = none
, class O7 = none , class O7 = none
, class O8 = none
, class O9 = none
> >
class hashtable; class hashtable;
@@ -306,6 +307,8 @@ template
, class O5 = none , class O5 = none
, class O6 = none , class O6 = none
, class O7 = none , class O7 = none
, class O8 = none
, class O9 = none
> >
class unordered_set; class unordered_set;
@@ -318,6 +321,8 @@ template
, class O5 = none , class O5 = none
, class O6 = none , class O6 = none
, class O7 = none , class O7 = none
, class O8 = none
, class O9 = none
> >
class unordered_multiset; class unordered_multiset;
@@ -337,6 +342,20 @@ template
> >
class unordered_set_member_hook; class unordered_set_member_hook;
template
< class O1 = none
, class O2 = none
, class O3 = none
>
class any_base_hook;
template
< class O1 = none
, class O2 = none
, class O3 = none
>
class any_member_hook;
} //namespace intrusive { } //namespace intrusive {
} //namespace boost { } //namespace boost {

View File

@@ -53,6 +53,7 @@ class linear_slist_algorithms
typedef detail::common_slist_algorithms<NodeTraits> base_t; typedef detail::common_slist_algorithms<NodeTraits> base_t;
/// @endcond /// @endcond
public: public:
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
@@ -136,7 +137,7 @@ class linear_slist_algorithms
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static void init_header(node_ptr this_node) static void init_header(node_ptr this_node)
{ NodeTraits::set_next(this_node, 0); } { NodeTraits::set_next(this_node, node_ptr(0)); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same linear list. //! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
//! //!
@@ -195,7 +196,7 @@ class linear_slist_algorithms
//! <b>Complexity</b>: This function is linear to the contained elements. //! <b>Complexity</b>: This function is linear to the contained elements.
static node_ptr reverse(node_ptr p) static node_ptr reverse(node_ptr p)
{ {
if(!p) return 0; if(!p) return node_ptr(0);
node_ptr i = NodeTraits::get_next(p); node_ptr i = NodeTraits::get_next(p);
node_ptr first(p); node_ptr first(p);
while(i){ while(i){
@@ -218,7 +219,7 @@ class linear_slist_algorithms
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static std::pair<node_ptr, node_ptr> move_first_n_backwards(node_ptr p, std::size_t n) static std::pair<node_ptr, node_ptr> move_first_n_backwards(node_ptr p, std::size_t n)
{ {
std::pair<node_ptr, node_ptr> ret(0, 0); std::pair<node_ptr, node_ptr> ret(node_ptr(0), node_ptr(0));
//Null shift, or count() == 0 or 1, nothing to do //Null shift, or count() == 0 or 1, nothing to do
if(!n || !p || !NodeTraits::get_next(p)){ if(!n || !p || !NodeTraits::get_next(p)){
return ret; return ret;
@@ -252,12 +253,12 @@ class linear_slist_algorithms
//If the p has not been found in the previous loop, find it //If the p has not been found in the previous loop, find it
//starting in the new first node and unlink it //starting in the new first node and unlink it
if(!end_found){ if(!end_found){
old_last = base_t::get_previous_node(first, 0); old_last = base_t::get_previous_node(first, node_ptr(0));
} }
//Now link p after the new last node //Now link p after the new last node
NodeTraits::set_next(old_last, p); NodeTraits::set_next(old_last, p);
NodeTraits::set_next(new_last, 0); NodeTraits::set_next(new_last, node_ptr(0));
ret.first = first; ret.first = first;
ret.second = new_last; ret.second = new_last;
return ret; return ret;
@@ -273,7 +274,7 @@ class linear_slist_algorithms
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static std::pair<node_ptr, node_ptr> move_first_n_forward(node_ptr p, std::size_t n) static std::pair<node_ptr, node_ptr> move_first_n_forward(node_ptr p, std::size_t n)
{ {
std::pair<node_ptr, node_ptr> ret(0, 0); std::pair<node_ptr, node_ptr> ret(node_ptr(0), node_ptr(0));
//Null shift, or count() == 0 or 1, nothing to do //Null shift, or count() == 0 or 1, nothing to do
if(!n || !p || !NodeTraits::get_next(p)) if(!n || !p || !NodeTraits::get_next(p))
return ret; return ret;
@@ -311,7 +312,7 @@ class linear_slist_algorithms
node_ptr new_first(node_traits::get_next(new_last)); node_ptr new_first(node_traits::get_next(new_last));
//Now put the old beginning after the old end //Now put the old beginning after the old end
NodeTraits::set_next(old_last, p); NodeTraits::set_next(old_last, p);
NodeTraits::set_next(new_last, 0); NodeTraits::set_next(new_last, node_ptr(0));
ret.first = new_first; ret.first = new_first;
ret.second = new_last; ret.second = new_last;
return ret; return ret;

View File

@@ -24,7 +24,7 @@
#include <boost/intrusive/link_mode.hpp> #include <boost/intrusive/link_mode.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/intrusive/options.hpp> #include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/no_exceptions_support.hpp> #include <boost/intrusive/detail/utilities.hpp>
#include <iterator> #include <iterator>
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
@@ -586,7 +586,7 @@ class list_impl
iterator erase(iterator i) iterator erase(iterator i)
{ return this->erase_and_dispose(i, detail::null_disposer()); } { return this->erase_and_dispose(i, detail::null_disposer()); }
//! <b>Requires</b>: first and last must be valid iterator to elements in *this. //! <b>Requires</b>: b and e must be valid iterators to elements in *this.
//! //!
//! <b>Effects</b>: Erases the element range pointed by b and e //! <b>Effects</b>: Erases the element range pointed by b and e
//! No destructors are called. //! No destructors are called.
@@ -596,8 +596,8 @@ class list_impl
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements erased if it's a safe-mode //! <b>Complexity</b>: Linear to the number of erased elements if it's a safe-mode
//! or auto-unlink value. Constant time otherwise. //! or auto-unlink value, or constant-time size is enabled. Constant-time otherwise.
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the //! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased elements. //! erased elements.
@@ -612,6 +612,37 @@ class list_impl
} }
} }
//! <b>Requires</b>: b and e must be valid iterators to elements in *this.
//! n must be std::distance(b, e).
//!
//! <b>Effects</b>: Erases the element range pointed by b and e
//! No destructors are called.
//!
//! <b>Returns</b>: the first element remaining beyond the removed elements,
//! or end() if no such element exists.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of erased elements if it's a safe-mode
//! or auto-unlink value is enabled. Constant-time otherwise.
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased elements.
iterator erase(iterator b, iterator e, difference_type n)
{
BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(b, e) == difference_type(n));
if(safemode_or_autounlink || constant_time_size){
return this->erase_and_dispose(b, e, detail::null_disposer());
}
else{
if(constant_time_size){
this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n);
}
node_algorithms::unlink(b.pointed_node(), e.pointed_node());
return e;
}
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
//! <b>Effects</b>: Erases the element pointed by i of the list. //! <b>Effects</b>: Erases the element pointed by i of the list.
@@ -732,17 +763,13 @@ class list_impl
void clone_from(const list_impl &src, Cloner cloner, Disposer disposer) void clone_from(const list_impl &src, Cloner cloner, Disposer disposer)
{ {
this->clear_and_dispose(disposer); this->clear_and_dispose(disposer);
BOOST_INTRUSIVE_TRY{ detail::exception_disposer<list_impl, Disposer>
const_iterator b(src.begin()), e(src.end()); rollback(*this, disposer);
for(; b != e; ++b){ const_iterator b(src.begin()), e(src.end());
this->push_back(*cloner(*b)); for(; b != e; ++b){
} this->push_back(*cloner(*b));
} }
BOOST_INTRUSIVE_CATCH(...){ rollback.release();
this->clear_and_dispose(disposer);
BOOST_INTRUSIVE_RETHROW;
}
BOOST_INTRUSIVE_CATCH_END
} }
//! <b>Requires</b>: value must be an lvalue and p must be a valid iterator of *this. //! <b>Requires</b>: value must be an lvalue and p must be a valid iterator of *this.

View File

@@ -49,15 +49,56 @@ struct eval_bucket_traits
typedef typename BucketTraits::bucket_traits type; typedef typename BucketTraits::bucket_traits type;
}; };
template <class T, class BaseHook>
struct concrete_hook_base_value_traits
{
typedef typename BaseHook::boost_intrusive_tags tags;
typedef detail::base_hook_traits
< T
, typename tags::node_traits
, tags::link_mode
, typename tags::tag
, tags::hook_type> type;
};
template <class BaseHook>
struct concrete_hook_base_node_traits
{ typedef typename BaseHook::boost_intrusive_tags::node_traits type; };
template <class T, class BaseHook>
struct any_hook_base_value_traits
{
typedef typename BaseHook::boost_intrusive_tags tags;
typedef detail::base_hook_traits
< T
, typename BaseHook::node_traits
, tags::link_mode
, typename tags::tag
, tags::hook_type> type;
};
template <class BaseHook>
struct any_hook_base_node_traits
{ typedef typename BaseHook::node_traits type; };
template<class T, class BaseHook> template<class T, class BaseHook>
struct get_base_value_traits struct get_base_value_traits
{ {
typedef detail::base_hook_traits typedef typename detail::eval_if_c
< T < internal_any_hook_bool_is_true<BaseHook>::value
, typename BaseHook::boost_intrusive_tags::node_traits , any_hook_base_value_traits<T, BaseHook>
, BaseHook::boost_intrusive_tags::link_mode , concrete_hook_base_value_traits<T, BaseHook>
, typename BaseHook::boost_intrusive_tags::tag >::type type;
, BaseHook::boost_intrusive_tags::hook_type> type; };
template<class BaseHook>
struct get_base_node_traits
{
typedef typename detail::eval_if_c
< internal_any_hook_bool_is_true<BaseHook>::value
, any_hook_base_node_traits<BaseHook>
, concrete_hook_base_node_traits<BaseHook>
>::type type;
}; };
template<class T, class MemberHook> template<class T, class MemberHook>
@@ -66,6 +107,12 @@ struct get_member_value_traits
typedef typename MemberHook::member_value_traits type; typedef typename MemberHook::member_value_traits type;
}; };
template<class MemberHook>
struct get_member_node_traits
{
typedef typename MemberHook::member_value_traits::node_traits type;
};
template<class T, class SupposedValueTraits> template<class T, class SupposedValueTraits>
struct get_value_traits struct get_value_traits
{ {
@@ -86,25 +133,12 @@ struct get_value_traits
>::type type; >::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> template<class ValueTraits>
struct get_explicit_node_traits struct get_explicit_node_traits
{ {
typedef typename ValueTraits::node_traits type; typedef typename ValueTraits::node_traits type;
}; };
template<class SupposedValueTraits> template<class SupposedValueTraits>
struct get_node_traits struct get_node_traits
{ {
@@ -125,7 +159,6 @@ struct get_node_traits
>::type type; >::type type;
}; };
} //namespace detail{ } //namespace detail{
@@ -258,7 +291,6 @@ template< typename Parent
struct member_hook struct member_hook
{ {
/// @cond /// @cond
typedef char Parent::* GenericPtrToMember;
typedef detail::member_hook_traits typedef detail::member_hook_traits
< Parent < Parent
, MemberHook , MemberHook
@@ -272,6 +304,7 @@ struct member_hook
/// @endcond /// @endcond
}; };
//!This option setter specifies that the container //!This option setter specifies that the container
//!must use the specified base hook //!must use the specified base hook
template<typename BaseHook> template<typename BaseHook>
@@ -406,6 +439,24 @@ struct store_hash
/// @endcond /// @endcond
}; };
//!This option setter specifies if the unordered hook
//!should offer room to store another link to another node
//!with the same key.
//!Storing this link will speed up lookups and insertions on
//!unordered_multiset containers with a great number of elements
//!with the same key.
template<bool Enabled>
struct optimize_multikey
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool optimize_multikey = Enabled;
};
/// @endcond
};
//!This option setter specifies if the bucket array will be always power of two. //!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 //!This allows using masks instead of the default modulo operation to determine
//!the bucket number from the hash value, leading to better performance. //!the bucket number from the hash value, leading to better performance.
@@ -423,6 +474,41 @@ struct power_2_buckets
/// @endcond /// @endcond
}; };
//!This option setter specifies if the container will cache a pointer to the first
//!non-empty bucket so that begin() is always constant-time.
//!This is specially helpful when we can have containers with a few elements
//!but with big bucket arrays (that is, hashtables with low load factors).
template<bool Enabled>
struct cache_begin
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool cache_begin = Enabled;
};
/// @endcond
};
//!This option setter specifies if the container will compare the hash value
//!before comparing objects. This option can't be specified if store_hash<>
//!is not true.
//!This is specially helpful when we have containers with a high load factor.
//!and the comparison function is much more expensive that comparing already
//!stored hash values.
template<bool Enabled>
struct compare_hash
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool compare_hash = Enabled;
};
/// @endcond
};
/// @cond /// @cond
template<class Prev, class Next> template<class Prev, class Next>
@@ -500,6 +586,7 @@ struct hook_defaults
, optimize_size<false> , optimize_size<false>
, store_hash<false> , store_hash<false>
, linear<false> , linear<false>
, optimize_multikey<false>
>::type >::type
{}; {};

View File

@@ -1,82 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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_POINTER_PLUS_2_BIT_HPP
#define BOOST_INTRUSIVE_POINTER_PLUS_2_BIT_HPP
namespace boost {
namespace intrusive {
//!This trait class is used to know if a pointer
//!can embed 2 extra bits of information if
//!it's going to be used to point to objects
//!with an alignment of "Alignment" bytes.
template<class VoidPointer, std::size_t Alignment>
struct has_pointer_plus_2_bits
{
static const bool value = false;
};
//!This is an specialization for raw pointers.
//!Raw pointers can embed two extra bits in the lower bits
//!if the alignment is multiple of 4.
template<std::size_t N>
struct has_pointer_plus_2_bits<void*, N>
{
static const bool value = (N % 4u == 0);
};
//!This is class that is supposed to have static methods
//!to embed 2 extra bits of information in a pointer.
//!
//!This is a declaration and there is no default implementation,
//!because operations to embed bits change with every pointer type.
//!
//!An implementation that detects that a pointer type whose
//!has_pointer_plus_2_bits<>::value is non-zero can make use of these
//!operations to embed bits in the pointer.
template<class Pointer>
struct pointer_plus_2_bits
{
static const bool value = false;
};
//!This is the specialization to embed 2 extra bits of information
//!in a raw pointer. Extra bits are stored in the lower bits of the pointer.
template<class T>
struct pointer_plus_2_bits<T*>
{
typedef T* pointer;
static pointer get_pointer(pointer n)
{ return pointer(std::size_t(n) & ~std::size_t(3u)); }
static void set_pointer(pointer &n, pointer p)
{
assert(0 == (std::size_t(p) & std::size_t(3u)));
n = pointer(std::size_t(p) | (std::size_t(n) & std::size_t(3u)));
}
static std::size_t get_bits(pointer n)
{ return (std::size_t(n) & std::size_t(3u)); }
static void set_bits(pointer &n, std::size_t c)
{
assert(c < 4);
n = pointer(std::size_t(get_pointer(n)) | c);
}
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_POINTER_PLUS_2_BIT_HPP

View File

@@ -1,78 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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_POINTER_PLUS_BIT_HPP
#define BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
namespace boost {
namespace intrusive {
//!This trait class is used to know if a pointer
//!can embed an extra bit of information if
//!it's going to be used to point to objects
//!with an alignment of "Alignment" bytes.
template<class VoidPointer, std::size_t Alignment>
struct has_pointer_plus_bit
{
static const bool value = false;
};
//!This is an specialization for raw pointers.
//!Raw pointers can embed an extra bit in the lower bit
//!if the alignment is multiple of 2.
template<std::size_t N>
struct has_pointer_plus_bit<void*, N>
{
static const bool value = (N % 2u == 0);
};
//!This is class that is supposed to have static methods
//!to embed an extra bit of information in a pointer.
//!This is a declaration and there is no default implementation,
//!because operations to embed the bit change with every pointer type.
//!
//!An implementation that detects that a pointer type whose
//!has_pointer_plus_bit<>::value is non-zero can make use of these
//!operations to embed the bit in the pointer.
template<class Pointer>
struct pointer_plus_bit
{
static const bool value = false;
};
//!This is the specialization to embed an extra bit of information
//!in a raw pointer. The extra bit is stored in the lower bit of the pointer.
template<class T>
struct pointer_plus_bit<T*>
{
typedef T* pointer;
static pointer get_pointer(pointer n)
{ return pointer(std::size_t(n) & ~std::size_t(1u)); }
static void set_pointer(pointer &n, pointer p)
{
assert(0 == (std::size_t(p) & std::size_t(1u)));
n = pointer(std::size_t(p) | (std::size_t(n) & std::size_t(1u)));
}
static bool get_bit(pointer n)
{ return (std::size_t(n) & std::size_t(1u)) != 0; }
static void set_bit(pointer &n, bool c)
{ n = pointer(std::size_t(get_pointer(n)) | std::size_t(c)); }
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP

View File

@@ -0,0 +1,81 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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_POINTER_PLUS_BITS_HPP
#define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
#include <boost/intrusive/detail/mpl.hpp> //ls_zeros
namespace boost {
namespace intrusive {
//!This trait class is used to know if a pointer
//!can embed extra bits of information if
//!it's going to be used to point to objects
//!with an alignment of "Alignment" bytes.
template<class VoidPointer, std::size_t Alignment>
struct max_pointer_plus_bits
{
static const std::size_t value = 0;
};
//!This is an specialization for raw pointers.
//!Raw pointers can embed extra bits in the lower bits
//!if the alignment is multiple of 2pow(NumBits).
template<std::size_t Alignment>
struct max_pointer_plus_bits<void*, Alignment>
{
static const std::size_t value = detail::ls_zeros<Alignment>::value;
};
//!This is class that is supposed to have static methods
//!to embed extra bits of information in a pointer.
//!This is a declaration and there is no default implementation,
//!because operations to embed the bits change with every pointer type.
//!
//!An implementation that detects that a pointer type whose
//!has_pointer_plus_bits<>::value is non-zero can make use of these
//!operations to embed the bits in the pointer.
template<class Pointer, std::size_t NumBits>
struct pointer_plus_bits;
//!This is the specialization to embed extra bits of information
//!in a raw pointer. The extra bits are stored in the lower bit of the pointer.
template<class T, std::size_t NumBits>
struct pointer_plus_bits<T*, NumBits>
{
static const std::size_t Mask = ((std::size_t(1u) << NumBits) - 1);
typedef T* pointer;
static pointer get_pointer(pointer n)
{ return pointer(std::size_t(n) & ~Mask); }
static void set_pointer(pointer &n, pointer p)
{
assert(0 == (std::size_t(p) & Mask));
n = pointer(std::size_t(p) | (std::size_t(n) & Mask));
}
static std::size_t get_bits(pointer n)
{ return (std::size_t(n) & Mask); }
static void set_bits(pointer &n, std::size_t c)
{
assert(c <= Mask);
n = pointer(std::size_t(get_pointer(n)) | c);
}
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP

View File

@@ -379,7 +379,7 @@ class rbtree_impl
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
//! of rbtree. //! of rbtree.
//! //!
//! <b>Effects</b>: Returns a const reference to the rbtree associated to the end iterator //! <b>Effects</b>: Returns a const reference to the rbtree associated to the iterator
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
@@ -387,6 +387,28 @@ class rbtree_impl
static const rbtree_impl &container_from_end_iterator(const_iterator end_iterator) static const rbtree_impl &container_from_end_iterator(const_iterator end_iterator)
{ return priv_container_from_end_iterator(end_iterator); } { return priv_container_from_end_iterator(end_iterator); }
//! <b>Precondition</b>: it must be a valid iterator
//! of rbtree.
//!
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static rbtree_impl &container_from_iterator(iterator it)
{ return priv_container_from_iterator(it); }
//! <b>Precondition</b>: it must be a valid end const_iterator
//! of rbtree.
//!
//! <b>Effects</b>: Returns a const reference to the tree associated to the end iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const rbtree_impl &container_from_iterator(const_iterator it)
{ return priv_container_from_iterator(it); }
//! <b>Effects</b>: Returns the value_compare object used by the tree. //! <b>Effects</b>: Returns the value_compare object used by the tree.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1176,33 +1198,26 @@ class rbtree_impl
static void init_node(reference value) static void init_node(reference value)
{ node_algorithms::init(value_traits::to_node_ptr(value)); } { node_algorithms::init(value_traits::to_node_ptr(value)); }
/* //! <b>Effects</b>: removes "value" from the container.
//! <b>Effects</b>: removes x from a tree of the appropriate type. It has no effect,
//! if x is not in such a tree.
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Constant time. //! <b>Complexity</b>: Logarithmic time.
//! //!
//! <b>Note</b>: This static function is only usable with the "safe mode" //! <b>Note</b>: This static function is only usable with non-constant
//! hook and non-constant time size lists. Otherwise, the user must use //! time size containers that have stateless comparison functors.
//! the non-static "erase(reference )" member. If the user calls //!
//! this function with a non "safe mode" or constant time size list //! If the user calls
//! a compilation error will be issued. //! this function with a constant time size container or stateful comparison
template<class T> //! functor a compilation error will be issued.
static void remove_node(T& value) static void remove_node(reference value)
{ {
//This function is only usable for safe mode hooks and non-constant
//time lists.
//BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size)));
BOOST_STATIC_ASSERT((!constant_time_size)); BOOST_STATIC_ASSERT((!constant_time_size));
BOOST_STATIC_ASSERT((boost::is_convertible<T, value_type>::value));
node_ptr to_remove(value_traits::to_node_ptr(value)); node_ptr to_remove(value_traits::to_node_ptr(value));
node_algorithms::unlink_and_rebalance(to_remove); node_algorithms::unlink(to_remove);
if(safemode_or_autounlink) if(safemode_or_autounlink)
node_algorithms::init(to_remove); node_algorithms::init(to_remove);
} }
*/
/// @cond /// @cond
private: private:
@@ -1233,6 +1248,9 @@ class rbtree_impl
rbtree_impl *rb = detail::parent_from_member<rbtree_impl, data_t>(d, &rbtree_impl::data_); rbtree_impl *rb = detail::parent_from_member<rbtree_impl, data_t>(d, &rbtree_impl::data_);
return *rb; return *rb;
} }
static rbtree_impl &priv_container_from_iterator(const const_iterator &it)
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
}; };
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
@@ -1426,6 +1444,12 @@ class rbtree
static const rbtree &container_from_end_iterator(const_iterator end_iterator) static const rbtree &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const rbtree &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const rbtree &>(Base::container_from_end_iterator(end_iterator)); }
static rbtree &container_from_it(iterator it)
{ return static_cast<rbtree &>(Base::container_from_iterator(it)); }
static const rbtree &container_from_it(const_iterator it)
{ return static_cast<const rbtree &>(Base::container_from_iterator(it)); }
}; };
#endif #endif

View File

@@ -54,7 +54,6 @@
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/no_exceptions_support.hpp>
#include <boost/intrusive/detail/utilities.hpp> #include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/tree_algorithms.hpp> #include <boost/intrusive/detail/tree_algorithms.hpp>
@@ -117,6 +116,7 @@ class rbtree_algorithms
{ {
public: public:
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef typename NodeTraits::color color; typedef typename NodeTraits::color color;
@@ -124,7 +124,6 @@ class rbtree_algorithms
/// @cond /// @cond
private: private:
typedef typename NodeTraits::node node;
typedef detail::tree_algorithms<NodeTraits> tree_algorithms; typedef detail::tree_algorithms<NodeTraits> tree_algorithms;
template<class F> template<class F>
@@ -695,6 +694,16 @@ class rbtree_algorithms
rebalance_after_insertion(header, new_value); rebalance_after_insertion(header, new_value);
} }
//! <b>Requires</b>: "n" must be a node inserted in a tree.
//!
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
//!
//! <b>Complexity</b>: Logarithmic.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_header(node_ptr n)
{ return tree_algorithms::get_header(n); }
/// @cond /// @cond
private: private:

View File

@@ -226,7 +226,7 @@ class set_impl
//! <b>Precondition</b>: end_iterator must be a valid end iterator //! <b>Precondition</b>: end_iterator must be a valid end iterator
//! of set. //! of set.
//! //!
//! <b>Effects</b>: Returns a const reference to the set associated to the end iterator //! <b>Effects</b>: Returns a reference to the set associated to the end iterator
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
@@ -253,6 +253,34 @@ class set_impl
, &set_impl::tree_); , &set_impl::tree_);
} }
//! <b>Precondition</b>: it must be a valid iterator of set.
//!
//! <b>Effects</b>: Returns a reference to the set associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static set_impl &container_from_iterator(iterator it)
{
return *detail::parent_from_member<set_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &set_impl::tree_);
}
//! <b>Precondition</b>: it must be a valid const_iterator of set.
//!
//! <b>Effects</b>: Returns a const reference to the set associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const set_impl &container_from_iterator(const_iterator it)
{
return *detail::parent_from_member<set_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &set_impl::tree_);
}
//! <b>Effects</b>: Returns the key_compare object used by the set. //! <b>Effects</b>: Returns the key_compare object used by the set.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1086,6 +1114,12 @@ class set
static const set &container_from_end_iterator(const_iterator end_iterator) static const set &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const set &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const set &>(Base::container_from_end_iterator(end_iterator)); }
static set &container_from_iterator(iterator it)
{ return static_cast<set &>(Base::container_from_iterator(it)); }
static const set &container_from_iterator(const_iterator it)
{ return static_cast<const set &>(Base::container_from_iterator(it)); }
}; };
#endif #endif
@@ -1318,6 +1352,34 @@ class multiset_impl
, &multiset_impl::tree_); , &multiset_impl::tree_);
} }
//! <b>Precondition</b>: it must be a valid iterator of multiset.
//!
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
static multiset_impl &container_from_iterator(iterator it)
{
return *detail::parent_from_member<multiset_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &multiset_impl::tree_);
}
//! <b>Precondition</b>: it must be a valid const_iterator of multiset.
//!
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
static const multiset_impl &container_from_iterator(const_iterator it)
{
return *detail::parent_from_member<multiset_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &multiset_impl::tree_);
}
//! <b>Effects</b>: Returns the key_compare object used by the multiset. //! <b>Effects</b>: Returns the key_compare object used by the multiset.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1932,6 +1994,21 @@ class multiset_impl
void replace_node(iterator replace_this, reference with_this) void replace_node(iterator replace_this, reference with_this)
{ tree_.replace_node(replace_this, with_this); } { tree_.replace_node(replace_this, with_this); }
//! <b>Effects</b>: removes "value" from the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic time.
//!
//! <b>Note</b>: This static function is only usable with non-constant
//! time size containers that have stateless comparison functors.
//!
//! If the user calls
//! this function with a constant time size container or stateful comparison
//! functor a compilation error will be issued.
static void remove_node(reference value)
{ tree_type::remove_node(value); }
/// @cond /// @cond
friend bool operator==(const multiset_impl &x, const multiset_impl &y) friend bool operator==(const multiset_impl &x, const multiset_impl &y)
{ return x.tree_ == y.tree_; } { return x.tree_ == y.tree_; }
@@ -2058,6 +2135,12 @@ class multiset
static const multiset &container_from_end_iterator(const_iterator end_iterator) static const multiset &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const multiset &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const multiset &>(Base::container_from_end_iterator(end_iterator)); }
static multiset &container_from_iterator(iterator it)
{ return static_cast<multiset &>(Base::container_from_iterator(it)); }
static const multiset &container_from_iterator(const_iterator it)
{ return static_cast<const multiset &>(Base::container_from_iterator(it)); }
}; };
#endif #endif

View File

@@ -252,6 +252,34 @@ class sg_set_impl
, &sg_set_impl::tree_); , &sg_set_impl::tree_);
} }
//! <b>Precondition</b>: it must be a valid iterator of set.
//!
//! <b>Effects</b>: Returns a reference to the set associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static sg_set_impl &container_from_iterator(iterator it)
{
return *detail::parent_from_member<sg_set_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &sg_set_impl::tree_);
}
//! <b>Precondition</b>: it must be a valid const_iterator of set.
//!
//! <b>Effects</b>: Returns a const reference to the set associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const sg_set_impl &container_from_iterator(const_iterator it)
{
return *detail::parent_from_member<sg_set_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &sg_set_impl::tree_);
}
//! <b>Effects</b>: Returns the key_compare object used by the sg_set. //! <b>Effects</b>: Returns the key_compare object used by the sg_set.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1124,6 +1152,12 @@ class sg_set
static const sg_set &container_from_end_iterator(const_iterator end_iterator) static const sg_set &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const sg_set &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const sg_set &>(Base::container_from_end_iterator(end_iterator)); }
static sg_set &container_from_iterator(iterator it)
{ return static_cast<sg_set &>(Base::container_from_iterator(it)); }
static const sg_set &container_from_iterator(const_iterator it)
{ return static_cast<const sg_set &>(Base::container_from_iterator(it)); }
}; };
#endif #endif
@@ -1356,6 +1390,34 @@ class sg_multiset_impl
, &sg_multiset_impl::tree_); , &sg_multiset_impl::tree_);
} }
//! <b>Precondition</b>: it must be a valid iterator of multiset.
//!
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
static sg_multiset_impl &container_from_iterator(iterator it)
{
return *detail::parent_from_member<sg_multiset_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &sg_multiset_impl::tree_);
}
//! <b>Precondition</b>: it must be a valid const_iterator of multiset.
//!
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
static const sg_multiset_impl &container_from_iterator(const_iterator it)
{
return *detail::parent_from_member<sg_multiset_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &sg_multiset_impl::tree_);
}
//! <b>Effects</b>: Returns the key_compare object used by the sg_multiset. //! <b>Effects</b>: Returns the key_compare object used by the sg_multiset.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -2135,6 +2197,12 @@ class sg_multiset
static const sg_multiset &container_from_end_iterator(const_iterator end_iterator) static const sg_multiset &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const sg_multiset &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const sg_multiset &>(Base::container_from_end_iterator(end_iterator)); }
static sg_multiset &container_from_iterator(iterator it)
{ return static_cast<sg_multiset &>(Base::container_from_iterator(it)); }
static const sg_multiset &container_from_iterator(const_iterator it)
{ return static_cast<const sg_multiset &>(Base::container_from_iterator(it)); }
}; };
#endif #endif

View File

@@ -527,6 +527,28 @@ class sgtree_impl
static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator) static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator)
{ return priv_container_from_end_iterator(end_iterator); } { return priv_container_from_end_iterator(end_iterator); }
//! <b>Precondition</b>: it must be a valid iterator
//! of rbtree.
//!
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static sgtree_impl &container_from_iterator(iterator it)
{ return priv_container_from_iterator(it); }
//! <b>Precondition</b>: it must be a valid end const_iterator
//! of rbtree.
//!
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const sgtree_impl &container_from_iterator(const_iterator it)
{ return priv_container_from_iterator(it); }
//! <b>Effects</b>: Returns the value_compare object used by the tree. //! <b>Effects</b>: Returns the value_compare object used by the tree.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1442,6 +1464,9 @@ class sgtree_impl
sgtree_impl *scapegoat = detail::parent_from_member<sgtree_impl, data_t>(d, &sgtree_impl::data_); sgtree_impl *scapegoat = detail::parent_from_member<sgtree_impl, data_t>(d, &sgtree_impl::data_);
return *scapegoat; return *scapegoat;
} }
static sgtree_impl &priv_container_from_iterator(const const_iterator &it)
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
}; };
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED

View File

@@ -22,7 +22,6 @@
#include <cstddef> #include <cstddef>
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/no_exceptions_support.hpp>
#include <boost/intrusive/detail/utilities.hpp> #include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/tree_algorithms.hpp> #include <boost/intrusive/detail/tree_algorithms.hpp>
@@ -59,6 +58,7 @@ template<class NodeTraits>
class sgtree_algorithms class sgtree_algorithms
{ {
public: public:
typedef typename NodeTraits::node node;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
@@ -66,7 +66,6 @@ class sgtree_algorithms
/// @cond /// @cond
private: private:
typedef typename NodeTraits::node node;
typedef detail::tree_algorithms<NodeTraits> tree_algorithms; typedef detail::tree_algorithms<NodeTraits> tree_algorithms;
static node_ptr uncast(const_node_ptr ptr) static node_ptr uncast(const_node_ptr ptr)
@@ -640,6 +639,16 @@ class sgtree_algorithms
static node_ptr rebalance_subtree(node_ptr old_root) static node_ptr rebalance_subtree(node_ptr old_root)
{ return tree_algorithms::rebalance_subtree(old_root); } { return tree_algorithms::rebalance_subtree(old_root); }
//! <b>Requires</b>: "n" must be a node inserted in a tree.
//!
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
//!
//! <b>Complexity</b>: Logarithmic.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_header(node_ptr n)
{ return tree_algorithms::get_header(n); }
/// @cond /// @cond
private: private:

View File

@@ -16,7 +16,6 @@
#include <boost/intrusive/detail/config_begin.hpp> #include <boost/intrusive/detail/config_begin.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/intrusive/detail/no_exceptions_support.hpp>
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/slist_hook.hpp> #include <boost/intrusive/slist_hook.hpp>
@@ -25,6 +24,7 @@
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/link_mode.hpp> #include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/options.hpp> #include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/utilities.hpp>
#include <iterator> #include <iterator>
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
@@ -183,10 +183,12 @@ class slist_impl
BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink))); BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink)));
node_ptr get_end_node() node_ptr get_end_node()
{ return node_ptr(linear ? 0 : this->get_root_node()); } { return node_ptr(linear ? node_ptr(0) : this->get_root_node()); }
const_node_ptr get_end_node() const const_node_ptr get_end_node() const
{ return const_node_ptr(linear ? 0 : this->get_root_node()); } {
return const_node_ptr
(linear ? const_node_ptr(0) : this->get_root_node()); }
node_ptr get_root_node() node_ptr get_root_node()
{ return node_ptr(&data_.root_plus_size_.root_); } { return node_ptr(&data_.root_plus_size_.root_); }
@@ -203,13 +205,10 @@ class slist_impl
void set_last_node(node_ptr n) void set_last_node(node_ptr n)
{ return this->set_last_node(n, detail::bool_<cache_last>()); } { return this->set_last_node(n, detail::bool_<cache_last>()); }
node_ptr get_last_node(detail::bool_<false>) static node_ptr get_last_node(detail::bool_<false>)
{ return node_ptr(0); } { return node_ptr(0); }
const_node_ptr get_last_node(detail::bool_<false>) const static void set_last_node(node_ptr, detail::bool_<false>)
{ return const_node_ptr(0); }
void set_last_node(node_ptr, detail::bool_<false>)
{} {}
node_ptr get_last_node(detail::bool_<true>) node_ptr get_last_node(detail::bool_<true>)
@@ -667,18 +666,14 @@ class slist_impl
void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer) void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer)
{ {
this->clear_and_dispose(disposer); this->clear_and_dispose(disposer);
BOOST_INTRUSIVE_TRY{ detail::exception_disposer<slist_impl, Disposer>
iterator prev(this->before_begin()); rollback(*this, disposer);
const_iterator b(src.begin()), e(src.end()); iterator prev(this->before_begin());
for(; b != e; ++b){ const_iterator b(src.begin()), e(src.end());
prev = this->insert_after(prev, *cloner(*b)); for(; b != e; ++b){
} prev = this->insert_after(prev, *cloner(*b));
} }
BOOST_INTRUSIVE_CATCH(...){ rollback.release();
this->clear_and_dispose(disposer);
BOOST_INTRUSIVE_RETHROW;
}
BOOST_INTRUSIVE_CATCH_END
} }
//! <b>Requires</b>: value must be an lvalue and prev_p must point to an element //! <b>Requires</b>: value must be an lvalue and prev_p must point to an element
@@ -783,12 +778,64 @@ class slist_impl
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Lineal to the elements (last - before_first + 1). //! <b>Complexity</b>: Linear to the number of erased elements if it's a safe-mode
//! , auto-unlink value or constant-time size is activated. Constant time otherwise.
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the //! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element. //! erased element.
iterator erase_after(iterator before_first, iterator last) iterator erase_after(iterator before_first, iterator last)
{ return this->erase_after_and_dispose(before_first, last, detail::null_disposer()); } {
if(safemode_or_autounlink || constant_time_size){
return this->erase_after_and_dispose(before_first, last, detail::null_disposer());
}
else{
node_ptr bfp = before_first.pointed_node();
node_ptr lp = last.pointed_node();
if(cache_last){
if((lp == this->get_end_node())){
this->set_last_node(bfp);
}
}
node_algorithms::unlink_after(bfp, lp);
return last;
}
}
//! <b>Effects</b>: Erases the range (before_first, last) from
//! the list. n must be std::distance(before_first, last) - 1.
//! No destructors are called.
//!
//! <b>Returns</b>: the first element remaining beyond the removed elements,
//! or end() if no such element exists.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: constant-time if link_mode is normal_link.
//! Linear to the elements (last - before_first) otherwise.
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
iterator erase_after(iterator before_first, iterator last, difference_type n)
{
BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(++iterator(before_first), last) == difference_type(n));
if(safemode_or_autounlink){
return this->erase_after(before_first, last);
}
else{
node_ptr bfp = before_first.pointed_node();
node_ptr lp = last.pointed_node();
if(cache_last){
if((lp == this->get_end_node())){
this->set_last_node(bfp);
}
}
node_algorithms::unlink_after(bfp, lp);
if(constant_time_size){
this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n);
}
return last;
}
}
//! <b>Effects</b>: Erases the element pointed by i of the list. //! <b>Effects</b>: Erases the element pointed by i of the list.
//! No destructors are called. //! No destructors are called.
@@ -815,14 +862,30 @@ class slist_impl
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements erased plus linear //! <b>Complexity</b>: Linear to the elements before last.
//! to the elements before first.
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the //! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased elements. //! erased elements.
iterator erase(iterator first, iterator last) iterator erase(iterator first, iterator last)
{ return this->erase_after(this->previous(first), last); } { return this->erase_after(this->previous(first), last); }
//! <b>Effects</b>: Erases the range [first, last) from
//! the list. n must be std::distance(first, last).
//! No destructors are called.
//!
//! <b>Returns</b>: the first element remaining beyond the removed elements,
//! or end() if no such element exists.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: linear to the elements before first if link_mode is normal_link
//! and constant_time_size is activated. Linear to the elements before last otherwise.
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
iterator erase(iterator first, iterator last, difference_type n)
{ return this->erase_after(this->previous(first), last, n); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
//! <b>Effects</b>: Erases the element after the element pointed by prev of //! <b>Effects</b>: Erases the element after the element pointed by prev of
@@ -849,13 +912,36 @@ class slist_impl
if(cache_last && (to_erase == this->get_last_node())){ if(cache_last && (to_erase == this->get_last_node())){
this->set_last_node(prev_n); this->set_last_node(prev_n);
} }
this->priv_size_traits().decrement();
if(safemode_or_autounlink) if(safemode_or_autounlink)
node_algorithms::init(to_erase); node_algorithms::init(to_erase);
disposer(get_real_value_traits().to_value_ptr(to_erase)); disposer(get_real_value_traits().to_value_ptr(to_erase));
this->priv_size_traits().decrement();
return it; return it;
} }
/// @cond
template<class Disposer>
static iterator s_erase_after_and_dispose(iterator prev, Disposer disposer)
{
BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits)));
iterator it(prev);
++it;
node_ptr to_erase(it.pointed_node());
++it;
node_ptr prev_n(prev.pointed_node());
node_algorithms::unlink_after(prev_n);
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
disposer(real_value_traits::to_value_ptr(to_erase));
return it;
}
static iterator s_erase_after(iterator prev)
{ return s_erase_after_and_dispose(prev, detail::null_disposer()); }
/// @endcond
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
//! <b>Effects</b>: Erases the range (before_first, last) from //! <b>Effects</b>: Erases the range (before_first, last) from
@@ -867,7 +953,7 @@ class slist_impl
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Lineal to the elements (last - before_first). //! <b>Complexity</b>: Lineal to the elements (last - before_first + 1).
//! //!
//! <b>Note</b>: Invalidates the iterators to the erased element. //! <b>Note</b>: Invalidates the iterators to the erased element.
template<class Disposer> template<class Disposer>
@@ -921,7 +1007,7 @@ class slist_impl
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements erased plus linear //! <b>Complexity</b>: Linear to the number of erased elements plus linear
//! to the elements before first. //! to the elements before first.
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the //! <b>Note</b>: Invalidates the iterators (but not the references) to the
@@ -997,8 +1083,11 @@ class slist_impl
iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active
node_ptr prev_n(prev.pointed_node()); node_ptr prev_n(prev.pointed_node());
node_ptr last_x_n(last_x.pointed_node()); node_ptr last_x_n(last_x.pointed_node());
if(cache_last && node_traits::get_next(prev_n) == this->get_end_node()){ if(cache_last){
this->set_last_node(last_x_n); x.set_last_node(x.get_root_node());
if(node_traits::get_next(prev_n) == this->get_end_node()){
this->set_last_node(last_x_n);
}
} }
node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n); node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n);
this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size()); this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size());
@@ -1026,10 +1115,7 @@ class slist_impl
void splice_after(iterator prev_pos, slist_impl &x, iterator prev_ele) void splice_after(iterator prev_pos, slist_impl &x, iterator prev_ele)
{ {
iterator elem = prev_ele; iterator elem = prev_ele;
++elem; this->splice_after(prev_pos, x, prev_ele, ++elem, 1);
if (elem != prev_pos && prev_ele != prev_pos){
this->splice_after(prev_pos, x, prev_ele, elem, 1);
}
} }
//! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be //! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be
@@ -1567,15 +1653,18 @@ class slist_impl
private: private:
void priv_splice_after(node_ptr prev_pos_n, slist_impl &x, node_ptr before_first_n, node_ptr before_last_n) void priv_splice_after(node_ptr prev_pos_n, slist_impl &x, node_ptr before_first_n, node_ptr before_last_n)
{ {
if(cache_last){ if (before_first_n != before_last_n && prev_pos_n != before_first_n && prev_pos_n != before_last_n)
if(node_traits::get_next(prev_pos_n) == this->get_end_node()){ {
this->set_last_node(before_last_n); if(cache_last){
} if(node_traits::get_next(prev_pos_n) == this->get_end_node()){
if(node_traits::get_next(before_last_n) == x.get_end_node()){ this->set_last_node(before_last_n);
x.set_last_node(before_first_n); }
if(node_traits::get_next(before_last_n) == x.get_end_node()){
x.set_last_node(before_first_n);
}
} }
node_algorithms::transfer_after(prev_pos_n, before_first_n, before_last_n);
} }
node_algorithms::transfer_after(prev_pos_n, before_first_n, before_last_n);
} }
void priv_reverse(detail::bool_<false>) void priv_reverse(detail::bool_<false>)

View File

@@ -252,6 +252,34 @@ class splay_set_impl
, &splay_set_impl::tree_); , &splay_set_impl::tree_);
} }
//! <b>Precondition</b>: it must be a valid iterator of set.
//!
//! <b>Effects</b>: Returns a reference to the set associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
static splay_set_impl &container_from_iterator(iterator it)
{
return *detail::parent_from_member<splay_set_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &splay_set_impl::tree_);
}
//! <b>Precondition</b>: it must be a valid const_iterator of set.
//!
//! <b>Effects</b>: Returns a const reference to the set associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const splay_set_impl &container_from_iterator(const_iterator it)
{
return *detail::parent_from_member<splay_set_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &splay_set_impl::tree_);
}
//! <b>Effects</b>: Returns the key_compare object used by the splay_set. //! <b>Effects</b>: Returns the key_compare object used by the splay_set.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1161,6 +1189,12 @@ class splay_set
static const splay_set &container_from_end_iterator(const_iterator end_iterator) static const splay_set &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const splay_set &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const splay_set &>(Base::container_from_end_iterator(end_iterator)); }
static splay_set &container_from_iterator(iterator it)
{ return static_cast<splay_set &>(Base::container_from_iterator(it)); }
static const splay_set &container_from_iterator(const_iterator it)
{ return static_cast<const splay_set &>(Base::container_from_iterator(it)); }
}; };
#endif #endif
@@ -1393,6 +1427,34 @@ class splay_multiset_impl
, &splay_multiset_impl::tree_); , &splay_multiset_impl::tree_);
} }
//! <b>Precondition</b>: it must be a valid iterator of multiset.
//!
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static splay_multiset_impl &container_from_iterator(iterator it)
{
return *detail::parent_from_member<splay_multiset_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &splay_multiset_impl::tree_);
}
//! <b>Precondition</b>: it must be a valid const_iterator of multiset.
//!
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
static const splay_multiset_impl &container_from_iterator(const_iterator it)
{
return *detail::parent_from_member<splay_multiset_impl, tree_type>
( &tree_type::container_from_iterator(it)
, &splay_multiset_impl::tree_);
}
//! <b>Effects</b>: Returns the key_compare object used by the splay_multiset. //! <b>Effects</b>: Returns the key_compare object used by the splay_multiset.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -2209,6 +2271,12 @@ class splay_multiset
static const splay_multiset &container_from_end_iterator(const_iterator end_iterator) static const splay_multiset &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const splay_multiset &>(Base::container_from_end_iterator(end_iterator)); } { return static_cast<const splay_multiset &>(Base::container_from_end_iterator(end_iterator)); }
static splay_multiset &container_from_iterator(iterator it)
{ return static_cast<splay_multiset &>(Base::container_from_iterator(it)); }
static const splay_multiset &container_from_iterator(const_iterator it)
{ return static_cast<const splay_multiset &>(Base::container_from_iterator(it)); }
}; };
#endif #endif

View File

@@ -387,6 +387,28 @@ class splaytree_impl
static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator) static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator)
{ return priv_container_from_end_iterator(end_iterator); } { return priv_container_from_end_iterator(end_iterator); }
//! <b>Precondition</b>: it must be a valid iterator
//! of rbtree.
//!
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static splaytree_impl &container_from_iterator(iterator it)
{ return priv_container_from_iterator(it); }
//! <b>Precondition</b>: it must be a valid end const_iterator
//! of rbtree.
//!
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Logarithmic.
static const splaytree_impl &container_from_iterator(const_iterator it)
{ return priv_container_from_iterator(it); }
//! <b>Effects</b>: Returns the value_compare object used by the tree. //! <b>Effects</b>: Returns the value_compare object used by the tree.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
@@ -1312,6 +1334,9 @@ class splaytree_impl
splaytree_impl *rb = detail::parent_from_member<splaytree_impl, data_t>(d, &splaytree_impl::data_); splaytree_impl *rb = detail::parent_from_member<splaytree_impl, data_t>(d, &splaytree_impl::data_);
return *rb; return *rb;
} }
static splaytree_impl &priv_container_from_iterator(const const_iterator &it)
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
}; };
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED

View File

@@ -50,13 +50,48 @@
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <cstddef> #include <cstddef>
#include <boost/intrusive/detail/no_exceptions_support.hpp>
#include <boost/intrusive/detail/utilities.hpp> #include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/tree_algorithms.hpp> #include <boost/intrusive/detail/tree_algorithms.hpp>
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
/// @cond
namespace detail {
template<class NodeTraits>
struct splaydown_rollback
{
typedef typename NodeTraits::node_ptr node_ptr;
splaydown_rollback( const node_ptr *pcur_subtree, node_ptr header
, node_ptr leftmost , node_ptr rightmost)
: pcur_subtree_(pcur_subtree) , header_(header)
, leftmost_(leftmost) , rightmost_(rightmost)
{}
void release()
{ pcur_subtree_ = 0; }
~splaydown_rollback()
{
if(pcur_subtree_){
//Exception can only be thrown by comp, but
//tree invariants still hold. *pcur_subtree is the current root
//so link it to the header.
NodeTraits::set_parent(*pcur_subtree_, header_);
NodeTraits::set_parent(header_, *pcur_subtree_);
//Recover leftmost/rightmost pointers
NodeTraits::set_left (header_, leftmost_);
NodeTraits::set_right(header_, rightmost_);
}
}
const node_ptr *pcur_subtree_;
node_ptr header_, leftmost_, rightmost_;
};
} //namespace detail {
/// @endcond
//! A splay tree is an implementation of a binary search tree. The tree is //! A splay tree is an implementation of a binary search tree. The tree is
//! self balancing using the splay algorithm as described in //! self balancing using the splay algorithm as described in
//! //!
@@ -95,11 +130,11 @@ class splaytree_algorithms
{ {
/// @cond /// @cond
private: private:
typedef typename NodeTraits::node node;
typedef detail::tree_algorithms<NodeTraits> tree_algorithms; typedef detail::tree_algorithms<NodeTraits> tree_algorithms;
/// @endcond /// @endcond
public: public:
typedef typename NodeTraits::node node;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
@@ -656,7 +691,8 @@ class splaytree_algorithms
node_ptr leftmost = NodeTraits::get_left(header); node_ptr leftmost = NodeTraits::get_left(header);
node_ptr rightmost = NodeTraits::get_right(header); node_ptr rightmost = NodeTraits::get_right(header);
try{ {
detail::splaydown_rollback<NodeTraits> rollback(&t, header, leftmost, rightmost);
node_ptr null = header; node_ptr null = header;
node_ptr l = null; node_ptr l = null;
node_ptr r = null; node_ptr r = null;
@@ -712,18 +748,9 @@ class splaytree_algorithms
} }
assemble(t, l, r, null); assemble(t, l, r, null);
rollback.release();
} }
catch(...){
//Exception can only be thrown by comp, but
//tree invariants still hold. t is the current root
//so link it to the header.
NodeTraits::set_parent(t, header);
NodeTraits::set_parent(header, t);
//Recover leftmost/rightmost pointers
NodeTraits::set_left (header, leftmost);
NodeTraits::set_right(header, rightmost);
throw;
}
//t is the current root //t is the current root
NodeTraits::set_parent(header, t); NodeTraits::set_parent(header, t);
NodeTraits::set_parent(t, header); NodeTraits::set_parent(t, header);
@@ -755,6 +782,17 @@ class splaytree_algorithms
static node_ptr rebalance_subtree(node_ptr old_root) static node_ptr rebalance_subtree(node_ptr old_root)
{ return tree_algorithms::rebalance_subtree(old_root); } { return tree_algorithms::rebalance_subtree(old_root); }
//! <b>Requires</b>: "n" must be a node inserted in a tree.
//!
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
//!
//! <b>Complexity</b>: Logarithmic.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_header(node_ptr n)
{ return tree_algorithms::get_header(n); }
private: private:
/// @cond /// @cond

View File

@@ -24,7 +24,7 @@ namespace intrusive {
//! The class template unordered_set is an intrusive container, that mimics most of //! The class template unordered_set is an intrusive container, that mimics most of
//! the interface of std::tr1::unordered_set as described in the C++ TR1. //! the interface of std::tr1::unordered_set as described in the C++ TR1.
//! //!
//! unordered_set is a pseudo-intrusive container: each object to be stored in the //! unordered_set is a semi-intrusive container: each object to be stored in the
//! container must contain a proper hook, but the container also needs //! container must contain a proper hook, but the container also needs
//! additional auxiliary memory to work: unordered_set needs a pointer to an array //! additional auxiliary memory to work: unordered_set needs a pointer to an array
//! of type `bucket_type` to be passed in the constructor. This bucket array must //! of type `bucket_type` to be passed in the constructor. This bucket array must
@@ -38,7 +38,8 @@ namespace intrusive {
//! //!
//! The container supports the following options: //! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>, //! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> . //! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>.
//! //!
//! unordered_set only provides forward iterators but it provides 4 iterator types: //! unordered_set only provides forward iterators but it provides 4 iterator types:
//! iterator and const_iterator to navigate through the whole container and //! iterator and const_iterator to navigate through the whole container and
@@ -167,8 +168,8 @@ class unordered_set_impl
//! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_set. //! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_set.
//! //!
//! <b>Complexity</b>: Amortized constant time. //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
//! Worst case (empty unordered_set): O(this->bucket_count()) //! constant time with worst case (empty unordered_set) O(this->bucket_count())
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
iterator begin() iterator begin()
@@ -177,8 +178,8 @@ class unordered_set_impl
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
//! of the unordered_set. //! of the unordered_set.
//! //!
//! <b>Complexity</b>: Amortized constant time. //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
//! Worst case (empty unordered_set): O(this->bucket_count()) //! constant time with worst case (empty unordered_set) O(this->bucket_count())
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
const_iterator begin() const const_iterator begin() const
@@ -187,8 +188,8 @@ class unordered_set_impl
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
//! of the unordered_set. //! of the unordered_set.
//! //!
//! <b>Complexity</b>: Amortized constant time. //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
//! Worst case (empty unordered_set): O(this->bucket_count()) //! constant time with worst case (empty unordered_set) O(this->bucket_count())
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
const_iterator cbegin() const const_iterator cbegin() const
@@ -236,8 +237,8 @@ class unordered_set_impl
//! <b>Effects</b>: Returns true is the container is empty. //! <b>Effects</b>: Returns true is the container is empty.
//! //!
//! <b>Complexity</b>: if constant-time size option is disabled, average constant time //! <b>Complexity</b>: if constant-time size and cache_last options are disabled,
//! (worst case, with empty() == true): O(this->bucket_count()). //! average constant time (worst case, with empty() == true: O(this->bucket_count()).
//! Otherwise constant. //! Otherwise constant.
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
@@ -959,7 +960,8 @@ template<class T, class ...Options>
template<class T, class O1 = none, class O2 = none template<class T, class O1 = none, class O2 = none
, class O3 = none, class O4 = none , class O3 = none, class O4 = none
, class O5 = none, class O6 = none , class O5 = none, class O6 = none
, class O7 = none , class O7 = none, class O8 = none
, class O9 = none
> >
#endif #endif
struct make_unordered_set struct make_unordered_set
@@ -967,19 +969,19 @@ struct make_unordered_set
/// @cond /// @cond
typedef unordered_set_impl typedef unordered_set_impl
< typename make_hashtable_opt < typename make_hashtable_opt
<T, O1, O2, O3, O4, O5, O6, O7>::type <T, true, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
> implementation_defined; > implementation_defined;
/// @endcond /// @endcond
typedef implementation_defined type; typedef implementation_defined type;
}; };
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7> template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9>
class unordered_set class unordered_set
: public make_unordered_set<T, O1, O2, O3, O4, O5, O6, O7>::type : public make_unordered_set<T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
{ {
typedef typename make_unordered_set typedef typename make_unordered_set
<T, O1, O2, O3, O4, O5, O6, O7>::type Base; <T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type Base;
//Assert if passed value traits are compatible with the type //Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value)); BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
@@ -1018,7 +1020,7 @@ class unordered_set
//! The class template unordered_multiset is an intrusive container, that mimics most of //! The class template unordered_multiset is an intrusive container, that mimics most of
//! the interface of std::tr1::unordered_multiset as described in the C++ TR1. //! the interface of std::tr1::unordered_multiset as described in the C++ TR1.
//! //!
//! unordered_multiset is a pseudo-intrusive container: each object to be stored in the //! unordered_multiset is a semi-intrusive container: each object to be stored in the
//! container must contain a proper hook, but the container also needs //! container must contain a proper hook, but the container also needs
//! additional auxiliary memory to work: unordered_multiset needs a pointer to an array //! additional auxiliary memory to work: unordered_multiset needs a pointer to an array
//! of type `bucket_type` to be passed in the constructor. This bucket array must //! of type `bucket_type` to be passed in the constructor. This bucket array must
@@ -1032,7 +1034,8 @@ class unordered_set
//! //!
//! The container supports the following options: //! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>, //! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> . //! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>.
//! //!
//! unordered_multiset only provides forward iterators but it provides 4 iterator types: //! unordered_multiset only provides forward iterators but it provides 4 iterator types:
//! iterator and const_iterator to navigate through the whole container and //! iterator and const_iterator to navigate through the whole container and
@@ -1161,8 +1164,8 @@ class unordered_multiset_impl
//! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_multiset. //! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_multiset.
//! //!
//! <b>Complexity</b>: Amortized constant time. //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
//! Worst case (empty unordered_multiset): O(this->bucket_count()) //! constant time with worst case (empty unordered_set) O(this->bucket_count())
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
iterator begin() iterator begin()
@@ -1171,8 +1174,8 @@ class unordered_multiset_impl
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
//! of the unordered_multiset. //! of the unordered_multiset.
//! //!
//! <b>Complexity</b>: Amortized constant time. //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
//! Worst case (empty unordered_multiset): O(this->bucket_count()) //! constant time with worst case (empty unordered_set) O(this->bucket_count())
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
const_iterator begin() const const_iterator begin() const
@@ -1181,8 +1184,8 @@ class unordered_multiset_impl
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
//! of the unordered_multiset. //! of the unordered_multiset.
//! //!
//! <b>Complexity</b>: Amortized constant time. //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
//! Worst case (empty unordered_multiset): O(this->bucket_count()) //! constant time with worst case (empty unordered_set) O(this->bucket_count())
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
const_iterator cbegin() const const_iterator cbegin() const
@@ -1230,8 +1233,8 @@ class unordered_multiset_impl
//! <b>Effects</b>: Returns true is the container is empty. //! <b>Effects</b>: Returns true is the container is empty.
//! //!
//! <b>Complexity</b>: if constant-time size option is disabled, average constant time //! <b>Complexity</b>: if constant-time size and cache_last options are disabled,
//! (worst case, with empty() == true): O(this->bucket_count()). //! average constant time (worst case, with empty() == true: O(this->bucket_count()).
//! Otherwise constant. //! Otherwise constant.
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
@@ -1891,7 +1894,8 @@ template<class T, class ...Options>
template<class T, class O1 = none, class O2 = none template<class T, class O1 = none, class O2 = none
, class O3 = none, class O4 = none , class O3 = none, class O4 = none
, class O5 = none, class O6 = none , class O5 = none, class O6 = none
, class O7 = none , class O7 = none, class O8 = none
, class O9 = none
> >
#endif #endif
struct make_unordered_multiset struct make_unordered_multiset
@@ -1899,19 +1903,19 @@ struct make_unordered_multiset
/// @cond /// @cond
typedef unordered_multiset_impl typedef unordered_multiset_impl
< typename make_hashtable_opt < typename make_hashtable_opt
<T, O1, O2, O3, O4, O5, O6, O7>::type <T, false, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
> implementation_defined; > implementation_defined;
/// @endcond /// @endcond
typedef implementation_defined type; typedef implementation_defined type;
}; };
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7> template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9>
class unordered_multiset class unordered_multiset
: public make_unordered_multiset<T, O1, O2, O3, O4, O5, O6, O7>::type : public make_unordered_multiset<T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
{ {
typedef typename make_unordered_multiset typedef typename make_unordered_multiset
<T, O1, O2, O3, O4, O5, O6, O7>::type Base; <T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type Base;
//Assert if passed value traits are compatible with the type //Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value)); BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));

View File

@@ -17,6 +17,7 @@
#include <boost/intrusive/detail/config_begin.hpp> #include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/utilities.hpp> #include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/slist_hook.hpp> #include <boost/intrusive/slist_hook.hpp>
#include <boost/intrusive/options.hpp> #include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/generic_hook.hpp> #include <boost/intrusive/detail/generic_hook.hpp>
@@ -26,35 +27,66 @@ namespace intrusive {
/// @cond /// @cond
template<class VoidPointer> template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
struct slist_node_plus_hash struct unordered_node
: public slist_node<VoidPointer>
{ {
typedef typename boost::pointer_to_other typedef typename boost::pointer_to_other
<VoidPointer, slist_node_plus_hash>::type node_ptr; < VoidPointer
node_ptr next_; , unordered_node<VoidPointer, StoreHash, OptimizeMultiKey>
>::type node_ptr;
node_ptr prev_in_group_;
std::size_t hash_; std::size_t hash_;
}; };
// slist_node_traits can be used with circular_slist_algorithms and supplies
// a slist_node holding the pointers needed for a singly-linked list
// it is used by slist_base_hook and slist_member_hook
template<class VoidPointer> template<class VoidPointer>
struct slist_node_traits_plus_hash struct unordered_node<VoidPointer, false, true>
: public slist_node<VoidPointer>
{ {
typedef slist_node_plus_hash<VoidPointer> node; typedef typename boost::pointer_to_other
< VoidPointer
, unordered_node<VoidPointer, false, true>
>::type node_ptr;
node_ptr prev_in_group_;
};
template<class VoidPointer>
struct unordered_node<VoidPointer, true, false>
: public slist_node<VoidPointer>
{
typedef typename boost::pointer_to_other
< VoidPointer
, unordered_node<VoidPointer, true, false>
>::type node_ptr;
std::size_t hash_;
};
template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
struct unordered_node_traits
: public slist_node_traits<VoidPointer>
{
typedef slist_node_traits<VoidPointer> reduced_slist_node_traits;
typedef unordered_node<VoidPointer, StoreHash, OptimizeMultiKey> node;
typedef typename boost::pointer_to_other typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr; <VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr; <VoidPointer, const node>::type const_node_ptr;
static const bool store_hash = true; static const bool store_hash = StoreHash;
static const bool optimize_multikey = OptimizeMultiKey;
static node_ptr get_next(const_node_ptr n) static node_ptr get_next(const_node_ptr n)
{ return n->next_; } { return node_ptr(&static_cast<node &>(*n->next_)); }
static void set_next(node_ptr n, node_ptr next) static void set_next(node_ptr n, node_ptr next)
{ n->next_ = next; } { n->next_ = next; }
static node_ptr get_prev_in_group(const_node_ptr n)
{ return n->prev_in_group_; }
static void set_prev_in_group(node_ptr n, node_ptr prev)
{ n->prev_in_group_ = prev; }
static std::size_t get_hash(const_node_ptr n) static std::size_t get_hash(const_node_ptr n)
{ return n->hash_; } { return n->hash_; }
@@ -62,15 +94,60 @@ struct slist_node_traits_plus_hash
{ n->hash_ = h; } { n->hash_ = h; }
}; };
template<class VoidPointer, bool StoreHash> template<class NodeTraits>
struct unordered_group_adapter
{
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
static node_ptr get_next(const_node_ptr n)
{ return NodeTraits::get_prev_in_group(n); }
static void set_next(node_ptr n, node_ptr next)
{ NodeTraits::set_prev_in_group(n, next); }
};
template<class NodeTraits>
struct unordered_algorithms
: public circular_slist_algorithms<NodeTraits>
{
typedef circular_slist_algorithms<NodeTraits> base_type;
typedef unordered_group_adapter<NodeTraits> group_traits;
typedef circular_slist_algorithms<group_traits> group_algorithms;
static void init(typename base_type::node_ptr n)
{
base_type::init(n);
group_algorithms::init(n);
}
static void init_header(typename base_type::node_ptr n)
{
base_type::init_header(n);
group_algorithms::init_header(n);
}
static void unlink(typename base_type::node_ptr n)
{
base_type::unlink(n);
group_algorithms::unlink(n);
}
};
template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
struct get_uset_node_algo struct get_uset_node_algo
{ {
typedef typename detail::if_c typedef typename detail::if_c
< StoreHash < (StoreHash || OptimizeMultiKey)
, slist_node_traits_plus_hash<VoidPointer> , unordered_node_traits<VoidPointer, StoreHash, OptimizeMultiKey>
, slist_node_traits<VoidPointer> , slist_node_traits<VoidPointer>
>::type node_traits_type; >::type node_traits_type;
typedef circular_slist_algorithms<node_traits_type> type; typedef typename detail::if_c
< OptimizeMultiKey
, unordered_algorithms<node_traits_type>
, circular_slist_algorithms<node_traits_type>
>::type type;
}; };
/// @endcond /// @endcond
@@ -90,6 +167,7 @@ struct make_unordered_set_base_hook
typedef detail::generic_hook typedef detail::generic_hook
< get_uset_node_algo<typename packed_options::void_pointer < get_uset_node_algo<typename packed_options::void_pointer
, packed_options::store_hash , packed_options::store_hash
, packed_options::optimize_multikey
> >
, typename packed_options::tag , typename packed_options::tag
, packed_options::link_mode , packed_options::link_mode
@@ -104,7 +182,7 @@ struct make_unordered_set_base_hook
//! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set. //! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
//! //!
//! The hook admits the following options: \c tag<>, \c void_pointer<>, //! The hook admits the following options: \c tag<>, \c void_pointer<>,
//! \c link_mode<> and \c store_hash<>. //! \c link_mode<>, \c store_hash<> and \c optimize_multikey<>.
//! //!
//! \c tag<> defines a tag to identify the 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 //! The same tag value can be used in different classes, but if a class is
@@ -119,6 +197,10 @@ struct make_unordered_set_base_hook
//! //!
//! \c store_hash<> will tell the hook to store the hash of the value //! \c store_hash<> will tell the hook to store the hash of the value
//! to speed up rehashings. //! to speed up rehashings.
//!
//! \c optimize_multikey<> will tell the hook to store a link to form a group
//! with other value with the same value to speed up searches and insertions
//! in unordered_multisets with a great number of with equivalent keys.
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template<class ...Options> template<class ...Options>
#else #else
@@ -211,6 +293,7 @@ struct make_unordered_set_member_hook
typedef detail::generic_hook typedef detail::generic_hook
< get_uset_node_algo< typename packed_options::void_pointer < get_uset_node_algo< typename packed_options::void_pointer
, packed_options::store_hash , packed_options::store_hash
, packed_options::optimize_multikey
> >
, member_tag , member_tag
, packed_options::link_mode , packed_options::link_mode

View File

@@ -4,6 +4,6 @@
</head> </head>
<body> <body>
Automatic redirection failed, please go to Automatic redirection failed, please go to
<a href="../../doc/html/intrusive.html">../../doc/html/intrusive.html</a> <a href="../../doc/html/intrusive">../../doc/html/intrusive</a>
</body> </body>
</html> </html>

View File

@@ -1,6 +1,6 @@
# Boost Intrusive Library Performance test Jamfile # Boost Intrusive Library Performance test Jamfile
# (C) Copyright Ion Gazta<EFBFBD>aga 2006-2007. # (C) Copyright Ion Gaztanaga 2006-2007.
# Use, modification and distribution are subject to the # Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file # Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -23,7 +23,7 @@ using namespace boost::posix_time;
//[perf_list_value_type //[perf_list_value_type
//Iteration and element count defines //Iteration and element count defines
const int NumIter = 100; const int NumIter = 100;
const int NumElements = 100000; const int NumElements = 50000;
using namespace boost::intrusive; using namespace boost::intrusive;

View File

@@ -1,175 +1,361 @@
Microsoft Visual Studio Solution File, Format Version 8.00 <<<<<<< .working
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list\list.vcproj", "{977B61B4-9968-497C-9F0B-24A8145473B8}" Microsoft Visual Studio Solution File, Format Version 8.00
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list\list.vcproj", "{977B61B4-9968-497C-9F0B-24A8145473B8}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist", "slist\slist.vcproj", "{5A02061D-3728-4C49-AFC8-0130C1F161C0}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist", "slist\slist.vcproj", "{5A02061D-3728-4C49-AFC8-0130C1F161C0}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multiset", "multiset\multiset.vcproj", "{961F0E06-C092-4AF7-ABC5-2A49999F3B79}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multiset", "multiset\multiset.vcproj", "{961F0E06-C092-4AF7-ABC5-2A49999F3B79}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_intrusivelib", "_intrusivelib\_intrusivelib.vcproj", "{90F3C5BD-8E6C-4629-BC71-A1009EC88059}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_intrusivelib", "_intrusivelib\_intrusivelib.vcproj", "{90F3C5BD-8E6C-4629-BC71-A1009EC88059}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set", "set\set.vcproj", "{960E01F6-92C1-F74A-BCA5-2A9F3B994979}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set", "set\set.vcproj", "{960E01F6-92C1-F74A-BCA5-2A9F3B994979}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_set", "unordered_set\unordered_set.vcproj", "{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_set", "unordered_set\unordered_set.vcproj", "{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_multiset", "unordered_multiset\unordered_multiset.vcproj", "{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_multiset", "unordered_multiset\unordered_multiset.vcproj", "{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "perf_test", "perf_test\perf_test.vcproj", "{910E70E6-2C91-AA67-BF4C-A9C74A309927}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "perf_test", "perf_test\perf_test.vcproj", "{910E70E6-2C91-AA67-BF4C-A9C74A309927}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "default_hook", "default_hook\default_hook.vcproj", "{761A79B4-9968-CB81-F02B-2A4497345475}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "default_hook", "default_hook\default_hook.vcproj", "{761A79B4-9968-CB81-F02B-2A4497345475}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stateful_value_traits", "stateful_value_traits\stateful_value_traits.vcproj", "{9571A7B4-9968-B9C1-17FB-134547B46975}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stateful_value_traits", "stateful_value_traits\stateful_value_traits.vcproj", "{9571A7B4-9968-B9C1-17FB-134547B46975}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "virtual_base", "virtual_base\virtual_base.vcproj", "{3579B1A4-9894-02AB-CB81-297B46154345}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "virtual_base", "virtual_base\virtual_base.vcproj", "{3579B1A4-9894-02AB-CB81-297B46154345}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_functions", "make_functions\make_functions.vcproj", "{7679B41B-F2B4-9176-CB81-35449467B435}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_functions", "make_functions\make_functions.vcproj", "{7679B41B-F2B4-9176-CB81-35449467B435}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "custom_bucket_traits", "custom_bucket_traits\custom_bucket_traits.vcproj", "{31C77B84-0B2C-9481-CB81-27A149F33825}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "custom_bucket_traits", "custom_bucket_traits\custom_bucket_traits.vcproj", "{31C77B84-0B2C-9481-CB81-27A149F33825}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "external_value_traits", "external_value_traits\external_value_traits.vcproj", "{97B69A72-B9D3-7389-17FB-74612F4A9543}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "external_value_traits", "external_value_traits\external_value_traits.vcproj", "{97B69A72-B9D3-7389-17FB-74612F4A9543}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_multiset", "splay_multiset\splay_multiset.vcproj", "{01E70176-B6C5-BF47-2C91-A949077BA323}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_multiset", "splay_multiset\splay_multiset.vcproj", "{01E70176-B6C5-BF47-2C91-A949077BA323}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_set", "splay_set\splay_set.vcproj", "{1E6909E7-C971-F24A-6C7B-A92094B71B59}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_set", "splay_set\splay_set.vcproj", "{1E6909E7-C971-F24A-6C7B-A92094B71B59}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_multiset", "avl_multiset\avl_multiset.vcproj", "{0AE70176-5B8C-4BC7-392C-A4A312B07893}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_multiset", "avl_multiset\avl_multiset.vcproj", "{0AE70176-5B8C-4BC7-392C-A4A312B07893}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_set", "avl_set\avl_set.vcproj", "{16909EE7-24AF-97C1-C76B-204B971BA959}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_set", "avl_set\avl_set.vcproj", "{16909EE7-24AF-97C1-C76B-204B971BA959}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_multiset", "sg_multiset\sg_multiset.vcproj", "{07022E76-6CB5-92C1-B47F-A10772A79B43}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_multiset", "sg_multiset\sg_multiset.vcproj", "{07022E76-6CB5-92C1-B47F-A10772A79B43}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_set", "sg_set\sg_set.vcproj", "{1690A9E7-DB57-971C-F24A-09B752A942F7}" EndProject
ProjectSection(ProjectDependencies) = postProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_set", "sg_set\sg_set.vcproj", "{1690A9E7-DB57-971C-F24A-09B752A942F7}"
EndProjectSection ProjectSection(ProjectDependencies) = postProject
EndProject EndProjectSection
Global EndProject
GlobalSection(SolutionConfiguration) = preSolution Global
Debug = Debug GlobalSection(SolutionConfiguration) = preSolution
Release = Release Debug = Debug
EndGlobalSection Release = Release
GlobalSection(ProjectDependencies) = postSolution EndGlobalSection
EndGlobalSection GlobalSection(ProjectDependencies) = postSolution
GlobalSection(ProjectConfiguration) = postSolution EndGlobalSection
{977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.ActiveCfg = Debug|Win32 GlobalSection(ProjectConfiguration) = postSolution
{977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.Build.0 = Debug|Win32 {977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.ActiveCfg = Debug|Win32
{977B61B4-9968-497C-9F0B-24A8145473B8}.Release.ActiveCfg = Release|Win32 {977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.Build.0 = Debug|Win32
{977B61B4-9968-497C-9F0B-24A8145473B8}.Release.Build.0 = Release|Win32 {977B61B4-9968-497C-9F0B-24A8145473B8}.Release.ActiveCfg = Release|Win32
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.ActiveCfg = Debug|Win32 {977B61B4-9968-497C-9F0B-24A8145473B8}.Release.Build.0 = Release|Win32
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.Build.0 = Debug|Win32 {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.ActiveCfg = Debug|Win32
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.ActiveCfg = Release|Win32 {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.Build.0 = Debug|Win32
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.Build.0 = Release|Win32 {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.ActiveCfg = Release|Win32
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.ActiveCfg = Debug|Win32 {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.Build.0 = Release|Win32
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.Build.0 = Debug|Win32 {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.ActiveCfg = Debug|Win32
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.ActiveCfg = Release|Win32 {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.Build.0 = Debug|Win32
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.Build.0 = Release|Win32 {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.ActiveCfg = Release|Win32
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.ActiveCfg = Debug|Win32 {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.Build.0 = Release|Win32
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.Build.0 = Debug|Win32 {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.ActiveCfg = Debug|Win32
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.ActiveCfg = Release|Win32 {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.Build.0 = Debug|Win32
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.Build.0 = Release|Win32 {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.ActiveCfg = Release|Win32
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.ActiveCfg = Debug|Win32 {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.Build.0 = Release|Win32
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.Build.0 = Debug|Win32 {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.ActiveCfg = Debug|Win32
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.ActiveCfg = Release|Win32 {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.Build.0 = Debug|Win32
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.Build.0 = Release|Win32 {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.ActiveCfg = Release|Win32
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.ActiveCfg = Debug|Win32 {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.Build.0 = Release|Win32
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.Build.0 = Debug|Win32 {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.ActiveCfg = Debug|Win32
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.ActiveCfg = Release|Win32 {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.Build.0 = Debug|Win32
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.Build.0 = Release|Win32 {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.ActiveCfg = Release|Win32
{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.ActiveCfg = Debug|Win32 {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.Build.0 = Release|Win32
{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.Build.0 = Debug|Win32 {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.ActiveCfg = Debug|Win32
{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.ActiveCfg = Release|Win32 {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.Build.0 = Debug|Win32
{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.Build.0 = Release|Win32 {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.ActiveCfg = Release|Win32
{910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.ActiveCfg = Debug|Win32 {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.Build.0 = Release|Win32
{910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.Build.0 = Debug|Win32 {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.ActiveCfg = Debug|Win32
{910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.ActiveCfg = Release|Win32 {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.Build.0 = Debug|Win32
{910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.Build.0 = Release|Win32 {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.ActiveCfg = Release|Win32
{761A79B4-9968-CB81-F02B-2A4497345475}.Debug.ActiveCfg = Debug|Win32 {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.Build.0 = Release|Win32
{761A79B4-9968-CB81-F02B-2A4497345475}.Debug.Build.0 = Debug|Win32 {761A79B4-9968-CB81-F02B-2A4497345475}.Debug.ActiveCfg = Debug|Win32
{761A79B4-9968-CB81-F02B-2A4497345475}.Release.ActiveCfg = Release|Win32 {761A79B4-9968-CB81-F02B-2A4497345475}.Debug.Build.0 = Debug|Win32
{761A79B4-9968-CB81-F02B-2A4497345475}.Release.Build.0 = Release|Win32 {761A79B4-9968-CB81-F02B-2A4497345475}.Release.ActiveCfg = Release|Win32
{9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.ActiveCfg = Debug|Win32 {761A79B4-9968-CB81-F02B-2A4497345475}.Release.Build.0 = Release|Win32
{9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.Build.0 = Debug|Win32 {9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.ActiveCfg = Debug|Win32
{9571A7B4-9968-B9C1-17FB-134547B46975}.Release.ActiveCfg = Release|Win32 {9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.Build.0 = Debug|Win32
{9571A7B4-9968-B9C1-17FB-134547B46975}.Release.Build.0 = Release|Win32 {9571A7B4-9968-B9C1-17FB-134547B46975}.Release.ActiveCfg = Release|Win32
{3579B1A4-9894-02AB-CB81-297B46154345}.Debug.ActiveCfg = Debug|Win32 {9571A7B4-9968-B9C1-17FB-134547B46975}.Release.Build.0 = Release|Win32
{3579B1A4-9894-02AB-CB81-297B46154345}.Debug.Build.0 = Debug|Win32 {3579B1A4-9894-02AB-CB81-297B46154345}.Debug.ActiveCfg = Debug|Win32
{3579B1A4-9894-02AB-CB81-297B46154345}.Release.ActiveCfg = Release|Win32 {3579B1A4-9894-02AB-CB81-297B46154345}.Debug.Build.0 = Debug|Win32
{3579B1A4-9894-02AB-CB81-297B46154345}.Release.Build.0 = Release|Win32 {3579B1A4-9894-02AB-CB81-297B46154345}.Release.ActiveCfg = Release|Win32
{7679B41B-F2B4-9176-CB81-35449467B435}.Debug.ActiveCfg = Debug|Win32 {3579B1A4-9894-02AB-CB81-297B46154345}.Release.Build.0 = Release|Win32
{7679B41B-F2B4-9176-CB81-35449467B435}.Debug.Build.0 = Debug|Win32 {7679B41B-F2B4-9176-CB81-35449467B435}.Debug.ActiveCfg = Debug|Win32
{7679B41B-F2B4-9176-CB81-35449467B435}.Release.ActiveCfg = Release|Win32 {7679B41B-F2B4-9176-CB81-35449467B435}.Debug.Build.0 = Debug|Win32
{7679B41B-F2B4-9176-CB81-35449467B435}.Release.Build.0 = Release|Win32 {7679B41B-F2B4-9176-CB81-35449467B435}.Release.ActiveCfg = Release|Win32
{31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.ActiveCfg = Debug|Win32 {7679B41B-F2B4-9176-CB81-35449467B435}.Release.Build.0 = Release|Win32
{31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.Build.0 = Debug|Win32 {31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.ActiveCfg = Debug|Win32
{31C77B84-0B2C-9481-CB81-27A149F33825}.Release.ActiveCfg = Release|Win32 {31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.Build.0 = Debug|Win32
{31C77B84-0B2C-9481-CB81-27A149F33825}.Release.Build.0 = Release|Win32 {31C77B84-0B2C-9481-CB81-27A149F33825}.Release.ActiveCfg = Release|Win32
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.ActiveCfg = Debug|Win32 {31C77B84-0B2C-9481-CB81-27A149F33825}.Release.Build.0 = Release|Win32
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.Build.0 = Debug|Win32 {97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.ActiveCfg = Debug|Win32
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.ActiveCfg = Release|Win32 {97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.Build.0 = Debug|Win32
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.Build.0 = Release|Win32 {97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.ActiveCfg = Release|Win32
{01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.ActiveCfg = Debug|Win32 {97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.Build.0 = Release|Win32
{01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.Build.0 = Debug|Win32 {01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.ActiveCfg = Debug|Win32
{01E70176-B6C5-BF47-2C91-A949077BA323}.Release.ActiveCfg = Release|Win32 {01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.Build.0 = Debug|Win32
{01E70176-B6C5-BF47-2C91-A949077BA323}.Release.Build.0 = Release|Win32 {01E70176-B6C5-BF47-2C91-A949077BA323}.Release.ActiveCfg = Release|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.ActiveCfg = Debug|Win32 {01E70176-B6C5-BF47-2C91-A949077BA323}.Release.Build.0 = Release|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.Build.0 = Debug|Win32 {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.ActiveCfg = Debug|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.ActiveCfg = Release|Win32 {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.Build.0 = Debug|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.Build.0 = Release|Win32 {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.ActiveCfg = Release|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.ActiveCfg = Debug|Win32 {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.Build.0 = Release|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.Build.0 = Debug|Win32 {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.ActiveCfg = Debug|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.ActiveCfg = Release|Win32 {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.Build.0 = Debug|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.Build.0 = Release|Win32 {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.ActiveCfg = Release|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.ActiveCfg = Debug|Win32 {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.Build.0 = Release|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.Build.0 = Debug|Win32 {16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.ActiveCfg = Debug|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Release.ActiveCfg = Release|Win32 {16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.Build.0 = Debug|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Release.Build.0 = Release|Win32 {16909EE7-24AF-97C1-C76B-204B971BA959}.Release.ActiveCfg = Release|Win32
{07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.ActiveCfg = Debug|Win32 {16909EE7-24AF-97C1-C76B-204B971BA959}.Release.Build.0 = Release|Win32
{07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.Build.0 = Debug|Win32 {07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.ActiveCfg = Debug|Win32
{07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.ActiveCfg = Release|Win32 {07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.Build.0 = Debug|Win32
{07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.Build.0 = Release|Win32 {07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.ActiveCfg = Release|Win32
{1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.ActiveCfg = Debug|Win32 {07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.Build.0 = Release|Win32
{1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.Build.0 = Debug|Win32 {1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.ActiveCfg = Debug|Win32
{1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.ActiveCfg = Release|Win32 {1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.Build.0 = Debug|Win32
{1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.Build.0 = Release|Win32 {1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.ActiveCfg = Release|Win32
EndGlobalSection {1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.Build.0 = Release|Win32
GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection
EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution
GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection
EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobal EndGlobalSection
EndGlobal
=======
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list\list.vcproj", "{977B61B4-9968-497C-9F0B-24A8145473B8}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist", "slist\slist.vcproj", "{5A02061D-3728-4C49-AFC8-0130C1F161C0}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multiset", "multiset\multiset.vcproj", "{961F0E06-C092-4AF7-ABC5-2A49999F3B79}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_intrusivelib", "_intrusivelib\_intrusivelib.vcproj", "{90F3C5BD-8E6C-4629-BC71-A1009EC88059}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set", "set\set.vcproj", "{960E01F6-92C1-F74A-BCA5-2A9F3B994979}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_set", "unordered_set\unordered_set.vcproj", "{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_multiset", "unordered_multiset\unordered_multiset.vcproj", "{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "perf_test", "perf_test\perf_test.vcproj", "{910E70E6-2C91-AA67-BF4C-A9C74A309927}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "default_hook", "default_hook\default_hook.vcproj", "{761A79B4-9968-CB81-F02B-2A4497345475}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stateful_value_traits", "stateful_value_traits\stateful_value_traits.vcproj", "{9571A7B4-9968-B9C1-17FB-134547B46975}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "virtual_base", "virtual_base\virtual_base.vcproj", "{3579B1A4-9894-02AB-CB81-297B46154345}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_functions", "make_functions\make_functions.vcproj", "{7679B41B-F2B4-9176-CB81-35449467B435}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "custom_bucket_traits", "custom_bucket_traits\custom_bucket_traits.vcproj", "{31C77B84-0B2C-9481-CB81-27A149F33825}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "external_value_traits", "external_value_traits\external_value_traits.vcproj", "{97B69A72-B9D3-7389-17FB-74612F4A9543}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_multiset", "splay_multiset\splay_multiset.vcproj", "{01E70176-B6C5-BF47-2C91-A949077BA323}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_set", "splay_set\splay_set.vcproj", "{1E6909E7-C971-F24A-6C7B-A92094B71B59}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_multiset", "avl_multiset\avl_multiset.vcproj", "{0AE70176-5B8C-4BC7-392C-A4A312B07893}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_set", "avl_set\avl_set.vcproj", "{16909EE7-24AF-97C1-C76B-204B971BA959}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_multiset", "sg_multiset\sg_multiset.vcproj", "{07022E76-6CB5-92C1-B47F-A10772A79B43}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_set", "sg_set\sg_set.vcproj", "{1690A9E7-DB57-971C-F24A-09B752A942F7}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "any_hook", "any_test\any_test.vcproj", "{97B61B24-4C97-9681-50BF-243175A813B6}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectDependencies) = postSolution
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.ActiveCfg = Debug|Win32
{977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.Build.0 = Debug|Win32
{977B61B4-9968-497C-9F0B-24A8145473B8}.Release.ActiveCfg = Release|Win32
{977B61B4-9968-497C-9F0B-24A8145473B8}.Release.Build.0 = Release|Win32
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.ActiveCfg = Debug|Win32
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.Build.0 = Debug|Win32
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.ActiveCfg = Release|Win32
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.Build.0 = Release|Win32
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.ActiveCfg = Debug|Win32
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.Build.0 = Debug|Win32
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.ActiveCfg = Release|Win32
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.Build.0 = Release|Win32
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.ActiveCfg = Debug|Win32
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.Build.0 = Debug|Win32
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.ActiveCfg = Release|Win32
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.Build.0 = Release|Win32
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.ActiveCfg = Debug|Win32
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.Build.0 = Debug|Win32
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.ActiveCfg = Release|Win32
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.Build.0 = Release|Win32
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.ActiveCfg = Debug|Win32
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.Build.0 = Debug|Win32
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.ActiveCfg = Release|Win32
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.Build.0 = Release|Win32
{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.ActiveCfg = Debug|Win32
{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.Build.0 = Debug|Win32
{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.ActiveCfg = Release|Win32
{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.Build.0 = Release|Win32
{910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.ActiveCfg = Debug|Win32
{910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.Build.0 = Debug|Win32
{910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.ActiveCfg = Release|Win32
{910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.Build.0 = Release|Win32
{761A79B4-9968-CB81-F02B-2A4497345475}.Debug.ActiveCfg = Debug|Win32
{761A79B4-9968-CB81-F02B-2A4497345475}.Debug.Build.0 = Debug|Win32
{761A79B4-9968-CB81-F02B-2A4497345475}.Release.ActiveCfg = Release|Win32
{761A79B4-9968-CB81-F02B-2A4497345475}.Release.Build.0 = Release|Win32
{9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.ActiveCfg = Debug|Win32
{9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.Build.0 = Debug|Win32
{9571A7B4-9968-B9C1-17FB-134547B46975}.Release.ActiveCfg = Release|Win32
{9571A7B4-9968-B9C1-17FB-134547B46975}.Release.Build.0 = Release|Win32
{3579B1A4-9894-02AB-CB81-297B46154345}.Debug.ActiveCfg = Debug|Win32
{3579B1A4-9894-02AB-CB81-297B46154345}.Debug.Build.0 = Debug|Win32
{3579B1A4-9894-02AB-CB81-297B46154345}.Release.ActiveCfg = Release|Win32
{3579B1A4-9894-02AB-CB81-297B46154345}.Release.Build.0 = Release|Win32
{7679B41B-F2B4-9176-CB81-35449467B435}.Debug.ActiveCfg = Debug|Win32
{7679B41B-F2B4-9176-CB81-35449467B435}.Debug.Build.0 = Debug|Win32
{7679B41B-F2B4-9176-CB81-35449467B435}.Release.ActiveCfg = Release|Win32
{7679B41B-F2B4-9176-CB81-35449467B435}.Release.Build.0 = Release|Win32
{31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.ActiveCfg = Debug|Win32
{31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.Build.0 = Debug|Win32
{31C77B84-0B2C-9481-CB81-27A149F33825}.Release.ActiveCfg = Release|Win32
{31C77B84-0B2C-9481-CB81-27A149F33825}.Release.Build.0 = Release|Win32
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.ActiveCfg = Debug|Win32
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.Build.0 = Debug|Win32
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.ActiveCfg = Release|Win32
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.Build.0 = Release|Win32
{01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.ActiveCfg = Debug|Win32
{01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.Build.0 = Debug|Win32
{01E70176-B6C5-BF47-2C91-A949077BA323}.Release.ActiveCfg = Release|Win32
{01E70176-B6C5-BF47-2C91-A949077BA323}.Release.Build.0 = Release|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.ActiveCfg = Debug|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.Build.0 = Debug|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.ActiveCfg = Release|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.Build.0 = Release|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.ActiveCfg = Debug|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.Build.0 = Debug|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.ActiveCfg = Release|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.Build.0 = Release|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.ActiveCfg = Debug|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.Build.0 = Debug|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Release.ActiveCfg = Release|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Release.Build.0 = Release|Win32
{07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.ActiveCfg = Debug|Win32
{07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.Build.0 = Debug|Win32
{07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.ActiveCfg = Release|Win32
{07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.Build.0 = Release|Win32
{1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.ActiveCfg = Debug|Win32
{1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.Build.0 = Debug|Win32
{1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.ActiveCfg = Release|Win32
{1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.Build.0 = Release|Win32
{97B61B24-4C97-9681-50BF-243175A813B6}.Debug.ActiveCfg = Debug|Win32
{97B61B24-4C97-9681-50BF-243175A813B6}.Debug.Build.0 = Debug|Win32
{97B61B24-4C97-9681-50BF-243175A813B6}.Release.ActiveCfg = Release|Win32
{97B61B24-4C97-9681-50BF-243175A813B6}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal
>>>>>>> .merge-right.r46629

View File

@@ -105,6 +105,9 @@
Name="Header Files" Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd" Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath="..\..\..\..\..\boost\intrusive\any_hook.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\avl_set.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\avl_set.hpp">
</File> </File>
@@ -154,10 +157,7 @@
RelativePath="..\..\..\..\..\boost\intrusive\options.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\options.hpp">
</File> </File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_2_bits.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bits.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bit.hpp">
</File> </File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\rbtree.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\rbtree.hpp">
@@ -210,6 +210,9 @@
<Filter <Filter
Name="detail" Name="detail"
Filter=""> Filter="">
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\any_node_and_algorithms.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\assert.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\assert.hpp">
</File> </File>
@@ -240,9 +243,6 @@
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\mpl.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\mpl.hpp">
</File> </File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\no_exceptions_support.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\parent_from_member.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\parent_from_member.hpp">
</File> </File>
@@ -322,6 +322,9 @@
<File <File
RelativePath="..\..\..\example\doc_advanced_value_traits2.cpp"> RelativePath="..\..\..\example\doc_advanced_value_traits2.cpp">
</File> </File>
<File
RelativePath="..\..\..\example\doc_any_hook.cpp">
</File>
<File <File
RelativePath="..\..\..\example\doc_assoc_optimized_code.cpp"> RelativePath="..\..\..\example\doc_assoc_optimized_code.cpp">
</File> </File>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="any_hook"
ProjectGUID="{97B61B24-4C97-9681-50BF-243175A813B6}"
RootNamespace="any_hook"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../../../"
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
GeneratePreprocessedFile="0"
KeepComments="FALSE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="FALSE"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/any_hook.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/any_hook.pdb"
GenerateMapFile="FALSE"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../../../"
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="4"
DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/any_hook.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4737FFC1-76A6-A5C7-4376-2EA02C41523F}">
<File
RelativePath="..\..\..\test\any_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -127,16 +127,6 @@
RelativePath="..\..\..\test\list_test.cpp"> RelativePath="..\..\..\test\list_test.cpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@@ -121,16 +121,6 @@
RelativePath="..\..\..\test\multiset_test.cpp"> RelativePath="..\..\..\test\multiset_test.cpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@@ -122,16 +122,6 @@
RelativePath="..\..\..\perf\perf_list.cpp"> RelativePath="..\..\..\perf\perf_list.cpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{68B017A6-F80D6A2-084c-06A6-8A323C1ABD01}">
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@@ -121,16 +121,6 @@
RelativePath="..\..\..\test\set_test.cpp"> RelativePath="..\..\..\test\set_test.cpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{68007AB6-FDA6800-084c-B78A-8121AA3BBD01}">
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@@ -121,16 +121,6 @@
RelativePath="..\..\..\test\slist_test.cpp"> RelativePath="..\..\..\test\slist_test.cpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

37
proj/vc7ide/to-do.txt Normal file
View File

@@ -0,0 +1,37 @@
Implement incremental hashing:
bucket_len is power of two
cur_idx is always at least, half of bucket_len
find bucket from value:
size_type bucket_num = hash(val) &(bucket_len - 1);
if (bucket_num >= cur_idx)
bucket_num -= bucket_len/2;
incremental_rehash:
iterator _Plist, _Where;
if (load_factor > LoadFactorLimit)
{ // too dense, need to grow hash table
if (cur_idx >= (bucket_len - 1))
{ // table full, request doubling
return false;
}
else if (cur_idx >= bucket_len)
bucket_len*=2;
size_type bucket_num = cur_idx - bucket_len/2;
// rehash elements from bucket_num
++cur_idx;
}
insert from value:
size_type bucket_num = hash(val) & (bucket_len - 1);
if (bucket_num >= cur_idx)
bucket_num -= bucket_len/2;
insert in bucket
rehash:

View File

@@ -122,16 +122,6 @@
RelativePath="..\..\..\test\unordered_multiset_test.cpp"> RelativePath="..\..\..\test\unordered_multiset_test.cpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{99954380-9C8D-084c-4b04-62E52E6FBBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{6A181B76-FDA6800-8E8B-0A66-813A3BB1AD01}">
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@@ -121,16 +121,6 @@
RelativePath="..\..\..\test\unordered_set_test.cpp"> RelativePath="..\..\..\test\unordered_set_test.cpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{68AB0076-FDA6800-084c-06A6-8121AA3BBD01}">
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@@ -1,5 +1,5 @@
# Boost Intrusive Library Test Jamfile # Boost Intrusive Library Test Jamfile
# (C) Copyright Ion Gazta<EFBFBD>aga 2006. # (C) Copyright Ion Gaztanaga 2006.
# Use, modification and distribution are subject to the # Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file # Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

178
test/any_test.cpp Normal file
View File

@@ -0,0 +1,178 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (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.
//
/////////////////////////////////////////////////////////////////////////////
#include<boost/intrusive/detail/config_begin.hpp>
#include<boost/intrusive/any_hook.hpp>
#include<boost/intrusive/slist.hpp>
#include<boost/intrusive/rbtree.hpp>
#include<boost/intrusive/list.hpp>
#include<boost/intrusive/avltree.hpp>
#include<boost/intrusive/sgtree.hpp>
#include<boost/intrusive/splaytree.hpp>
#include<boost/intrusive/hashtable.hpp>
#include<boost/functional/hash.hpp>
#include <vector> //std::vector
#include <cstddef> //std::size_t
using namespace boost::intrusive;
class MyClass : public any_base_hook<>
{
int int_;
public:
//This is a member hook
any_member_hook<> member_hook_;
MyClass(int i = 0)
: int_(i)
{}
int get() const
{ return this->int_; }
friend bool operator < (const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator == (const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &o)
{ return boost::hash<int>()(o.get()); }
};
void instantiation_test()
{
typedef member_hook< MyClass, any_member_hook<>, &MyClass::member_hook_> MemberHook;
typedef base_hook< any_base_hook<> > BaseHook;
MyClass myclass;
{
slist < MyClass, any_to_slist_hook< BaseHook > > slist_base;
slist_base.push_front(myclass);
}
{
slist < MyClass, any_to_slist_hook< MemberHook > > slist_member;
slist_member.push_front(myclass);
}
{
list < MyClass, any_to_list_hook< BaseHook > > list_base;
list_base.push_front(myclass);
}
{
list < MyClass, any_to_list_hook< MemberHook > > list_member;
list_member.push_front(myclass);
}
{
rbtree < MyClass, any_to_set_hook< BaseHook > > rbtree_base;
rbtree_base.insert_unique(myclass);
}
{
rbtree < MyClass, any_to_set_hook< MemberHook > > rbtree_member;
rbtree_member.insert_unique(myclass);
}
{
avltree < MyClass, any_to_avl_set_hook< BaseHook > > avltree_base;
avltree_base.insert_unique(myclass);
}
{
avltree < MyClass, any_to_avl_set_hook< MemberHook > > avltree_member;
avltree_member.insert_unique(myclass);
}
{
sgtree < MyClass, any_to_bs_set_hook< BaseHook > > sgtree_base;
sgtree_base.insert_unique(myclass);
}
{
sgtree < MyClass, any_to_bs_set_hook< MemberHook > > sgtree_member;
sgtree_member.insert_unique(myclass);
}
{
splaytree < MyClass, any_to_bs_set_hook< BaseHook > > splaytree_base;
splaytree_base.insert_unique(myclass);
}
{
splaytree < MyClass, any_to_bs_set_hook< MemberHook > > splaytree_member;
splaytree_member.insert_unique(myclass);
}
typedef unordered_bucket<any_to_unordered_set_hook< BaseHook > >::type bucket_type;
typedef unordered_default_bucket_traits<any_to_unordered_set_hook< BaseHook > >::type bucket_traits;
bucket_type buckets[2];
{
hashtable < MyClass, any_to_unordered_set_hook< BaseHook > >
hashtable_base(bucket_traits(&buckets[0], 1));
hashtable_base.insert_unique(myclass);
}
{
hashtable < MyClass, any_to_unordered_set_hook< MemberHook > >
hashtable_member(bucket_traits(&buckets[1], 1));
hashtable_member.insert_unique(myclass);
}
}
bool simple_slist_test()
{
//Define an slist that will store MyClass using the public base hook
typedef any_to_slist_hook< base_hook< any_base_hook<> > >BaseOption;
typedef slist<MyClass, BaseOption, constant_time_size<false> > BaseList;
//Define an slist that will store MyClass using the public member hook
typedef any_to_slist_hook< member_hook<MyClass, any_member_hook<>, &MyClass::member_hook_> > MemberOption;
typedef slist<MyClass, MemberOption> MemberList;
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
BaseList baselist;
MemberList memberlist;
//Now insert them in the reverse order in the base hook list
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
baselist.push_front(*it);
//Now insert them in the same order as in vector in the member hook list
for(BaseList::iterator it(baselist.begin()), itend(baselist.end())
; it != itend; ++it){
memberlist.push_front(*it);
}
//Now test lists
{
BaseList::iterator bit(baselist.begin()), bitend(baselist.end());
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
VectRit rit(values.rbegin()), ritend(values.rend());
VectIt it(values.begin()), itend(values.end());
//Test the objects inserted in the base hook list
for(; rit != ritend; ++rit, ++bit)
if(&*bit != &*rit) return false;
//Test the objects inserted in the member hook list
for(; it != itend; ++it, ++mit)
if(&*mit != &*it) return false;
}
return true;
}
int main()
{
if(!simple_slist_test())
return 1;
instantiation_test();
return 0;
}
#include <boost/intrusive/detail/config_end.hpp>

View File

@@ -108,7 +108,6 @@ class test_main_template<VoidPointer, false>
int main( int, char* [] ) int main( int, char* [] )
{ {
test_main_template<void*, false>()(); test_main_template<void*, false>()();
test_main_template<boost::intrusive::smart_ptr<void>, false>()(); test_main_template<boost::intrusive::smart_ptr<void>, false>()();
test_main_template<void*, true>()(); test_main_template<void*, true>()();

View File

@@ -41,6 +41,14 @@ class new_cloner
{ return new T(t); } { return new T(t); }
}; };
template<class T>
class new_default_factory
{
public:
T *operator()()
{ return new T(); }
};
} //namespace test { } //namespace test {
} //namespace intrusive { } //namespace intrusive {
} //namespace boost { } //namespace boost {

View File

@@ -52,8 +52,37 @@ struct test_generic_assoc
static void test_rebalance(std::vector<value_type>& values); static void test_rebalance(std::vector<value_type>& values);
static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::true_type); static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::true_type);
static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::false_type); static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::false_type);
static void test_container_from_iterator(std::vector<value_type>& values);
}; };
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::
test_container_from_iterator(std::vector<value_type>& values)
{
typedef typename ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
>::type assoc_type;
assoc_type testset(values.begin(), values.end());
typedef typename assoc_type::iterator it_type;
typedef typename assoc_type::const_iterator cit_type;
typedef typename assoc_type::size_type sz_type;
sz_type sz = testset.size();
for(it_type b(testset.begin()), e(testset.end()); b != e; ++b)
{
assoc_type &s = assoc_type::container_from_iterator(b);
const assoc_type &cs = assoc_type::container_from_iterator(cit_type(b));
BOOST_TEST(&s == &cs);
BOOST_TEST(&s == &testset);
s.erase(b);
BOOST_TEST(testset.size() == (sz-1));
s.insert(*b);
BOOST_TEST(testset.size() == sz);
}
}
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner> template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst() void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst()
{ {
@@ -103,12 +132,14 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst(
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner> template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(std::vector<typename ValueTraits::value_type>& values) void test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type;
test_clone(values); test_clone(values);
test_container_from_end(values); test_container_from_end(values);
test_splay_up(values); test_splay_up(values);
test_splay_down(values); test_splay_down(values);
test_rebalance(values); test_rebalance(values);
test_insert_erase_burst(); test_insert_erase_burst();
test_container_from_iterator(values);
} }
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner> template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>

View File

@@ -35,6 +35,7 @@ struct test_generic_set
static void test_impl(); static void test_impl();
}; };
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner> template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_all() void test_generic_set<ValueTraits, ContainerDefiner>::test_all()
{ {

View File

@@ -126,20 +126,30 @@ template<class VoidPointer>
struct uset_auto_base_hook_type struct uset_auto_base_hook_type
{ {
typedef unordered_set_base_hook typedef unordered_set_base_hook
< link_mode<auto_unlink>, void_pointer<VoidPointer> < link_mode<auto_unlink>
, tag<my_tag>, store_hash<true> > type; , void_pointer<VoidPointer>
, tag<my_tag>
, store_hash<true>
> type;
}; };
template<class VoidPointer> template<class VoidPointer>
struct uset_member_hook_type struct uset_member_hook_type
{ typedef unordered_set_member_hook<void_pointer<VoidPointer> > type; }; {
typedef unordered_set_member_hook
< void_pointer<VoidPointer>
, optimize_multikey<true>
> type;
};
template<class VoidPointer> template<class VoidPointer>
struct uset_auto_member_hook_type struct uset_auto_member_hook_type
{ {
typedef unordered_set_member_hook typedef unordered_set_member_hook
< link_mode<auto_unlink>, void_pointer<VoidPointer> < link_mode<auto_unlink>, void_pointer<VoidPointer>
, store_hash<true> > type; , store_hash<true>
, optimize_multikey<true>
> type;
}; };
template<class VoidPointer, bool ConstantTimeSize> template<class VoidPointer, bool ConstantTimeSize>
@@ -318,6 +328,49 @@ struct testvalue
slist_auto_node_.swap_nodes(other.slist_auto_node_); slist_auto_node_.swap_nodes(other.slist_auto_node_);
} }
bool is_linked() const
{
//Set
return set_base_hook_t::is_linked() ||
set_auto_base_hook_t::is_linked() ||
set_node_.is_linked() ||
set_auto_node_.is_linked() ||
//SplaySet
splay_set_base_hook_t::is_linked() ||
splay_set_auto_base_hook_t::is_linked() ||
splay_set_node_.is_linked() ||
splay_set_auto_node_.is_linked() ||
//ScapeoatSet
bs_set_base_hook_t::is_linked() ||
sg_set_node_.is_linked() ||
//AvlSet
avl_set_base_hook_t::is_linked() ||
avl_set_auto_base_hook_t::is_linked() ||
avl_set_node_.is_linked() ||
avl_set_auto_node_.is_linked() ||
//Unordered set
unordered_set_base_hook_t::is_linked() ||
unordered_set_auto_base_hook_t::is_linked() ||
unordered_set_node_.is_linked() ||
unordered_set_auto_node_.is_linked() ||
//List
list_base_hook_t::is_linked() ||
list_auto_base_hook_t::is_linked() ||
list_node_.is_linked() ||
list_auto_node_.is_linked() ||
//Slist
slist_base_hook_t::is_linked() ||
slist_auto_base_hook_t::is_linked() ||
slist_node_.is_linked() ||
slist_auto_node_.is_linked();
}
~testvalue() ~testvalue()
{} {}

View File

@@ -229,6 +229,7 @@ void test_list<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
} }
template<class ValueTraits> template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>
::test_shift(std::vector<typename ValueTraits::value_type>& values) ::test_shift(std::vector<typename ValueTraits::value_type>& values)

View File

@@ -315,7 +315,7 @@ void test_slist<ValueTraits, Linear, CacheLast>
testlist.erase (++testlist.begin(), testlist.end()); testlist.erase (++testlist.begin(), testlist.end());
BOOST_TEST (testlist.size() == 1); BOOST_TEST (testlist.size() == 1);
BOOST_TEST (testlist.front().value_ == 3); BOOST_TEST (testlist.front().value_ == 3);
} }
template<class ValueTraits, bool Linear, bool CacheLast> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear, CacheLast> void test_slist<ValueTraits, Linear, CacheLast>

View File

@@ -12,8 +12,7 @@
#define BOOST_INTRUSIVE_SMART_PTR_HPP #define BOOST_INTRUSIVE_SMART_PTR_HPP
#include <boost/iterator.hpp> #include <boost/iterator.hpp>
#include <boost/intrusive/pointer_plus_bit.hpp> #include <boost/intrusive/pointer_plus_bits.hpp>
#include <boost/intrusive/pointer_plus_2_bits.hpp>
#if (defined _MSC_VER) && (_MSC_VER >= 1200) #if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once # pragma once
@@ -109,7 +108,7 @@ class smart_ptr
public: //Public Functions public: //Public Functions
//!Constructor from raw pointer (allows "0" pointer conversion). Never throws. //!Constructor from raw pointer (allows "0" pointer conversion). Never throws.
smart_ptr(pointer ptr = 0) explicit smart_ptr(pointer ptr = 0)
: m_ptr(ptr) : m_ptr(ptr)
{} {}
@@ -351,67 +350,34 @@ namespace boost{
//for intrusive containers, saving space //for intrusive containers, saving space
namespace intrusive { namespace intrusive {
template<std::size_t N> template<std::size_t Alignment>
struct has_pointer_plus_bit<smart_ptr<void>, N> struct max_pointer_plus_bits<smart_ptr<void>, Alignment>
{ {
static const bool value = has_pointer_plus_bit<void*, N>::value; static const std::size_t value = max_pointer_plus_bits<void*, Alignment>::value;
}; };
//Specialization template<class T, std::size_t NumBits>
template<class T> struct pointer_plus_bits<smart_ptr<T>, NumBits>
struct pointer_plus_bit<smart_ptr<T> >
{ {
typedef smart_ptr<T> pointer; typedef smart_ptr<T> pointer;
static pointer get_pointer(const pointer &n) static pointer get_pointer(const pointer &n)
{ return pointer_plus_bit<T*>::get_pointer(n.get()); } { return pointer_plus_bits<T*, NumBits>::get_pointer(n.get()); }
static void set_pointer(pointer &n, pointer p) static void set_pointer(pointer &n, pointer p)
{ {
T *raw_n = n.get(); T *raw_n = n.get();
pointer_plus_bit<T*>::set_pointer(raw_n, p.get()); pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.get());
n = raw_n;
}
static bool get_bit(const pointer &n)
{ return pointer_plus_bit<T*>::get_bit(n.get()); }
static void set_bit(pointer &n, bool c)
{
T *raw_n = n.get();
pointer_plus_bit<T*>::set_bit(raw_n, c);
n = raw_n;
}
};
template<std::size_t N>
struct has_pointer_plus_2_bits<smart_ptr<void>, N>
{
static const bool value = has_pointer_plus_2_bits<void*, N>::value;
};
template<class T>
struct pointer_plus_2_bits<smart_ptr<T> >
{
typedef smart_ptr<T> pointer;
static pointer get_pointer(const pointer &n)
{ return pointer_plus_2_bits<T*>::get_pointer(n.get()); }
static void set_pointer(pointer &n, pointer p)
{
T *raw_n = n.get();
pointer_plus_2_bits<T*>::set_pointer(raw_n, p.get());
n = raw_n; n = raw_n;
} }
static std::size_t get_bits(const pointer &n) static std::size_t get_bits(const pointer &n)
{ return pointer_plus_2_bits<T*>::get_bits(n.get()); } { return pointer_plus_bits<T*, NumBits>::get_bits(n.get()); }
static void set_bits(pointer &n, std::size_t c) static void set_bits(pointer &n, std::size_t c)
{ {
T *raw_n = n.get(); T *raw_n = n.get();
pointer_plus_2_bits<T*>::set_bits(raw_n, c); pointer_plus_bits<T*, NumBits>::set_bits(raw_n, c);
n = raw_n; n = raw_n;
} }
}; };

View File

@@ -10,7 +10,6 @@
// See http://www.boost.org/libs/intrusive for documentation. // See http://www.boost.org/libs/intrusive for documentation.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/detail/config_begin.hpp> #include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/unordered_set.hpp> #include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
@@ -18,6 +17,7 @@
#include "smart_ptr.hpp" #include "smart_ptr.hpp"
#include "common_functors.hpp" #include "common_functors.hpp"
#include <vector> #include <vector>
#include <algorithm> //std::sort std::find
#include <set> #include <set>
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp" #include "test_macros.hpp"
@@ -27,7 +27,7 @@ using namespace boost::intrusive;
static const std::size_t BucketSize = 11; static const std::size_t BucketSize = 11;
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
struct test_unordered_multiset struct test_unordered_multiset
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -41,14 +41,16 @@ struct test_unordered_multiset
static void test_clone(std::vector<value_type>& values); static void test_clone(std::vector<value_type>& values);
}; };
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_all (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset typedef unordered_multiset
<value_type < value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_multiset_type; > unordered_multiset_type;
{ {
typedef typename unordered_multiset_type::bucket_traits bucket_traits; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -76,14 +78,16 @@ void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueT
} }
//test case due to an error in tree implementation: //test case due to an error in tree implementation:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits>::test_impl() void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_impl()
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset typedef unordered_multiset
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -106,14 +110,16 @@ void test_unordered_multiset<ValueTraits>::test_impl()
} }
//test: constructor, iterator, clear, reverse_iterator, front, back, size: //test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset typedef unordered_multiset
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -127,104 +133,190 @@ void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueT
} }
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to: //test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset typedef unordered_multiset
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typedef typename unordered_multiset_type::iterator iterator;
{
typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
typename unordered_multiset_type::bucket_type buckets [BucketSize]; testset.insert(&values[0] + 2, &values[0] + 5);
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
testset.insert(&values[0] + 2, &values[0] + 5); const unordered_multiset_type& const_testset = testset;
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
const unordered_multiset_type& const_testset = testset; typename unordered_multiset_type::iterator i = testset.begin();
{ int init_values [] = { 1, 4, 5 }; BOOST_TEST (i->value_ == 1);
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
typename unordered_multiset_type::iterator i = testset.begin(); i = testset.insert (values[0]);
BOOST_TEST (i->value_ == 1); BOOST_TEST (&*i == &values[0]);
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase(i);
i = testset.insert (values[0]); { int init_values [] = { 1, 3, 5 };
BOOST_TEST (&*i == &values[0]); TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
testset.clear();
i = testset.iterator_to (values[2]); testset.insert(&values[0], &values[0] + values.size());
BOOST_TEST (&*i == &values[2]);
testset.erase(i);
{ int init_values [] = { 1, 3, 5 }; { int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
testset.clear();
testset.insert(&values[0], &values[0] + values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 }; BOOST_TEST (testset.erase(1) == 1);
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); } BOOST_TEST (testset.erase(2) == 2);
BOOST_TEST (testset.erase(3) == 1);
BOOST_TEST (testset.erase(4) == 1);
BOOST_TEST (testset.erase(5) == 1);
BOOST_TEST (testset.empty() == true);
BOOST_TEST (testset.erase(1) == 1); //Now with a single bucket
BOOST_TEST (testset.erase(2) == 2); typename unordered_multiset_type::bucket_type single_bucket[1];
BOOST_TEST (testset.erase(3) == 1); unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
BOOST_TEST (testset.erase(4) == 1); testset2.insert(&values[0], &values[0] + values.size());
BOOST_TEST (testset.erase(5) == 1); BOOST_TEST (testset2.erase(5) == 1);
BOOST_TEST (testset.empty() == true); BOOST_TEST (testset2.erase(2) == 2);
BOOST_TEST (testset2.erase(1) == 1);
BOOST_TEST (testset2.erase(4) == 1);
BOOST_TEST (testset2.erase(3) == 1);
BOOST_TEST (testset2.empty() == true);
}
{
//Now erase just one per loop
const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 };
const unsigned int random_size = sizeof(random_init)/sizeof(random_init[0]);
typename unordered_multiset_type::bucket_type single_bucket[1];
for(unsigned int i = 0, max = random_size; i != max; ++i){
std::vector<typename ValueTraits::value_type> data (random_size);
for (unsigned int j = 0; j < random_size; ++j)
data[j].value_ = random_init[j];
unordered_multiset_type testset_new(bucket_traits(single_bucket, 1));
testset_new.insert(&data[0], &data[0]+max);
testset_new.erase(testset_new.iterator_to(data[i]));
BOOST_TEST (testset_new.size() == (max -1));
}
}
{
typename unordered_multiset_type::bucket_type buckets [BucketSize];
const unsigned int NumBucketSize = BucketSize;
const unsigned int LoadFactor = 3;
const unsigned int NumIterations = NumBucketSize*LoadFactor;
std::vector<value_type> random_init(NumIterations);//Preserve memory
std::vector<value_type> set_tester;
set_tester.reserve(NumIterations);
//Now with a single bucket //Initialize values
typename unordered_multiset_type::bucket_type single_bucket[1]; for (unsigned int i = 0; i < NumIterations; ++i){
unordered_multiset_type testset2(bucket_traits(single_bucket, 1)); random_init[i].value_ = i*2;//(i/LoadFactor)*LoadFactor;
testset2.insert(&values[0], &values[0] + values.size()); }
BOOST_TEST (testset2.erase(5) == 1);
BOOST_TEST (testset2.erase(2) == 2); for(unsigned int initial_pos = 0; initial_pos != (NumIterations+1); ++initial_pos){
BOOST_TEST (testset2.erase(1) == 1); for(unsigned int final_pos = initial_pos; final_pos != (NumIterations+1); ++final_pos){
BOOST_TEST (testset2.erase(4) == 1);
BOOST_TEST (testset2.erase(3) == 1); //Create intrusive container inserting values
BOOST_TEST (testset2.empty() == true); unordered_multiset_type testset
( &random_init[0]
, &random_init[0] + random_init.size()
, bucket_traits(buckets, NumBucketSize));
BOOST_TEST (testset.size() == random_init.size());
//Obtain the iterator range to erase
iterator it_beg_pos = testset.begin();
for(unsigned int it_beg_pos_num = 0; it_beg_pos_num != initial_pos; ++it_beg_pos_num){
++it_beg_pos;
}
iterator it_end_pos(it_beg_pos);
for(unsigned int it_end_pos_num = 0; it_end_pos_num != (final_pos - initial_pos); ++it_end_pos_num){
++it_end_pos;
}
//Erase the same values in both the intrusive and original vector
std::size_t erased_cnt = std::distance(it_beg_pos, it_end_pos);
//Erase values from the intrusive container
testset.erase(it_beg_pos, it_end_pos);
BOOST_TEST (testset.size() == (random_init.size()-(final_pos - initial_pos)));
//Now test...
BOOST_TEST ((random_init.size() - erased_cnt) == testset.size());
//Create an ordered copy of the intrusive container
set_tester.insert(set_tester.end(), testset.begin(), testset.end());
std::sort(set_tester.begin(), set_tester.end());
{
typename std::vector<value_type>::iterator it = set_tester.begin(), itend = set_tester.end();
typename std::vector<value_type>::iterator random_init_it(random_init.begin());
for( ; it != itend; ++it){
while(!random_init_it->is_linked())
++random_init_it;
BOOST_TEST(*it == *random_init_it);
++random_init_it;
}
}
set_tester.clear();
}
}
}
} }
//test: insert (seq-version), swap, erase (seq-version), size: //test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset typedef unordered_multiset
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typename unordered_multiset_type::bucket_type buckets [BucketSize]; typename unordered_multiset_type::bucket_type buckets [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize]; {
unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize)); typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize)); unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
testset2.insert (&values[0] + 2, &values[0] + 6); testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2); testset1.swap (testset2);
{ int init_values [] = { 1, 2, 4, 5 }; { int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
{ int init_values [] = { 2, 3 }; { int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
testset1.erase (testset1.iterator_to(values[5]), testset1.end()); BOOST_TEST (testset1.size() == 1);
BOOST_TEST (testset1.size() == 1); // BOOST_TEST (&testset1.front() == &values[3]);
// BOOST_TEST (&testset1.front() == &values[3]); BOOST_TEST (&*testset1.begin() == &values[3]);
BOOST_TEST (&*testset1.begin() == &values[3]); }
} }
//test: rehash: //test: rehash:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset typedef unordered_multiset
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -261,14 +353,16 @@ void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename Valu
} }
//test: find, equal_range (lower_bound, upper_bound): //test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_find(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset typedef unordered_multiset
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -293,8 +387,8 @@ void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueT
} }
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits> void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -302,6 +396,8 @@ void test_unordered_multiset<ValueTraits>
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
{ {
@@ -373,6 +469,8 @@ class test_main_template
< value_type < value_type
, typename value_type::unordered_set_base_hook_t , typename value_type::unordered_set_base_hook_t
>::type >::type
, true
, false
>::test_all(data); >::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits test_unordered_multiset < typename detail::get_member_value_traits
@@ -382,6 +480,8 @@ class test_main_template
, &value_type::unordered_set_node_ , &value_type::unordered_set_node_
> >
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
return 0; return 0;
@@ -404,6 +504,8 @@ class test_main_template<VoidPointer, false>
< value_type < value_type
, typename value_type::unordered_set_base_hook_t , typename value_type::unordered_set_base_hook_t
>::type >::type
, true
, false
>::test_all(data); >::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits test_unordered_multiset < typename detail::get_member_value_traits
@@ -413,12 +515,16 @@ class test_main_template<VoidPointer, false>
, &value_type::unordered_set_node_ , &value_type::unordered_set_node_
> >
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
test_unordered_multiset < typename detail::get_base_value_traits test_unordered_multiset < typename detail::get_base_value_traits
< value_type < value_type
, typename value_type::unordered_set_auto_base_hook_t , typename value_type::unordered_set_auto_base_hook_t
>::type >::type
, true
, true
>::test_all(data); >::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits test_unordered_multiset < typename detail::get_member_value_traits
@@ -428,6 +534,8 @@ class test_main_template<VoidPointer, false>
, &value_type::unordered_set_auto_node_ , &value_type::unordered_set_auto_node_
> >
>::type >::type
, false
, true
>::test_all(data); >::test_all(data);
return 0; return 0;
} }

View File

@@ -26,7 +26,7 @@ using namespace boost::intrusive;
static const std::size_t BucketSize = 11; static const std::size_t BucketSize = 11;
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
struct test_unordered_set struct test_unordered_set
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -40,14 +40,16 @@ struct test_unordered_set
static void test_clone(std::vector<value_type>& values); static void test_clone(std::vector<value_type>& values);
}; };
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_all(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_set typedef unordered_set
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits; typedef typename unordered_set_type::bucket_traits bucket_traits;
{ {
@@ -75,14 +77,16 @@ void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits:
} }
//test case due to an error in tree implementation: //test case due to an error in tree implementation:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits>::test_impl() void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_impl()
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_set typedef unordered_set
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits; typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -103,14 +107,16 @@ void test_unordered_set<ValueTraits>::test_impl()
} }
//test: constructor, iterator, clear, reverse_iterator, front, back, size: //test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_set typedef unordered_set
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits; typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -126,14 +132,16 @@ void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits
} }
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to: //test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_set typedef unordered_set
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits; typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -161,14 +169,16 @@ void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTrai
} }
//test: insert (seq-version), swap, erase (seq-version), size: //test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_set typedef unordered_set
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits; typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -192,14 +202,16 @@ void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits
} }
//test: rehash: //test: rehash:
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_set typedef unordered_set
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits; typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -237,14 +249,16 @@ void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTrai
//test: find, equal_range (lower_bound, upper_bound): //test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_find(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef unordered_set typedef unordered_set
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits; typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -267,8 +281,8 @@ void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits
BOOST_TEST (testset.find (cmp_val) == testset.end()); BOOST_TEST (testset.find (cmp_val) == testset.end());
} }
template<class ValueTraits> template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits> void test_unordered_set<ValueTraits, CacheBegin, CompareHash>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -276,6 +290,8 @@ void test_unordered_set<ValueTraits>
<value_type <value_type
, value_traits<ValueTraits> , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits; typedef typename unordered_set_type::bucket_traits bucket_traits;
{ {
@@ -347,6 +363,8 @@ class test_main_template
< value_type < value_type
, typename value_type::unordered_set_base_hook_t , typename value_type::unordered_set_base_hook_t
>::type >::type
, true
, false
>::test_all(data); >::test_all(data);
test_unordered_set < typename detail::get_member_value_traits test_unordered_set < typename detail::get_member_value_traits
< value_type < value_type
@@ -355,6 +373,8 @@ class test_main_template
, &value_type::unordered_set_node_ , &value_type::unordered_set_node_
> >
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
return 0; return 0;
@@ -377,6 +397,8 @@ class test_main_template<VoidPointer, false>
< value_type < value_type
, typename value_type::unordered_set_base_hook_t , typename value_type::unordered_set_base_hook_t
>::type >::type
, true
, false
>::test_all(data); >::test_all(data);
test_unordered_set < typename detail::get_member_value_traits test_unordered_set < typename detail::get_member_value_traits
@@ -386,12 +408,16 @@ class test_main_template<VoidPointer, false>
, &value_type::unordered_set_node_ , &value_type::unordered_set_node_
> >
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
test_unordered_set < typename detail::get_base_value_traits test_unordered_set < typename detail::get_base_value_traits
< value_type < value_type
, typename value_type::unordered_set_auto_base_hook_t , typename value_type::unordered_set_auto_base_hook_t
>::type >::type
, true
, true
>::test_all(data); >::test_all(data);
test_unordered_set < typename detail::get_member_value_traits test_unordered_set < typename detail::get_member_value_traits
@@ -401,6 +427,8 @@ class test_main_template<VoidPointer, false>
, &value_type::unordered_set_auto_node_ , &value_type::unordered_set_auto_node_
> >
>::type >::type
, false
, true
>::test_all(data); >::test_all(data);
return 0; return 0;
} }