From 4ba719bdb81a27fe690de0cc0a23ca7312054bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 15 Sep 2013 19:54:19 +0000 Subject: [PATCH 01/18] Added BOOST_NO_INT64_T protection for sqrt2_pow_max 64 bit specialization [SVN r85689] --- include/boost/intrusive/detail/utilities.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index 5e6abdb..ab7b02c 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -429,6 +429,8 @@ struct sqrt2_pow_max >::t static const std::size_t pow = 31; }; +#ifndef BOOST_NO_INT64_T + template struct sqrt2_pow_max >::type> { @@ -436,6 +438,8 @@ struct sqrt2_pow_max >::t static const std::size_t pow = 63; }; +#endif //BOOST_NO_INT64_T + // Returns floor(pow(sqrt(2), x * 2 + 1)). // Defined for X from 0 up to the number of bits in size_t minus 1. inline std::size_t sqrt2_pow_2xplus1 (std::size_t x) From 02ddd12716bf9c982e4a722c3245439c0234b987 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 26 Sep 2013 13:02:51 +0000 Subject: [PATCH 02/18] Remove obsolete MSVC check from pragma guard git grep -h -B1 "^#\s*pragma once" | grep -v pragma | sort | uniq is now clean. [SVN r85952] --- include/boost/intrusive/detail/assert.hpp | 2 +- include/boost/intrusive/detail/memory_util.hpp | 2 +- include/boost/intrusive/detail/preprocessor.hpp | 2 +- include/boost/intrusive/pointer_traits.hpp | 2 +- test/smart_ptr.hpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/intrusive/detail/assert.hpp b/include/boost/intrusive/detail/assert.hpp index 3dacbcc..d75d225 100644 --- a/include/boost/intrusive/detail/assert.hpp +++ b/include/boost/intrusive/detail/assert.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_INTRUSIVE_DETAIL_ASSERT_HPP #define BOOST_INTRUSIVE_DETAIL_ASSERT_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif diff --git a/include/boost/intrusive/detail/memory_util.hpp b/include/boost/intrusive/detail/memory_util.hpp index bfc9b14..e644ebc 100644 --- a/include/boost/intrusive/detail/memory_util.hpp +++ b/include/boost/intrusive/detail/memory_util.hpp @@ -17,7 +17,7 @@ #ifndef BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP #define BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/intrusive/detail/preprocessor.hpp b/include/boost/intrusive/detail/preprocessor.hpp index b3ed6e6..b8143a4 100644 --- a/include/boost/intrusive/detail/preprocessor.hpp +++ b/include/boost/intrusive/detail/preprocessor.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTRUSIVE_DETAIL_PREPROCESSOR_HPP #define BOOST_INTRUSIVE_DETAIL_PREPROCESSOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/intrusive/pointer_traits.hpp b/include/boost/intrusive/pointer_traits.hpp index 21b14a1..beebe6b 100644 --- a/include/boost/intrusive/pointer_traits.hpp +++ b/include/boost/intrusive/pointer_traits.hpp @@ -17,7 +17,7 @@ #ifndef BOOST_INTRUSIVE_POINTER_TRAITS_HPP #define BOOST_INTRUSIVE_POINTER_TRAITS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/test/smart_ptr.hpp b/test/smart_ptr.hpp index cea8e90..c226b5b 100644 --- a/test/smart_ptr.hpp +++ b/test/smart_ptr.hpp @@ -16,7 +16,7 @@ #include #include -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if (defined _MSC_VER) # pragma once #endif From 2b34e74562ed3f004371d85daf31736cf39d74a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 11 Nov 2013 22:21:22 +0000 Subject: [PATCH 03/18] Fixes #9332 [SVN r86626] --- .../has_member_function_callable_with.hpp | 13 +++++++++++-- test/has_member_function_callable_with.cpp | 18 +++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/boost/intrusive/detail/has_member_function_callable_with.hpp b/include/boost/intrusive/detail/has_member_function_callable_with.hpp index be4a015..d86231c 100644 --- a/include/boost/intrusive/detail/has_member_function_callable_with.hpp +++ b/include/boost/intrusive/detail/has_member_function_callable_with.hpp @@ -195,6 +195,8 @@ static const bool value = false; }; + #ifdef BOOST_NO_CXX11_DECLTYPE + //Special case for 0 args template< class F , std::size_t N = @@ -215,14 +217,21 @@ BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); }; + #endif //#ifdef BOOST_NO_CXX11_DECLTYPE + template struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) { + #ifndef BOOST_NO_CXX11_DECLTYPE + template().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()) > + static boost_intrusive_has_member_function_callable_with::yes_type Test(Fun*); + #else template - static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)*); - + #endif + template static boost_intrusive_has_member_function_callable_with::no_type Test(...); diff --git a/test/has_member_function_callable_with.cpp b/test/has_member_function_callable_with.cpp index 96b822e..0036c3f 100644 --- a/test/has_member_function_callable_with.cpp +++ b/test/has_member_function_callable_with.cpp @@ -68,7 +68,7 @@ class has_member_function_named_func }}} -#if !defined(BOOST_CONTAINER_PERFECT_FORWARDING) +#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) namespace boost{ namespace intrusive{ @@ -259,7 +259,7 @@ class has_member_function_named_func }}} -#else +#else //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) namespace boost{ namespace intrusive{ @@ -283,6 +283,7 @@ class has_member_function_named_func namespace intrusive{ namespace intrusive_detail{ + #ifdef BOOST_NO_CXX11_DECLTYPE template().func(), 0)> struct zeroarg_checker_func { @@ -299,12 +300,19 @@ class has_member_function_named_func zeroarg_checker_func(int); }; + #endif //BOOST_NO_CXX11_DECLTYPE + template struct has_member_function_callable_with_func_impl { - template - static zeroarg_checker_func Test(zeroarg_checker_func*); + #ifndef BOOST_NO_CXX11_DECLTYPE + template().func()) > + static boost_intrusive_has_member_function_callable_with::yes_type Test(U*); + #else + template + static zeroarg_checker_func Test(zeroarg_checker_func*); + #endif template static has_member_function_callable_with::no_type Test(...); @@ -356,7 +364,7 @@ class has_member_function_named_func }}} -#endif +#endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) struct functor { From 8c689df5b896d17fd34f2b0a498e2cb00ee042c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 12 Nov 2013 16:14:52 +0000 Subject: [PATCH 04/18] Updated changelog with #9332 [SVN r86652] --- doc/intrusive.qbk | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index c84700c..fdcbaf7 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3884,6 +3884,13 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes Release Notes] +[section:release_notes_boost_1_56_00 Boost 1.56 Release] + +* Fixed bugs: + * [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]]. + +[endsect] + [section:release_notes_boost_1_55_00 Boost 1.55 Release] * [*Source breaking]: Deprecated `xxx_dont_splay` functions from splay containers. From 1f5031f3106ad988158e55e3865ec7bd98d8c621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 18 Nov 2013 09:32:44 +0000 Subject: [PATCH 05/18] Fixes #9338 [SVN r86748] --- .../has_member_function_callable_with.hpp | 222 ++++++++++-------- .../boost/intrusive/detail/memory_util.hpp | 8 +- test/common_functors.hpp | 3 +- test/has_member_function_callable_with.cpp | 4 +- 4 files changed, 126 insertions(+), 111 deletions(-) diff --git a/include/boost/intrusive/detail/has_member_function_callable_with.hpp b/include/boost/intrusive/detail/has_member_function_callable_with.hpp index d86231c..12eec96 100644 --- a/include/boost/intrusive/detail/has_member_function_callable_with.hpp +++ b/include/boost/intrusive/detail/has_member_function_callable_with.hpp @@ -70,11 +70,11 @@ #error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END not defined!" #endif - #if BOOST_PP_ITERATION_START() != 0 - #error "BOOST_PP_ITERATION_START() must be zero (0)" + #if BOOST_PP_ITERATION_START() > BOOST_PP_ITERATION_FINISH() + #error "BOOST_PP_ITERATION_START() must be <= BOOST_PP_ITERATION_FINISH()" #endif - #if BOOST_PP_ITERATION() == 0 + #if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_START() BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN @@ -114,6 +114,119 @@ }; //! + #else //!defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) + + template + struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl); + + template + struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) + + { + static const bool value = false; + }; + + #ifdef BOOST_NO_CXX11_DECLTYPE + + //Special case for 0 args + template< class F + , std::size_t N = + sizeof((boost::move_detail::declval(). + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))> + struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + { + boost_intrusive_has_member_function_callable_with::yes_type dummy; + BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); + }; + + //For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not + //SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0. + template + struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + { + boost_intrusive_has_member_function_callable_with::no_type dummy; + BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); + }; + + #endif //#ifdef BOOST_NO_CXX11_DECLTYPE + + template + struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) + + { + #ifndef BOOST_NO_CXX11_DECLTYPE + template().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()) > + static boost_intrusive_has_member_function_callable_with::yes_type Test(U*); + #else + template + static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)*); + #endif + + template + static boost_intrusive_has_member_function_callable_with::no_type Test(...); + + static const bool value = sizeof(Test< Fun >(0)) + == sizeof(boost_intrusive_has_member_function_callable_with::yes_type); + }; + + template + struct BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME ) + : Fun + { + BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )(); + using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME; + + boost_intrusive_has_member_function_callable_with::private_type + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME + ( DontCares...) const; + }; + + template + struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl) + + { + template + struct make_dontcare + { + typedef boost_intrusive_has_member_function_callable_with::dont_care type; + }; + + typedef BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME ) + ::type...> FunWrap; + + static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) == + sizeof(boost_intrusive_has_member_function_callable_with::is_private_type + ( (::boost::move_detail::declval< FunWrap >(). + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME + ( ::boost::move_detail::declval()... ), 0) ) + ) + ); + }; + + template + struct BOOST_PP_CAT( has_member_function_callable_with_ + , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + : public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_ + , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) + < Fun + , BOOST_PP_CAT( has_member_function_named_ + , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )::value + , Args... > + {}; + + #endif //!defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) + + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END + + #endif //BOOST_PP_ITERATION() == BOOST_PP_ITERATION_START() + + #if BOOST_PP_ITERATION() == 0 + + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN + + #if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) + #if !defined(_MSC_VER) || (_MSC_VER < 1600) #if defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED) @@ -171,9 +284,9 @@ { template - static decltype( boost::move_detail::declval().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME() + static decltype( boost::move_detail::declval().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME() , boost_intrusive_has_member_function_callable_with::yes_type()) - Test(Fun*); + Test(U*); template static boost_intrusive_has_member_function_callable_with::no_type Test(...); @@ -185,105 +298,6 @@ #else //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) - template - struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl); - - template - struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) - - { - static const bool value = false; - }; - - #ifdef BOOST_NO_CXX11_DECLTYPE - - //Special case for 0 args - template< class F - , std::size_t N = - sizeof((boost::move_detail::declval(). - BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))> - struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) - { - boost_intrusive_has_member_function_callable_with::yes_type dummy; - BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); - }; - - //For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not - //SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0. - template - struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) - { - boost_intrusive_has_member_function_callable_with::no_type dummy; - BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); - }; - - #endif //#ifdef BOOST_NO_CXX11_DECLTYPE - - template - struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) - - { - #ifndef BOOST_NO_CXX11_DECLTYPE - template().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()) > - static boost_intrusive_has_member_function_callable_with::yes_type Test(Fun*); - #else - template - static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) - Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)*); - #endif - - template - static boost_intrusive_has_member_function_callable_with::no_type Test(...); - - static const bool value = sizeof(Test< Fun >(0)) - == sizeof(boost_intrusive_has_member_function_callable_with::yes_type); - }; - - template - struct BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME ) - : Fun - { - BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )(); - using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME; - - boost_intrusive_has_member_function_callable_with::private_type - BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME - ( DontCares...) const; - }; - - template - struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl) - - { - template - struct make_dontcare - { - typedef boost_intrusive_has_member_function_callable_with::dont_care type; - }; - - typedef BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME ) - ::type...> FunWrap; - - static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) == - sizeof(boost_intrusive_has_member_function_callable_with::is_private_type - ( (::boost::move_detail::declval< FunWrap >(). - BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME - ( ::boost::move_detail::declval()... ), 0) ) - ) - ); - }; - - template - struct BOOST_PP_CAT( has_member_function_callable_with_ - , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) - : public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_ - , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) - < Fun - , BOOST_PP_CAT( has_member_function_named_ - , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )::value - , Args... > - {}; - #endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END diff --git a/include/boost/intrusive/detail/memory_util.hpp b/include/boost/intrusive/detail/memory_util.hpp index e644ebc..e425c3b 100644 --- a/include/boost/intrusive/detail/memory_util.hpp +++ b/include/boost/intrusive/detail/memory_util.hpp @@ -118,25 +118,25 @@ struct LowPriorityConversion #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME pointer_to #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, )) +#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) #include BOOST_PP_ITERATE() #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME static_cast_from #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, )) +#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) #include BOOST_PP_ITERATE() #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME const_cast_from #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, )) +#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) #include BOOST_PP_ITERATE() #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME dynamic_cast_from #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, )) +#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) #include BOOST_PP_ITERATE() namespace boost { diff --git a/test/common_functors.hpp b/test/common_functors.hpp index 03fbc65..a6af9fb 100644 --- a/test/common_functors.hpp +++ b/test/common_functors.hpp @@ -15,6 +15,7 @@ #include #include +#include namespace boost { namespace intrusive { @@ -28,7 +29,7 @@ class delete_disposer void operator()(Pointer p) { typedef typename std::iterator_traits::value_type value_type; - BOOST_INTRUSIVE_INVARIANT_ASSERT(( detail::is_same::value )); + BOOST_STATIC_ASSERT(( detail::is_same::value )); delete boost::intrusive::detail::to_raw_pointer(p); } }; diff --git a/test/has_member_function_callable_with.cpp b/test/has_member_function_callable_with.cpp index 0036c3f..7839bf9 100644 --- a/test/has_member_function_callable_with.cpp +++ b/test/has_member_function_callable_with.cpp @@ -147,7 +147,7 @@ class has_member_function_named_func { template - static decltype(boost::move_detail::declval().func(), has_member_function_callable_with::yes_type()) Test(Fun* f); + static decltype(boost::move_detail::declval().func(), has_member_function_callable_with::yes_type()) Test(U* f); template static has_member_function_callable_with::no_type Test(...); @@ -307,7 +307,7 @@ class has_member_function_named_func { #ifndef BOOST_NO_CXX11_DECLTYPE - template().func()) > + template().func()) > static boost_intrusive_has_member_function_callable_with::yes_type Test(U*); #else template From edec698381f0ce7646b0a23154913fc830509cce Mon Sep 17 00:00:00 2001 From: Beman Date: Sun, 1 Dec 2013 17:18:08 -0500 Subject: [PATCH 06/18] End-of-line normalization. Most normalization was taken care of by .gitattributes, but a few files originally committed to svn with incorrect eol tags need explicit normalization. See .gitattributes man page and extensive list discussion. --- proj/vc7ide/avl_multiset/avl_multiset.vcproj | 256 +++++++++--------- proj/vc7ide/avl_set/avl_set.vcproj | 254 ++++++++--------- proj/vc7ide/sg_multiset/sg_multiset.vcproj | 256 +++++++++--------- proj/vc7ide/sg_set/sg_set.vcproj | 254 ++++++++--------- .../splay_multiset/splay_multiset.vcproj | 256 +++++++++--------- proj/vc7ide/splay_set/splay_set.vcproj | 254 ++++++++--------- 6 files changed, 765 insertions(+), 765 deletions(-) diff --git a/proj/vc7ide/avl_multiset/avl_multiset.vcproj b/proj/vc7ide/avl_multiset/avl_multiset.vcproj index 2a80b81..7199741 100644 --- a/proj/vc7ide/avl_multiset/avl_multiset.vcproj +++ b/proj/vc7ide/avl_multiset/avl_multiset.vcproj @@ -1,128 +1,128 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/avl_set/avl_set.vcproj b/proj/vc7ide/avl_set/avl_set.vcproj index 9ecd59d..afcca06 100644 --- a/proj/vc7ide/avl_set/avl_set.vcproj +++ b/proj/vc7ide/avl_set/avl_set.vcproj @@ -1,127 +1,127 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/sg_multiset/sg_multiset.vcproj b/proj/vc7ide/sg_multiset/sg_multiset.vcproj index b14f697..d954cdb 100644 --- a/proj/vc7ide/sg_multiset/sg_multiset.vcproj +++ b/proj/vc7ide/sg_multiset/sg_multiset.vcproj @@ -1,128 +1,128 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/sg_set/sg_set.vcproj b/proj/vc7ide/sg_set/sg_set.vcproj index 7910d1b..a339dcb 100644 --- a/proj/vc7ide/sg_set/sg_set.vcproj +++ b/proj/vc7ide/sg_set/sg_set.vcproj @@ -1,127 +1,127 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/splay_multiset/splay_multiset.vcproj b/proj/vc7ide/splay_multiset/splay_multiset.vcproj index 3bbce26..869b642 100644 --- a/proj/vc7ide/splay_multiset/splay_multiset.vcproj +++ b/proj/vc7ide/splay_multiset/splay_multiset.vcproj @@ -1,128 +1,128 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/splay_set/splay_set.vcproj b/proj/vc7ide/splay_set/splay_set.vcproj index 2bccaa2..1f2336a 100644 --- a/proj/vc7ide/splay_set/splay_set.vcproj +++ b/proj/vc7ide/splay_set/splay_set.vcproj @@ -1,127 +1,127 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ea126390a7938bb01e924f7e390cd78f385b3118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 23 Dec 2013 10:15:53 +0100 Subject: [PATCH 07/18] Changes for 1.56 made during Git transition: * Improved Doxygen generated reference and updated and fixed forward-declaration header. * Source breaking: Removed previously deprecated `xxx_dont_splay` functions from splay containers and removed `splay_set_base_hook` and `splay_set_member_hook`from splay containers. --- doc/Jamfile.v2 | 6 +- doc/intrusive.qbk | 8 +- example/doc_splay_set.cpp | 17 +- include/boost/intrusive/avltree.hpp | 2 +- .../boost/intrusive/avltree_algorithms.hpp | 2 +- include/boost/intrusive/bstree.hpp | 3 +- include/boost/intrusive/bstree_algorithms.hpp | 2 +- .../intrusive/derivation_value_traits.hpp | 12 +- .../boost/intrusive/detail/generic_hook.hpp | 6 +- include/boost/intrusive/hashtable.hpp | 2 +- include/boost/intrusive/intrusive_fwd.hpp | 287 +++++++++++++----- include/boost/intrusive/list.hpp | 2 +- .../boost/intrusive/member_value_traits.hpp | 11 +- .../boost/intrusive/parent_from_member.hpp | 2 + include/boost/intrusive/pointer_plus_bits.hpp | 4 + include/boost/intrusive/pointer_traits.hpp | 1 + include/boost/intrusive/rbtree.hpp | 2 +- include/boost/intrusive/rbtree_algorithms.hpp | 2 +- include/boost/intrusive/set.hpp | 1 + include/boost/intrusive/set_hook.hpp | 1 + include/boost/intrusive/sgtree.hpp | 2 +- include/boost/intrusive/sgtree_algorithms.hpp | 2 +- include/boost/intrusive/slist.hpp | 2 +- include/boost/intrusive/splay_set_hook.hpp | 286 ----------------- include/boost/intrusive/splaytree.hpp | 3 +- .../boost/intrusive/splaytree_algorithms.hpp | 2 +- include/boost/intrusive/treap.hpp | 2 +- include/boost/intrusive/treap_algorithms.hpp | 2 +- .../boost/intrusive/trivial_value_traits.hpp | 11 +- test/make_functions_test.cpp | 12 - test/splay_multiset_test.cpp | 12 +- test/splay_set_test.cpp | 12 +- 32 files changed, 294 insertions(+), 427 deletions(-) delete mode 100644 include/boost/intrusive/splay_set_hook.hpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 36fb46c..d64860b 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -33,10 +33,12 @@ doxygen autodoc \"BOOST_RV_REF_END=&&\" \\ \"list_impl=list\" \\ \"slist_impl=slist\" \\ + \"bstree_impl=bstree\" \\ + \"bs_set_impl=bs_set\" \\ + \"bs_multiset_impl=bs_multiset\" \\ + \"rbtree_impl=rbtree\" \\ \"set_impl=set\" \\ \"multiset_impl=multiset\" \\ - \"bstree_impl=bstree\" \\ - \"rbtree_impl=rbtree\" \\ \"unordered_set_impl=unordered_set\" \\ \"unordered_multiset_impl=unordered_multiset\" \\ \"hashtable_impl=hashtable\" \\ diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index fdcbaf7..cec53de 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3886,6 +3886,11 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes_boost_1_56_00 Boost 1.56 Release] +* Improved Doxygen generated reference and updated and fixed forward-declaration header. + +* [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers and + removed `splay_set_base_hook` and `splay_set_member_hook`from splay containers. + * Fixed bugs: * [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]]. @@ -3894,7 +3899,8 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes_boost_1_55_00 Boost 1.55 Release] * [*Source breaking]: Deprecated `xxx_dont_splay` functions from splay containers. - Deprecated `splay_set_hook` from splay containers, use `bs_set_hook` instead. + Deprecated `splay_set_base_hook` and `splay_set_member_hook`from splay containers, use + `bs_set_base_hook` or `bs_set_member_hook` instead. Both will be removed in Boost 1.56. * [*ABI breaking]: Hash containers' end iterator was implemented pointing to one-past the end of the bucket array diff --git a/example/doc_splay_set.cpp b/example/doc_splay_set.cpp index 45deceb..6c333b7 100644 --- a/example/doc_splay_set.cpp +++ b/example/doc_splay_set.cpp @@ -11,7 +11,6 @@ ///////////////////////////////////////////////////////////////////////////// //[doc_splay_set_code #include -#include #include #include @@ -20,14 +19,13 @@ using namespace boost::intrusive; class mytag; class MyClass - : public splay_set_base_hook<> //This is an splay tree base hook - , public bs_set_base_hook< tag > //This is a binary search tree base hook + : public bs_set_base_hook<> { int int_; public: //This is a member hook - splay_set_member_hook<> member_hook_; + bs_set_member_hook<> member_hook_; MyClass(int i) : int_(i) @@ -43,11 +41,8 @@ class MyClass //Define a set using the base hook that will store values in reverse order typedef splay_set< MyClass, compare > > BaseSplaySet; -//Define a set using the binary search tree hook -typedef splay_set< MyClass, base_hook > > > BaseBsSplaySet; - //Define an multiset using the member hook -typedef member_hook, &MyClass::member_hook_> MemberOption; +typedef member_hook, &MyClass::member_hook_> MemberOption; typedef splay_multiset< MyClass, MemberOption> MemberSplayMultiset; int main() @@ -59,21 +54,18 @@ int main() for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); BaseSplaySet baseset; - BaseBsSplaySet bsbaseset; MemberSplayMultiset membermultiset; //Insert values in the container for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ baseset.insert(*it); - bsbaseset.insert(*it); membermultiset.insert(*it); } //Now test sets { BaseSplaySet::reverse_iterator rbit(baseset.rbegin()); - BaseBsSplaySet::iterator bsit(bsbaseset.begin()); MemberSplayMultiset::iterator mit(membermultiset.begin()); VectIt it(values.begin()), itend(values.end()); @@ -83,8 +75,7 @@ int main() } //Test the objects inserted in member and binary search hook sets - for(it = values.begin(); it != itend; ++it, ++bsit, ++mit){ - if(&*bsit != &*it) return 1; + for(it = values.begin(); it != itend; ++it, ++mit){ if(&*mit != &*it) return 1; } } diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index f0cb9fe..225efcc 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_AVLTREE_HPP #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include -#include #include #include #include diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 1dc2acf..526649a 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -15,9 +15,9 @@ #define BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP #include +#include #include -#include #include #include diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index 32554fb..144415d 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_BSTREE_HPP #include +#include #include #include #include @@ -22,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index 6297329..9ae1d32 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -14,8 +14,8 @@ #define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP #include -#include #include +#include #include #include #include diff --git a/include/boost/intrusive/derivation_value_traits.hpp b/include/boost/intrusive/derivation_value_traits.hpp index 0b3c936..5581ab6 100644 --- a/include/boost/intrusive/derivation_value_traits.hpp +++ b/include/boost/intrusive/derivation_value_traits.hpp @@ -13,6 +13,9 @@ #ifndef BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP #define BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP +#include +#include + #include #include #include @@ -24,7 +27,12 @@ namespace intrusive { //!This value traits template is used to create value traits //!from user defined node traits where value_traits::value_type will //!derive from node_traits::node -template + +template struct derivation_value_traits { public: @@ -67,4 +75,6 @@ struct derivation_value_traits } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP diff --git a/include/boost/intrusive/detail/generic_hook.hpp b/include/boost/intrusive/detail/generic_hook.hpp index 8848aff..835a8c7 100644 --- a/include/boost/intrusive/detail/generic_hook.hpp +++ b/include/boost/intrusive/detail/generic_hook.hpp @@ -33,9 +33,9 @@ enum base_hook_type , SlistBaseHookId , RbTreeBaseHookId , HashBaseHookId -, SplayTreeBaseHookId , AvlTreeBaseHookId , BsTreeBaseHookId +, TreapTreeBaseHookId , AnyBaseHookId }; @@ -59,10 +59,6 @@ template struct hook_tags_definer { typedef HookTags default_hashtable_hook; }; -template -struct hook_tags_definer -{ typedef HookTags default_splaytree_hook; }; - template struct hook_tags_definer { typedef HookTags default_avltree_hook; }; diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index fa43bfe..f4bfb85 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_HASHTABLE_HPP #include +#include //std C++ #include //std::equal_to #include //std::pair @@ -24,7 +25,6 @@ #include #include //General intrusive utilities -#include #include #include #include diff --git a/include/boost/intrusive/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp index 0e5e21c..5beeffd 100644 --- a/include/boost/intrusive/intrusive_fwd.hpp +++ b/include/boost/intrusive/intrusive_fwd.hpp @@ -13,12 +13,47 @@ #ifndef BOOST_INTRUSIVE_FWD_HPP #define BOOST_INTRUSIVE_FWD_HPP +//! \file +//! This header file forward declares most Intrusive classes. +//! +//! It forward declares the following containers and hooks: +//! - boost::intrusive::slist / boost::intrusive::slist_base_hook / boost::intrusive::slist_member_hook +//! - boost::intrusive::list / boost::intrusive::list_base_hook / boost::intrusive::list_member_hook +//! - boost::intrusive::bstree / boost::intrusive::bs_set / boost::intrusive::bs_multiset / +//! boost::intrusive::bs_set_base_hook / boost::intrusive::bs_set_member_hook +//! - boost::intrusive::rbtree / boost::intrusive::set / boost::intrusive::multiset / +//! boost::intrusive::set_base_hook / boost::intrusive::set_member_hook +//! - boost::intrusive::avltree / boost::intrusive::avl_set / boost::intrusive::avl_multiset / +//! boost::intrusive::avl_set_base_hook / boost::intrusive::avl_set_member_hook +//! - boost::intrusive::splaytree / boost::intrusive::splay_set / boost::intrusive::splay_multiset +//! - boost::intrusive::sgtree / boost::intrusive::sg_set / boost::intrusive::sg_multiset +//! - boost::intrusive::treap / boost::intrusive::treap_set / boost::intrusive::treap_multiset +//! - boost::intrusive::hashtable / boost::intrusive::unordered_set / boost::intrusive::unordered_multiset / +//! boost::intrusive::unordered_set_base_hook / boost::intrusive::unordered_set_member_hook / +//! - boost::intrusive::any_base_hook / boost::intrusive::any_member_hook +//! +//! It forward declares the following container or hook options: +//! - boost::intrusive::constant_time_size / boost::intrusive::size_type / boost::intrusive::compare / boost::intrusive::equal +//! - boost::intrusive::floating_point / boost::intrusive::priority / boost::intrusive::hash +//! - boost::intrusive::value_traits / boost::intrusive::member_hook / boost::intrusive::function_hook / boost::intrusive::base_hook +//! - boost::intrusive::void_pointer / boost::intrusive::tag / boost::intrusive::link_mode +//! - boost::intrusive::optimize_size / boost::intrusive::linear / boost::intrusive::cache_last +//! - boost::intrusive::bucket_traits / boost::intrusive::store_hash / boost::intrusive::optimize_multikey +//! - boost::intrusive::power_2_buckets / boost::intrusive::cache_begin / boost::intrusive::compare_hash / boost::intrusive::incremental +//! +//! It forward declares the following value traits utilities: +//! - boost::intrusive::value_traits / boost::intrusive::derivation_value_traits / +//! boost::intrusive::trivial_value_traits +//! +//! Finally it forward declares the following general purpose utilities: +//! - boost::intrusive::pointer_plus_bits / boost::intrusive::priority_compare. + +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + #include #include #include -/// @cond - namespace boost { namespace intrusive { @@ -33,15 +68,33 @@ class circular_list_algorithms; template class circular_slist_algorithms; +template +class linear_slist_algorithms; + +template +class bstree_algorithms; + template class rbtree_algorithms; +template +class avltree_algorithms; + +template +class sgtree_algorithms; + +template +class splaytree_algorithms; + +template +class treap_algorithms; + //////////////////////////// // Containers //////////////////////////// //slist -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -55,7 +108,7 @@ template #endif class slist; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -66,7 +119,7 @@ template #endif class slist_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -78,7 +131,7 @@ template class slist_member_hook; //list -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -90,7 +143,7 @@ template #endif class list; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -101,7 +154,7 @@ template #endif class list_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -112,19 +165,8 @@ template #endif class list_member_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template - < class O1 = void - , class O2 = void - , class O3 = void - > -#else -template -#endif -class list_hook; - //rbtree/set/multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -137,7 +179,7 @@ template #endif class rbtree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -150,7 +192,7 @@ template #endif class set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -163,7 +205,7 @@ template #endif class multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -175,7 +217,7 @@ template #endif class set_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -188,7 +230,7 @@ template class set_member_hook; //splaytree/splay_set/splay_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -201,7 +243,7 @@ template #endif class splaytree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -214,7 +256,7 @@ template #endif class splay_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -227,30 +269,8 @@ template #endif class splay_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template - < class O1 = void - , class O2 = void - , class O3 = void - > -#else -template -#endif -class splay_set_base_hook; - -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template - < class O1 = void - , class O2 = void - , class O3 = void - > -#else -template -#endif -class splay_set_member_hook; - //avltree/avl_set/avl_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -263,7 +283,7 @@ template #endif class avltree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -276,7 +296,7 @@ template #endif class avl_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -289,7 +309,7 @@ template #endif class avl_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -301,7 +321,7 @@ template #endif class avl_set_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -315,7 +335,7 @@ class avl_set_member_hook; //treap/treap_set/treap_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -328,7 +348,7 @@ template #endif class treap; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -341,7 +361,7 @@ template #endif class treap_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -354,12 +374,8 @@ template #endif class treap_multiset; -//Default priority comparison functor -template -struct priority_compare; - //sgtree/sg_set/sg_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -372,7 +388,7 @@ template #endif class sgtree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -385,7 +401,7 @@ template #endif class sg_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -398,7 +414,7 @@ template #endif class sg_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -411,7 +427,7 @@ template #endif class bstree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -424,7 +440,7 @@ template #endif class bs_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -437,7 +453,7 @@ template #endif class bs_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -448,7 +464,7 @@ template #endif class bs_set_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -461,7 +477,7 @@ class bs_set_member_hook; //hashtable/unordered_set/unordered_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -480,7 +496,7 @@ template #endif class hashtable; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -499,7 +515,7 @@ template #endif class unordered_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -518,7 +534,7 @@ template #endif class unordered_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -530,7 +546,7 @@ template #endif class unordered_set_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -542,7 +558,7 @@ template #endif class unordered_set_member_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -553,7 +569,7 @@ template #endif class any_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -564,9 +580,126 @@ template #endif class any_member_hook; +//Options + +template +struct constant_time_size; + +template +struct size_type; + +template +struct compare; + +template +struct floating_point; + +template +struct equal; + +template +struct priority; + +template +struct hash; + +template struct value_traits; + +template< typename Parent + , typename MemberHook + , MemberHook Parent::* PtrToMember> +struct member_hook; + +template +struct function_hook; + +template +struct base_hook; + +template +struct void_pointer; + +template +struct tag; + +template +struct link_mode; + +template struct +optimize_size; + +template +struct linear; + +template +struct cache_last; + +template +struct bucket_traits; + +template +struct store_hash; + +template +struct optimize_multikey; + +template +struct power_2_buckets; + +template +struct cache_begin; + +template +struct compare_hash; + +template +struct incremental; + +//Value traits + +template +struct value_traits; + +template< typename Parent + , typename MemberHook + , MemberHook Parent::* PtrToMember> +struct member_hook; + +template< typename Functor> +struct function_hook; + +template +struct base_hook; + +template +struct derivation_value_traits; + +template +struct trivial_value_traits; + +//Additional utilities + +template +struct max_pointer_plus_bits; + +template +struct max_pointer_plus_bits; + +template +struct pointer_plus_bits; + +template +struct pointer_plus_bits; + +template +struct pointer_traits; + +template +struct pointer_traits; + } //namespace intrusive { } //namespace boost { -/// @endcond +#endif //#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) #endif //#ifndef BOOST_INTRUSIVE_FWD_HPP diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index 01eae13..fa0a1e8 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -15,8 +15,8 @@ #define BOOST_INTRUSIVE_LIST_HPP #include -#include #include +#include #include #include #include diff --git a/include/boost/intrusive/member_value_traits.hpp b/include/boost/intrusive/member_value_traits.hpp index ce35fdc..bd5f1fb 100644 --- a/include/boost/intrusive/member_value_traits.hpp +++ b/include/boost/intrusive/member_value_traits.hpp @@ -13,6 +13,9 @@ #ifndef BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP #define BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP +#include +#include + #include #include #include @@ -26,7 +29,11 @@ namespace intrusive { //!store a node_traits::node template< class T, class NodeTraits , typename NodeTraits::node T::* PtrToMember - , link_mode_type LinkMode = safe_link> + , link_mode_type LinkMode + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + = safe_link + #endif +> struct member_value_traits { public: @@ -67,4 +74,6 @@ struct member_value_traits } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP diff --git a/include/boost/intrusive/parent_from_member.hpp b/include/boost/intrusive/parent_from_member.hpp index e06f156..0f3eb5c 100644 --- a/include/boost/intrusive/parent_from_member.hpp +++ b/include/boost/intrusive/parent_from_member.hpp @@ -13,6 +13,8 @@ #define BOOST_INTRUSIVE_GET_PARENT_FROM_MEMBER_HPP #include +#include + #include namespace boost { diff --git a/include/boost/intrusive/pointer_plus_bits.hpp b/include/boost/intrusive/pointer_plus_bits.hpp index 7b0a793..3893d66 100644 --- a/include/boost/intrusive/pointer_plus_bits.hpp +++ b/include/boost/intrusive/pointer_plus_bits.hpp @@ -13,6 +13,8 @@ #ifndef BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP #define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP +#include +#include #include //ls_zeros #include //BOOST_INTRUSIVE_INVARIANT_ASSERT @@ -83,4 +85,6 @@ struct pointer_plus_bits } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP diff --git a/include/boost/intrusive/pointer_traits.hpp b/include/boost/intrusive/pointer_traits.hpp index beebe6b..660420d 100644 --- a/include/boost/intrusive/pointer_traits.hpp +++ b/include/boost/intrusive/pointer_traits.hpp @@ -22,6 +22,7 @@ #endif #include +#include #include #include #include diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 8acfe45..326b13f 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -13,13 +13,13 @@ #define BOOST_INTRUSIVE_RBTREE_HPP #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 38a5cdc..529ef90 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -49,9 +49,9 @@ #define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP #include +#include #include -#include #include #include diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index c8c197c..208360d 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -15,6 +15,7 @@ #include #include + #include #include #include diff --git a/include/boost/intrusive/set_hook.hpp b/include/boost/intrusive/set_hook.hpp index 38da7bc..ee35279 100644 --- a/include/boost/intrusive/set_hook.hpp +++ b/include/boost/intrusive/set_hook.hpp @@ -16,6 +16,7 @@ #include #include + #include #include #include diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 0be42dc..5b42185 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -19,6 +19,7 @@ #define BOOST_INTRUSIVE_SGTREE_HPP #include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index 2dd129c..65a76b1 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -18,9 +18,9 @@ #define BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP #include +#include #include -#include #include #include #include diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index c471826..e1f6688 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -15,9 +15,9 @@ #define BOOST_INTRUSIVE_SLIST_HPP #include +#include #include #include -#include #include #include #include diff --git a/include/boost/intrusive/splay_set_hook.hpp b/include/boost/intrusive/splay_set_hook.hpp deleted file mode 100644 index c78b4a3..0000000 --- a/include/boost/intrusive/splay_set_hook.hpp +++ /dev/null @@ -1,286 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2013 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/intrusive for documentation. -// -///////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP -#define BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP - -#include -#include - -namespace boost { -namespace intrusive { - -//! Helper metafunction to define a \c splay_set_base_hook that yields to the same -//! type when the same options (either explicitly or implicitly) are used. -//! WARNING: Deprecated class, use `make_bs_set_base_hook` instead. -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_splay_set_base_hook -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - #if defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - : public make_bs_set_base_hook - #else - : public make_bs_set_base_hook - #endif -#endif -{ - /// @cond - typedef typename make_bs_set_base_hook - < - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3 - #else - Options... - #endif - >::type implementation_defined; - /// @endcond - typedef implementation_defined type; -}; - -//! Derive a class from splay_set_base_hook in order to store objects in -//! in a splay_set/splay_multiset. splay_set_base_hook holds the data necessary to maintain -//! the splay_set/splay_multiset and provides an appropriate value_traits class for splay_set/splay_multiset. -//! -//! The hook admits the following options: \c tag<>, \c void_pointer<>, -//! \c link_mode<> and \c optimize_size<>. -//! -//! \c tag<> defines a tag to identify the node. -//! The same tag value can be used in different classes, but if a class is -//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its -//! unique tag. -//! -//! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. -//! -//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, -//! \c auto_unlink or \c safe_link). -//! -//! WARNING: Deprecated class, use `bs_set_base_hook` instead. -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -class splay_set_base_hook - : public make_splay_set_base_hook< - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3 - #else - Options... - #endif - >::type -{ - #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - public: - //! Effects: If link_mode is \c auto_unlink or \c safe_link - //! initializes the node to an unlinked state. - //! - //! Throws: Nothing. - splay_set_base_hook(); - - //! Effects: If link_mode is \c auto_unlink or \c safe_link - //! initializes the node to an unlinked state. The argument is ignored. - //! - //! Throws: Nothing. - //! - //! Rationale: 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. - splay_set_base_hook(const splay_set_base_hook& ); - - //! Effects: Empty function. The argument is ignored. - //! - //! Throws: Nothing. - //! - //! Rationale: 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. - splay_set_base_hook& operator=(const splay_set_base_hook& ); - - //! Effects: 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 set an assertion is raised. If link_mode is - //! \c auto_unlink and \c is_linked() is true, the node is unlinked. - //! - //! Throws: Nothing. - ~splay_set_base_hook(); - - //! Effects: Swapping two nodes swaps the position of the elements - //! related to those nodes in one or two containers. That is, if the node - //! this is part of the element e1, the node x is part of the element e2 - //! and both elements are included in the containers s1 and s2, then after - //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 - //! at the position of e1. If one element is not in a container, then - //! after the swap-operation the other element is not in a container. - //! Iterators to e1 and e2 related to those nodes are invalidated. - //! - //! Complexity: Constant - //! - //! Throws: Nothing. - void swap_nodes(splay_set_base_hook &other); - - //! Precondition: link_mode must be \c safe_link or \c auto_unlink. - //! - //! Returns: true, if the node belongs to a container, false - //! otherwise. This function can be used to test whether \c set::iterator_to - //! will return a valid iterator. - //! - //! Complexity: Constant - bool is_linked() const; - - //! Effects: Removes the node if it's inserted in a container. - //! This function is only allowed if link_mode is \c auto_unlink. - //! - //! Throws: Nothing. - void unlink(); - #endif -}; - -//! Helper metafunction to define a \c splay_set_member_hook that yields to the same -//! type when the same options (either explicitly or implicitly) are used. -//! -//! WARNING: Deprecated class, use `make_bs_set_member_hook` instead. -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_splay_set_member_hook -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - #if defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - : public make_bs_set_member_hook - #else - : public make_bs_set_member_hook - #endif -#endif -{ - /// @cond - typedef typename make_bs_set_member_hook - < - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3 - #else - Options... - #endif - >::type implementation_defined; - /// @endcond - typedef implementation_defined type; -}; - -//! Put a public data member splay_set_member_hook in order to store objects of this -//! class in a splay_set/splay_multiset. splay_set_member_hook holds the data -//! necessary for maintaining the splay_set/splay_multiset and provides an appropriate -//! value_traits class for splay_set/splay_multiset. -//! -//! The hook admits the following options: \c void_pointer<>, -//! \c link_mode<> and \c optimize_size<>. -//! -//! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. -//! -//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, -//! \c auto_unlink or \c safe_link). -//! -//! WARNING: Deprecated class, use `bs_set_member_hook` instead. -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -class splay_set_member_hook - : public make_splay_set_member_hook< - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3 - #else - Options... - #endif - >::type -{ - #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - public: - //! Effects: If link_mode is \c auto_unlink or \c safe_link - //! initializes the node to an unlinked state. - //! - //! Throws: Nothing. - splay_set_member_hook(); - - //! Effects: If link_mode is \c auto_unlink or \c safe_link - //! initializes the node to an unlinked state. The argument is ignored. - //! - //! Throws: Nothing. - //! - //! Rationale: 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. - splay_set_member_hook(const splay_set_member_hook& ); - - //! Effects: Empty function. The argument is ignored. - //! - //! Throws: Nothing. - //! - //! Rationale: 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. - splay_set_member_hook& operator=(const splay_set_member_hook& ); - - //! Effects: 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 set an assertion is raised. If link_mode is - //! \c auto_unlink and \c is_linked() is true, the node is unlinked. - //! - //! Throws: Nothing. - ~splay_set_member_hook(); - - //! Effects: Swapping two nodes swaps the position of the elements - //! related to those nodes in one or two containers. That is, if the node - //! this is part of the element e1, the node x is part of the element e2 - //! and both elements are included in the containers s1 and s2, then after - //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 - //! at the position of e1. If one element is not in a container, then - //! after the swap-operation the other element is not in a container. - //! Iterators to e1 and e2 related to those nodes are invalidated. - //! - //! Complexity: Constant - //! - //! Throws: Nothing. - void swap_nodes(splay_set_member_hook &other); - - //! Precondition: link_mode must be \c safe_link or \c auto_unlink. - //! - //! Returns: true, if the node belongs to a container, false - //! otherwise. This function can be used to test whether \c set::iterator_to - //! will return a valid iterator. - //! - //! Complexity: Constant - bool is_linked() const; - - //! Effects: Removes the node if it's inserted in a container. - //! This function is only allowed if link_mode is \c auto_unlink. - //! - //! Throws: Nothing. - void unlink(); - #endif -}; - -} //namespace intrusive -} //namespace boost - -#include - -#endif //BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index f02de06..b0e4469 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_SPLAYTREE_HPP #include +#include #include #include #include @@ -20,8 +21,6 @@ #include #include -#include -#include #include #include #include diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index d9ce54c..5d580a6 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -31,8 +31,8 @@ #define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP #include -#include #include +#include #include #include #include diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index 38b02d5..eb0e501 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_TREAP_HPP #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include -#include #include #include #include diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index 1bdd3b3..6a61b7e 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -14,9 +14,9 @@ #define BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP #include +#include #include -#include #include #include diff --git a/include/boost/intrusive/trivial_value_traits.hpp b/include/boost/intrusive/trivial_value_traits.hpp index 0ea306d..2505e08 100644 --- a/include/boost/intrusive/trivial_value_traits.hpp +++ b/include/boost/intrusive/trivial_value_traits.hpp @@ -13,6 +13,9 @@ #ifndef BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP #define BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP +#include +#include + #include #include @@ -22,7 +25,11 @@ namespace intrusive { //!This value traits template is used to create value traits //!from user defined node traits where value_traits::value_type and //!node_traits::node should be equal -template +template struct trivial_value_traits { typedef NodeTraits node_traits; @@ -43,4 +50,6 @@ struct trivial_value_traits } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP diff --git a/test/make_functions_test.cpp b/test/make_functions_test.cpp index 89de0e9..dcb8bc4 100644 --- a/test/make_functions_test.cpp +++ b/test/make_functions_test.cpp @@ -183,12 +183,6 @@ int main() return 1; } - if(detail::is_same, link_mode >::type - ,make_splay_set_base_hook<>::type - >::value == false){ - return 1; - } - //Check defined types and implicitly defined types are unequal if(detail::is_same, link_mode >::type ,make_list_base_hook<>::type @@ -220,12 +214,6 @@ int main() return 1; } - if(detail::is_same, link_mode >::type - ,make_splay_set_base_hook<>::type - >::value == true){ - return 1; - } - if(detail::is_same, link_mode >::type ,make_bs_set_base_hook<>::type >::value == true){ diff --git a/test/splay_multiset_test.cpp b/test/splay_multiset_test.cpp index bf8cb8e..7a21f07 100644 --- a/test/splay_multiset_test.cpp +++ b/test/splay_multiset_test.cpp @@ -77,15 +77,15 @@ struct my_tag; template struct hooks { - typedef splay_set_base_hook > base_hook_type; - typedef splay_set_base_hook + typedef bs_set_base_hook > base_hook_type; + typedef bs_set_base_hook < link_mode , void_pointer - , tag > auto_base_hook_type; - typedef splay_set_member_hook > member_hook_type; - typedef splay_set_member_hook + , tag > auto_base_hook_type; + typedef bs_set_member_hook > member_hook_type; + typedef bs_set_member_hook < link_mode - , void_pointer > auto_member_hook_type; + , void_pointer > auto_member_hook_type; }; template< class ValueType diff --git a/test/splay_set_test.cpp b/test/splay_set_test.cpp index a22accd..8e62f2c 100644 --- a/test/splay_set_test.cpp +++ b/test/splay_set_test.cpp @@ -74,15 +74,15 @@ struct my_tag; template struct hooks { - typedef splay_set_base_hook > base_hook_type; - typedef splay_set_base_hook + typedef bs_set_base_hook > base_hook_type; + typedef bs_set_base_hook < link_mode , void_pointer - , tag > auto_base_hook_type; - typedef splay_set_member_hook > member_hook_type; - typedef splay_set_member_hook + , tag > auto_base_hook_type; + typedef bs_set_member_hook > member_hook_type; + typedef bs_set_member_hook < link_mode - , void_pointer > auto_member_hook_type; + , void_pointer > auto_member_hook_type; }; template< class ValueType From abb8a78a75f02ca54ea3703c9726f4f38a3e6850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 24 Dec 2013 17:10:24 +0100 Subject: [PATCH 08/18] Fixes #9520 --- doc/intrusive.qbk | 4 ++-- include/boost/intrusive/any_hook.hpp | 4 ++-- include/boost/intrusive/avl_set_hook.hpp | 4 ++-- include/boost/intrusive/bs_set_hook.hpp | 4 ++-- include/boost/intrusive/list.hpp | 6 +++--- include/boost/intrusive/list_hook.hpp | 4 ++-- include/boost/intrusive/set_hook.hpp | 4 ++-- include/boost/intrusive/slist_hook.hpp | 4 ++-- include/boost/intrusive/unordered_set_hook.hpp | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index cec53de..90684a7 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -875,7 +875,7 @@ the section [link intrusive.usage How to use Boost.Intrusive]: last element of the singly linked list. This allows `O(1)` swap, `splice_after(iterator, slist &)` and makes the list offer new functions like `push_back(reference)` and `back()`. Logically, the size an empty list is - increased in `sizeof(void_pointer)` and the the cached last node pointer must + increased in `sizeof(void_pointer)` and the cached last node pointer must be updated in every operation, and that might incur in a slight performance impact. `auto_unlink` hooks are not usable if `linear` and/or `cache_last` options are @@ -3582,7 +3582,7 @@ and also derives from `test_class`. `func_ptr_adaptor` is just a functor adaptor to convert function objects taking `test_list` objects to function objects taking pointers to them. -You can find the full test code code in the +You can find the full test code in the [@../../libs/intrusive/perf/perf_list.cpp perf_list.cpp] source file. [section:performance_results_push_back Back insertion and destruction] diff --git a/include/boost/intrusive/any_hook.hpp b/include/boost/intrusive/any_hook.hpp index 03c299f..b53df9f 100644 --- a/include/boost/intrusive/any_hook.hpp +++ b/include/boost/intrusive/any_hook.hpp @@ -75,7 +75,7 @@ struct make_any_base_hook //! \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. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -175,7 +175,7 @@ struct make_any_member_hook //! \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. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else diff --git a/include/boost/intrusive/avl_set_hook.hpp b/include/boost/intrusive/avl_set_hook.hpp index cd0478d..7cb3e3d 100644 --- a/include/boost/intrusive/avl_set_hook.hpp +++ b/include/boost/intrusive/avl_set_hook.hpp @@ -74,7 +74,7 @@ struct make_avl_set_base_hook //! unique tag. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). @@ -200,7 +200,7 @@ struct make_avl_set_member_hook //! \c link_mode<> and \c optimize_size<>. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). diff --git a/include/boost/intrusive/bs_set_hook.hpp b/include/boost/intrusive/bs_set_hook.hpp index 1f16971..2ac050e 100644 --- a/include/boost/intrusive/bs_set_hook.hpp +++ b/include/boost/intrusive/bs_set_hook.hpp @@ -73,7 +73,7 @@ struct make_bs_set_base_hook //! unique tag. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). @@ -196,7 +196,7 @@ struct make_bs_set_member_hook //! The hook admits the following options: \c void_pointer<>, \c link_mode<>. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index fa0a1e8..ce2cda5 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -887,7 +887,7 @@ class list_impl //! new_ele must point to an element contained in list x. //! //! Effects: Transfers the value pointed by new_ele, from list x to this list, - //! before the the element pointed by p. No destructors or copy constructors are called. + //! before the element pointed by p. No destructors or copy constructors are called. //! If p == new_ele or p == ++new_ele, this function is a null operation. //! //! Throws: Nothing. @@ -907,7 +907,7 @@ class list_impl //! f and e must point to elements contained in list x. //! //! Effects: Transfers the range pointed by f and e from list x to this list, - //! before the the element pointed by p. No destructors or copy constructors are called. + //! before the element pointed by p. No destructors or copy constructors are called. //! //! Throws: Nothing. //! @@ -929,7 +929,7 @@ class list_impl //! n == std::distance(f, e) //! //! Effects: Transfers the range pointed by f and e from list x to this list, - //! before the the element pointed by p. No destructors or copy constructors are called. + //! before the element pointed by p. No destructors or copy constructors are called. //! //! Throws: Nothing. //! diff --git a/include/boost/intrusive/list_hook.hpp b/include/boost/intrusive/list_hook.hpp index ef55425..0d9bb32 100644 --- a/include/boost/intrusive/list_hook.hpp +++ b/include/boost/intrusive/list_hook.hpp @@ -77,7 +77,7 @@ struct make_list_base_hook //! \c auto_unlink or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -199,7 +199,7 @@ struct make_list_member_hook //! \c auto_unlink or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else diff --git a/include/boost/intrusive/set_hook.hpp b/include/boost/intrusive/set_hook.hpp index ee35279..e6bb3bd 100644 --- a/include/boost/intrusive/set_hook.hpp +++ b/include/boost/intrusive/set_hook.hpp @@ -77,7 +77,7 @@ struct make_set_base_hook //! unique tag. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). @@ -204,7 +204,7 @@ struct make_set_member_hook //! \c link_mode<> and \c optimize_size<>. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). diff --git a/include/boost/intrusive/slist_hook.hpp b/include/boost/intrusive/slist_hook.hpp index fc160d9..a9d5be6 100644 --- a/include/boost/intrusive/slist_hook.hpp +++ b/include/boost/intrusive/slist_hook.hpp @@ -80,7 +80,7 @@ struct make_slist_base_hook //! \c auto_unlink or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -203,7 +203,7 @@ struct make_slist_member_hook //! \c auto_unlink or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else diff --git a/include/boost/intrusive/unordered_set_hook.hpp b/include/boost/intrusive/unordered_set_hook.hpp index 64797e9..fb17a33 100644 --- a/include/boost/intrusive/unordered_set_hook.hpp +++ b/include/boost/intrusive/unordered_set_hook.hpp @@ -207,7 +207,7 @@ struct make_unordered_set_base_hook //! unique tag. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). @@ -341,7 +341,7 @@ struct make_unordered_set_member_hook //! \c link_mode<> and \c store_hash<>. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). From ada32665020b9d70e2842249d025bbadede461cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 29 Dec 2013 13:40:23 +0100 Subject: [PATCH 09/18] Fixed documentation after removal of deprecated splay_set_xxx_hooks. --- doc/intrusive.qbk | 394 +++++++++++++++++----------------------------- 1 file changed, 147 insertions(+), 247 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index 90684a7..4f37f12 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -1364,163 +1364,6 @@ the unordered container: [endsect] -[section:splay_set_multiset Intrusive splay tree based associative containers: splay_set, splay_multiset and , splay_tree] - -C++ associative containers are usually based on red-black tree implementations (e.g.: STL, -Boost.Intrusive associative containers). However, there are other interesting data -structures that offer some advantages (and also disadvantages). - -Splay trees are self-adjusting binary search trees used typically in caches, memory -allocators and other applications, because splay trees have a "caching effect": recently -accessed elements have better access times than elements accessed less frequently. -For more information on splay trees see [@http://en.wikipedia.org/wiki/Splay_tree Wikipedia entry]. - -[*Boost.Intrusive] offers 3 containers based on splay trees: -[classref boost::intrusive::splay_set splay_set], -[classref boost::intrusive::splay_multiset splay_multiset] and -[classref boost::intrusive::splaytree splaytree]. The first two are similar to -[classref boost::intrusive::set set] or -[classref boost::intrusive::multiset multiset] and the latter is a generalization -that offers functions both to insert unique and multiple keys. - -The memory overhead of these containers with Boost.Intrusive hooks is usually 3 pointers. -An empty, non constant-time size splay container has also a size of 3 pointers. - -[section:splay_set_multiset_disadvantages Advantages and disadvantages of splay tree based containers] - -Splay tree based intrusive containers have logarithmic complexity in many -operations like searches, insertions, erasures, etc., but if some elements are -more frequently accessed than others, splay trees perform faster searches than equivalent -balanced binary trees (such as red-black trees). - -The caching effect offered by splay trees comes with a cost: the tree must be -rebalanced when an element is searched. This disallows const versions of search -functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`, -`count()`, etc. - -Because of this, splay-tree based associative containers are not drop-in -replacements of [classref boost::intrusive::set set]/ -[classref boost::intrusive::multiset multiset]. - -Apart from this, if element searches are randomized, the tree will be rebalanced -without taking advantage of the cache effect, so splay trees can offer worse -performance than other balanced trees for some search patterns. - -[endsect] - -[section:splay_set_multiset_hooks splay_set, splay_multiset and splaytree hooks] - -[classref boost::intrusive::splay_set splay_set], -[classref boost::intrusive::splay_multiset splay_multiset] and -[classref boost::intrusive::splaytree splaytree] -share the same hooks. - -[c++] - - template - class splay_set_base_hook; - -* [classref boost::intrusive::splay_set_base_hook splay_set_base_hook]: - the user class derives publicly from this class to make - it compatible with splay tree based containers. - -[c++] - - template - class splay_set_member_hook; - -* [classref boost::intrusive::set_member_hook set_member_hook]: - the user class contains a public member of this class to make - it compatible with splay tree based containers. - -[classref boost::intrusive::splay_set_base_hook splay_set_base_hook] and -[classref boost::intrusive::splay_set_member_hook splay_set_member_hook] receive -the same options explained in the section -[link intrusive.usage How to use Boost.Intrusive]: - -* [*`tag`] (for base hooks only): This argument serves as a tag, - so you can derive from more than one base hook. - Default: `tag`. - -* [*`link_mode`]: The linking policy. - Default: `link_mode`. - -* [*`void_pointer`]: The pointer type to be used - internally in the hook and propagated to the container. - Default: `void_pointer`. - -[endsect] - -[section:set_multiset_containers splay_set, splay_multiset and splaytree containers] - -[c++] - - template - class splay_set; - - template - class splay_multiset; - - template - class splaytree; - -These containers receive the same options explained in the section -[link intrusive.usage How to use Boost.Intrusive]: - -* [*`base_hook`] / [*`member_hook`] / - [*`value_traits`]: To specify the hook type or value traits used - to configure the container. (To learn about value traits go to the section - [link intrusive.value_traits Containers with custom ValueTraits].) - -* [*`constant_time_size`]: To activate the constant-time `size()` operation. - Default: `constant_time_size` - -* [*`size_type`]: To specify the type that will be used to store the size - of the container. Default: `size_type` - -And they also can receive an additional option: - -* [*`compare`]: Comparison function for the objects to be inserted - in containers. The comparison functor must induce a strict weak ordering. - Default: `compare< std::less >` - -[endsect] - -[section:splay_set_bst_hook Splay trees with BST hooks] - -Intrusive splay containers can also use plain binary search tree hooks -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook]. -These hooks can be used by other intrusive containers like -intrusive scapegoat containers -[classref boost::intrusive::sg_set sg_set] and -[classref boost::intrusive::sg_multiset sg_multiset]. A programmer -might prefer using a binary search tree hook so that the same type -can be inserted in some situations in a splay container but -also inserted in other compatible containers when -the hook is not being used in a splay container. - -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and -[classref boost::intrusive::bs_set_base_hook bs_set_member_hook] admit -the same options as [classref boost::intrusive::splay_set_base_hook splay_set_base_hook]. - -[endsect] - -[section:splay_set_multiset_example Example] - -Now let's see a small example using both splay hooks, -binary search tree hooks and -[classref boost::intrusive::splay_set splay_set]/ -[classref boost::intrusive::splay_multiset splay_multiset] -containers: - -[import ../example/doc_splay_set.cpp] -[doc_splay_set_code] - -[endsect] - -[endsect] - [section:avl_set_multiset Intrusive avl tree based associative containers: avl_set, avl_multiset and avltree] Similar to red-black trees, AVL trees are balanced binary trees. @@ -1649,6 +1492,103 @@ containers: [endsect] +[section:splay_set_multiset Intrusive splay tree based associative containers: splay_set, splay_multiset and , splay_tree] + +C++ associative containers are usually based on red-black tree implementations (e.g.: STL, +Boost.Intrusive associative containers). However, there are other interesting data +structures that offer some advantages (and also disadvantages). + +Splay trees are self-adjusting binary search trees used typically in caches, memory +allocators and other applications, because splay trees have a "caching effect": recently +accessed elements have better access times than elements accessed less frequently. +For more information on splay trees see [@http://en.wikipedia.org/wiki/Splay_tree the corresponding Wikipedia entry]. + +[*Boost.Intrusive] offers 3 containers based on splay trees: +[classref boost::intrusive::splay_set splay_set], +[classref boost::intrusive::splay_multiset splay_multiset] and +[classref boost::intrusive::splaytree splaytree]. The first two are similar to +[classref boost::intrusive::set set] or +[classref boost::intrusive::multiset multiset] and the latter is a generalization +that offers functions both to insert unique and multiple keys. + +The memory overhead of these containers with Boost.Intrusive hooks is usually 3 pointers. +An empty, non constant-time size splay container has also a size of 3 pointers. + +[section:splay_set_multiset_disadvantages Advantages and disadvantages of splay tree based containers] + +Splay tree based intrusive containers have logarithmic complexity in many +operations like searches, insertions, erasures, etc., but if some elements are +more frequently accessed than others, splay trees perform faster searches than equivalent +balanced binary trees (such as red-black trees). + +The caching effect offered by splay trees comes with a cost: the tree must be +rebalanced when an element is searched. To maintain const-correctness and thread-safety +guarantees, this caching effect is not updated when const versions of +search functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`, +`count()`... are called. This means that using splay-tree based associative containers as drop-in +replacements of [classref boost::intrusive::set set]/ +[classref boost::intrusive::multiset multiset], specially for const search functions, +might not result in desired performance improvements. + +If element searches are randomized, the tree will be continuously srebalanced +without taking advantage of the cache effect, so splay trees can offer worse +performance than other balanced trees for several search patterns. + +[*Boost.Intrusive] splay associative containers don't use their own hook types but plain Binary search tree hooks. +See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more +information about these hooks. + +[endsect] + +[section:set_multiset_containers splay_set, splay_multiset and splaytree containers] + +[c++] + + template + class splay_set; + + template + class splay_multiset; + + template + class splaytree; + +These containers receive the same options explained in the section +[link intrusive.usage How to use Boost.Intrusive]: + +* [*`base_hook`] / [*`member_hook`] / + [*`value_traits`]: To specify the hook type or value traits used + to configure the container. (To learn about value traits go to the section + [link intrusive.value_traits Containers with custom ValueTraits].) + +* [*`constant_time_size`]: To activate the constant-time `size()` operation. + Default: `constant_time_size` + +* [*`size_type`]: To specify the type that will be used to store the size + of the container. Default: `size_type` + +And they also can receive an additional option: + +* [*`compare`]: Comparison function for the objects to be inserted + in containers. The comparison functor must induce a strict weak ordering. + Default: `compare< std::less >` + +[endsect] + +[section:splay_set_multiset_example Example] + +Now let's see a small example using +[classref boost::intrusive::splay_set splay_set]/ +[classref boost::intrusive::splay_multiset splay_multiset] +containers: + +[import ../example/doc_splay_set.cpp] +[doc_splay_set_code] + +[endsect] + +[endsect] + [section:sg_set_multiset Intrusive scapegoat tree based associative containers: sg_set, sg_multiset and sgtree] @@ -1705,50 +1645,9 @@ An empty, [classref boost::intrusive::sg_set sg_set], has also the size of 3 pointers, two integers and two floating point values (equivalent to the size of 7 pointers on most systems). -[section:sg_set_multiset_hooks Using binary search tree hooks: bs_set_base_hook and bs_set_member_hook] - -[classref boost::intrusive::sg_set sg_set], -[classref boost::intrusive::sg_multiset sg_multiset] and -[classref boost::intrusive::sgtree sgtree] don't use their -own hooks but plain binary search tree hooks. This has many advantages -since binary search tree hooks can also be used to insert values in -splay and treap containers. - -[c++] - - template - class bs_set_base_hook; - -* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]: - the user class derives publicly from this class to make - it compatible with scapegoat tree based containers. - -[c++] - - template - class bs_set_member_hook; - -* [classref boost::intrusive::set_member_hook set_member_hook]: - the user class contains a public member of this class to make - it compatible with scapegoat tree based containers. - -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and -[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive -the same options explained in the section -[link intrusive.usage How to use Boost.Intrusive]: - -* [*`tag`] (for base hooks only): This argument serves as a tag, - so you can derive from more than one base hook. - Default: `tag`. - -* [*`link_mode`]: The linking policy. - Default: `link_mode`. - -* [*`void_pointer`]: The pointer type to be used - internally in the hook and propagated to the container. - Default: `void_pointer`. - -[endsect] +[*Boost.Intrusive] scapegoat associative containers don't use their own hook types but plain Binary search tree hooks. +See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more +information about these hooks. [section:sg_set_multiset_containers sg_set, sg_multiset and sgtree containers] @@ -1791,7 +1690,7 @@ And they also can receive additional options: [section:sg_set_multiset_example Example] -Now let's see a small example using both hooks and +Now let's see a small example using binary search tree hooks and [classref boost::intrusive::sg_set sg_set]/ [classref boost::intrusive::sg_multiset sg_multiset] containers: @@ -1841,50 +1740,9 @@ An empty, [classref boost::intrusive::treap_set treap_set], has also the size of 3 pointers and an integer (supposing empty function objects for key and priority comparison and constant-time size). -[section:treap_set_multiset_hooks Using binary search tree hooks: bs_set_base_hook and bs_set_member_hook] - -[classref boost::intrusive::treap_set treap_set], -[classref boost::intrusive::treap_multiset treap_multiset] and -[classref boost::intrusive::treap treap] don't use their -own hooks but plain binary search tree hooks. This has many advantages -since binary search tree hooks can also be used to insert values in -splay containers and scapegoat trees. - -[c++] - - template - class bs_set_base_hook; - -* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]: - the user class derives publicly from this class to make - it compatible with scapegoat tree based containers. - -[c++] - - template - class bs_set_member_hook; - -* [classref boost::intrusive::set_member_hook set_member_hook]: - the user class contains a public member of this class to make - it compatible with scapegoat tree based containers. - -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and -[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive -the same options explained in the section -[link intrusive.usage How to use Boost.Intrusive]: - -* [*`tag`] (for base hooks only): This argument serves as a tag, - so you can derive from more than one base hook. - Default: `tag`. - -* [*`link_mode`]: The linking policy. - Default: `link_mode`. - -* [*`void_pointer`]: The pointer type to be used - internally in the hook and propagated to the container. - Default: `void_pointer`. - -[endsect] +[*Boost.Intrusive] treap associative containers don't use their own hook types but plain Binary search tree hooks. +See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more +information about these hooks. [section:treap_set_multiset_containers treap_set, treap_multiset and treap containers] @@ -1967,7 +1825,7 @@ the strongest possible behaviour in these situations. In summary: [section:treap_set_multiset_example Example] -Now let's see a small example using both hooks and +Now let's see a small example using binary search tree hooks and [classref boost::intrusive::treap_set treap_set]/ [classref boost::intrusive::treap_multiset treap_multiset] containers: @@ -1979,6 +1837,48 @@ containers: [endsect] +[section:bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] + +Binary search tree hooks can be used with several tree-like containers that don't +need any additional metadata for rebalancing operations. This has many advantages +since binary search tree hooks can also be used to insert values in +plain binary search tree, splay tree, scapegoat tree, and treap containers. + +[c++] + + template + class bs_set_base_hook; + +* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]: + the user class derives publicly from this class to make + it compatible with the mentioned tree based containers. + +[c++] + + template + class bs_set_member_hook; + +* [classref boost::intrusive::bs_set_member_hook bs_set_member_hook]: + the user class contains a public member of this class to make + it compatible with the mentioned tree based containers. + +[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and +[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive +the same options explained in the section +[link intrusive.usage How to use Boost.Intrusive]: + +* [*`tag`] (for base hooks only): This argument serves as a tag, + so you can derive from more than one base hook. + Default: `tag`. + +* [*`link_mode`]: The linking policy. + Default: `link_mode`. + +* [*`void_pointer`]: The pointer type to be used + internally in the hook and propagated to the container. + Default: `void_pointer`. + +[endsect] [section:advanced_lookups_insertions Advanced lookup and insertion functions for associative containers] From 37b30ef5c759182db2cf34611f1ced41251783ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 29 Dec 2013 13:42:55 +0100 Subject: [PATCH 10/18] pack_options is now public, documented and tested so that it can be used by other libraries like Container, to specify new options for customizable containers. --- doc/Jamfile.v2 | 4 +- example/doc_auto_unlink.cpp | 3 +- include/boost/intrusive/options.hpp | 553 ++---------------- include/boost/intrusive/pack_options.hpp | 370 ++++++++++++ proj/vc7ide/Intrusive.sln | 8 + .../vc7ide/_intrusivelib/_intrusivelib.vcproj | 3 + proj/vc7ide/pack_options/pack_options.vcproj | 133 +++++ proj/vc7ide/set/set.vcproj | 1 + test/pack_options_test.cpp | 60 ++ 9 files changed, 638 insertions(+), 497 deletions(-) create mode 100644 include/boost/intrusive/pack_options.hpp create mode 100644 proj/vc7ide/pack_options/pack_options.vcproj create mode 100644 test/pack_options_test.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index d64860b..d21ab56 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -53,7 +53,9 @@ doxygen autodoc \"avltree_impl=avltree\" \\ \"treap_set_impl=treap_set\" \\ \"treap_multiset_impl=treap_multiset\" \\ - \"treap_impl=treap\"" + \"treap_impl=treap\" \\ + \"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template struct OPTION_NAME{};\" \\ + \"BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) = template struct OPTION_NAME{};\" " ; xml intrusive : intrusive.qbk diff --git a/example/doc_auto_unlink.cpp b/example/doc_auto_unlink.cpp index 5fb12f4..b44dd31 100644 --- a/example/doc_auto_unlink.cpp +++ b/example/doc_auto_unlink.cpp @@ -24,7 +24,8 @@ class MyClass : public auto_unlink_hook public: MyClass(int i = 0) : int_(i) {} - void unlink() { auto_unlink_hook::unlink(); } + int get_int() { return int_; } + void unlink() { auto_unlink_hook::unlink(); } bool is_linked() { return auto_unlink_hook::is_linked(); } }; diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index 6d06a79..cbbd123 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -16,15 +16,15 @@ #include #include #include +#include #include #include #include - namespace boost { namespace intrusive { -/// @cond +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED //typedef void default_tag; struct default_tag; @@ -34,8 +34,6 @@ namespace detail{ struct default_hook_tag{}; -#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - #define BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER) \ struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\ {\ @@ -50,14 +48,9 @@ BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_rbtree_hook); BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_hashtable_hook); BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_avltree_hook); BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bstree_hook); -//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_splaytree_hook); -//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_sgtree_hook); -//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_treap_hook); #undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION -#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED - template struct eval_value_traits { @@ -165,7 +158,7 @@ struct get_value_traits //...get it's internal value traits using //the provided T value type. , get_base_value_traits - //...else use it's internal value traits tag + //...else use its internal value traits tag //(member hooks and custom value traits are in this group) , detail::eval_if_c < internal_member_value_traits::value @@ -191,7 +184,7 @@ struct get_node_traits //...get it's internal value traits using //the provided T value type. , get_base_node_traits - //...else use it's internal value traits tag + //...else use its internal value traits tag //(member hooks and custom value traits are in this group) , detail::eval_if_c < internal_member_value_traits::value @@ -203,50 +196,20 @@ struct get_node_traits } //namespace detail{ -/// @endcond +#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED //!This option setter specifies if the intrusive //!container stores its size as a member to //!obtain constant-time size() member. -template -struct constant_time_size -{ -/// @cond - template - struct pack : Base - { - static const bool constant_time_size = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(constant_time_size, bool, Enabled, constant_time_size) //!This option setter specifies the type that //!the container will use to store its size. -template -struct size_type -{ -/// @cond - template - struct pack : Base - { - typedef SizeType size_type; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(size_type, SizeType, SizeType, size_type) //!This option setter specifies the strict weak ordering //!comparison functor for the value type -template -struct compare -{ -/// @cond - template - struct pack : Base - { - typedef Compare compare; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(compare, Compare, Compare, compare) //!This option setter for scapegoat containers specifies if //!the intrusive scapegoat container should use a non-variable @@ -260,74 +223,39 @@ struct compare //!If the user only needs an alpha value near 1/sqrt(2), this //!option also improves performance since avoids logarithm //!and division operations when rebalancing the tree. -template -struct floating_point -{ -/// @cond - template - struct pack : Base - { - static const bool floating_point = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(floating_point, bool, Enabled, floating_point) //!This option setter specifies the equality //!functor for the value type -template -struct equal -{ -/// @cond - template - struct pack : Base - { - typedef Equal equal; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(equal, Equal, Equal, equal) //!This option setter specifies the equality //!functor for the value type -template -struct priority -{ -/// @cond - template - struct pack : Base - { - typedef Priority priority; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(priority, Priority, Priority, priority) //!This option setter specifies the hash //!functor for the value type -template -struct hash -{ -/// @cond - template - struct pack : Base - { - typedef Hash hash; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(hash, Hash, Hash, hash) //!This option setter specifies the relationship between the type //!to be managed by the container (the value type) and the node to be //!used in the node algorithms. It also specifies the linking policy. -template -struct value_traits -{ -/// @cond - template - struct pack : Base - { - typedef ValueTraits proto_value_traits; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(value_traits, ValueTraits, ValueTraits, proto_value_traits) + +//#define BOOST_INTRUSIVE_COMMA , +//#define BOOST_INTRUSIVE_LESS < +//#define BOOST_INTRUSIVE_MORE > +//BOOST_INTRUSIVE_OPTION_TYPE (member_hook, Parent BOOST_INTRUSIVE_COMMA class MemberHook BOOST_INTRUSIVE_COMMA MemberHook Parent::* PtrToMember , mhtraits BOOST_INTRUSIVE_LESS Parent BOOST_INTRUSIVE_COMMA MemberHook BOOST_INTRUSIVE_COMMA PtrToMember BOOST_INTRUSIVE_MORE , proto_value_traits) +//template< class Parent , class MemberHook , MemberHook Parent::* PtrToMember> +//struct member_hook { +// template struct pack : Base { +// typedef mhtraits < Parent , MemberHook , PtrToMember > proto_value_traits; +// }; +//}; +// +//#undef BOOST_INTRUSIVE_COMMA +//#undef BOOST_INTRUSIVE_LESS +//#undef BOOST_INTRUSIVE_MORE //!This option setter specifies the member hook the //!container must use. @@ -336,27 +264,21 @@ template< typename Parent , MemberHook Parent::* PtrToMember> struct member_hook { -/// @cond -/* - typedef typename MemberHook::hooktags::node_traits node_traits; - typedef typename node_traits::node node_type; - typedef node_type Parent::* Ptr2MemNode; - typedef mhtraits - < Parent - , node_traits - //This cast is really ugly but necessary to reduce template bloat. - //Since we control the layout between the hook and the node, and there is - //always single inheritance, the offset of the node is exactly the offset of - //the hook. Since the node type is shared between all member hooks, this saves - //quite a lot of symbol stuff. - , (Ptr2MemNode)PtrToMember - , MemberHook::hooktags::link_mode> member_value_traits; -*/ - typedef mhtraits - < Parent - , MemberHook - , PtrToMember - > member_value_traits; +// @cond +// typedef typename MemberHook::hooktags::node_traits node_traits; +// typedef typename node_traits::node node_type; +// typedef node_type Parent::* Ptr2MemNode; +// typedef mhtraits +// < Parent +// , node_traits +// //This cast is really ugly but necessary to reduce template bloat. +// //Since we control the layout between the hook and the node, and there is +// //always single inheritance, the offset of the node is exactly the offset of +// //the hook. Since the node type is shared between all member hooks, this saves +// //quite a lot of symbol stuff. +// , (Ptr2MemNode)PtrToMember +// , MemberHook::hooktags::link_mode> member_value_traits; + typedef mhtraits member_value_traits; template struct pack : Base { @@ -365,158 +287,54 @@ struct member_hook /// @endcond }; - //!This option setter specifies the function object that will //!be used to convert between values to be inserted in a container //!and the hook to be used for that purpose. -template< typename Functor> -struct function_hook -{ -/// @cond - typedef fhtraits - function_value_traits; - template - struct pack : Base - { - typedef function_value_traits proto_value_traits; - }; -/// @endcond -}; - +BOOST_INTRUSIVE_OPTION_TYPE(function_hook, Functor, fhtraits, proto_value_traits) //!This option setter specifies that the container //!must use the specified base hook -template -struct base_hook -{ -/// @cond - template - struct pack : Base - { - typedef BaseHook proto_value_traits; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(base_hook, BaseHook, BaseHook, proto_value_traits) //!This option setter specifies the type of //!a void pointer. This will instruct the hook //!to use this type of pointer instead of the //!default one -template -struct void_pointer -{ -/// @cond - template - struct pack : Base - { - typedef VoidPointer void_pointer; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(void_pointer, VoidPointer, VoidPointer, void_pointer) //!This option setter specifies the type of //!the tag of a base hook. A type cannot have two //!base hooks of the same type, so a tag can be used //!to differentiate two base hooks with otherwise same type -template -struct tag -{ -/// @cond - template - struct pack : Base - { - typedef Tag tag; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(tag, Tag, Tag, tag) //!This option setter specifies the link mode //!(normal_link, safe_link or auto_unlink) -template -struct link_mode -{ -/// @cond - template - struct pack : Base - { - static const link_mode_type link_mode = LinkType; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(link_mode, link_mode_type, LinkType, link_mode) //!This option setter specifies if the hook //!should be optimized for size instead of for speed. -template -struct optimize_size -{ -/// @cond - template - struct pack : Base - { - static const bool optimize_size = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size) //!This option setter specifies if the list container should //!use a linear implementation instead of a circular one. -template -struct linear -{ -/// @cond - template - struct pack : Base - { - static const bool linear = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(linear, bool, Enabled, linear) //!This option setter specifies if the list container should //!use a linear implementation instead of a circular one. -template -struct cache_last -{ -/// @cond - template - struct pack : Base - { - static const bool cache_last = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(cache_last, bool, Enabled, cache_last) //!This option setter specifies the bucket traits //!class for unordered associative containers. When this option is specified, //!instead of using the default bucket traits, a user defined holder will be defined -template -struct bucket_traits -{ -/// @cond - template - struct pack : Base - { - typedef BucketTraits bucket_traits; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(bucket_traits, BucketTraits, BucketTraits, bucket_traits) //!This option setter specifies if the unordered hook //!should offer room to store the hash value. //!Storing the hash in the hook will speed up rehashing //!processes in applications where rehashing is frequent, //!rehashing might throw or the value is heavy to hash. -template -struct store_hash -{ -/// @cond - template - struct pack : Base - { - static const bool store_hash = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(store_hash, bool, Enabled, store_hash) //!This option setter specifies if the unordered hook //!should offer room to store another link to another node @@ -524,51 +342,20 @@ struct store_hash //!Storing this link will speed up lookups and insertions on //!unordered_multiset containers with a great number of elements //!with the same key. -template -struct optimize_multikey -{ -/// @cond - template - struct pack : Base - { - static const bool optimize_multikey = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_multikey, bool, Enabled, optimize_multikey) //!This option setter specifies if the bucket array will be always power of two. //!This allows using masks instead of the default modulo operation to determine //!the bucket number from the hash value, leading to better performance. //!In debug mode, if power of two buckets mode is activated, the bucket length //!will be checked to through assertions to assure the bucket length is power of two. -template -struct power_2_buckets -{ -/// @cond - template - struct pack : Base - { - static const bool power_2_buckets = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(power_2_buckets, bool, Enabled, power_2_buckets) //!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 -struct cache_begin -{ -/// @cond - template - struct pack : Base - { - static const bool cache_begin = Enabled; - }; -/// @endcond -}; - +BOOST_INTRUSIVE_OPTION_CONSTANT(cache_begin, bool, Enabled, cache_begin) //!This option setter specifies if the container will compare the hash value //!before comparing objects. This option can't be specified if store_hash<> @@ -576,17 +363,7 @@ struct cache_begin //!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 -struct compare_hash -{ -/// @cond - template - struct pack : Base - { - static const bool compare_hash = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(compare_hash, bool, Enabled, compare_hash) //!This option setter specifies if the hash container will use incremental //!hashing. With incremental hashing the cost of hash table expansion is spread @@ -594,17 +371,7 @@ struct compare_hash //!Therefore linear hashing is well suited for interactive applications or real-time //!appplications where the worst-case insertion time of non-incremental hash containers //!(rehashing the whole bucket array) is not admisible. -template -struct incremental -{ - /// @cond - template - struct pack : Base - { - static const bool incremental = Enabled; - }; - /// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, incremental) /// @cond @@ -615,210 +382,6 @@ struct none {}; }; -//To-do: pass to variadic templates -#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - -template -struct do_pack -{ - //Use "pack" member template to pack options - typedef typename Next::template pack type; -}; - -template -struct do_pack -{ - //Avoid packing "void" to shorten template names - typedef Prev type; -}; - -template - < class DefaultOptions - , class O1 = void - , class O2 = void - , class O3 = void - , class O4 = void - , class O5 = void - , class O6 = void - , class O7 = void - , class O8 = void - , class O9 = void - , class O10 = void - , class O11 = void - > -struct pack_options -{ - // join options - typedef - typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < DefaultOptions - , O1 - >::type - , O2 - >::type - , O3 - >::type - , O4 - >::type - , O5 - >::type - , O6 - >::type - , O7 - >::type - , O8 - >::type - , O9 - >::type - , O10 - >::type - , O11 - >::type - type; -}; -#else - -//index_tuple -template -struct index_tuple{}; - -//build_number_seq -template > -struct build_number_seq; - -template -struct build_number_seq > - : build_number_seq > -{}; - -template -struct build_number_seq<0, index_tuple > -{ typedef index_tuple type; }; - -template -struct typelist -{}; - -//invert_typelist -template -struct invert_typelist; - -template -struct typelist_element; - -template -struct typelist_element > -{ - typedef typename typelist_element >::type type; -}; - -template -struct typelist_element<0, typelist > -{ - typedef Head type; -}; - -template -typelist >::type...> - inverted_typelist(index_tuple, typelist) -{ - return typelist >::type...>(); -} - -//sizeof_typelist -template -struct sizeof_typelist; - -template -struct sizeof_typelist< typelist > -{ - static const std::size_t value = sizeof...(Types); -}; - -//invert_typelist_impl -template -struct invert_typelist_impl; - - -template -struct invert_typelist_impl< Typelist, index_tuple > -{ - static const std::size_t last_idx = sizeof_typelist::value - 1; - typedef typelist - ::type...> type; -}; - -template -struct invert_typelist_impl< Typelist, index_tuple > -{ - typedef Typelist type; -}; - -template -struct invert_typelist_impl< Typelist, index_tuple<> > -{ - typedef Typelist type; -}; - -//invert_typelist -template -struct invert_typelist; - -template -struct invert_typelist< typelist > -{ - typedef typelist typelist_t; - typedef typename build_number_seq::type indexes_t; - typedef typename invert_typelist_impl::type type; -}; - -//Do pack -template -struct do_pack; - -template<> -struct do_pack >; - -template -struct do_pack > -{ - typedef Prev type; -}; - -template -struct do_pack > -{ - typedef typename Prev::template pack type; -}; - -template -struct do_pack > -{ - typedef typename Prev::template pack - >::type> type; -}; - - -template -struct pack_options -{ - typedef typelist typelist_t; - typedef typename invert_typelist::type inverted_typelist; - typedef typename do_pack::type type; -}; - -#endif - struct hook_defaults { typedef void* void_pointer; diff --git a/include/boost/intrusive/pack_options.hpp b/include/boost/intrusive/pack_options.hpp new file mode 100644 index 0000000..7d282dd --- /dev/null +++ b/include/boost/intrusive/pack_options.hpp @@ -0,0 +1,370 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-2013 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP +#define BOOST_INTRUSIVE_PACK_OPTIONS_HPP + +#include + +namespace boost { +namespace intrusive { + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + +template +struct do_pack +{ + //Use "pack" member template to pack options + typedef typename Next::template pack type; +}; + +template +struct do_pack +{ + //Avoid packing "void" to shorten template names + typedef Prev type; +}; + +template + < class DefaultOptions + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void + , class O5 = void + , class O6 = void + , class O7 = void + , class O8 = void + , class O9 = void + , class O10 = void + , class O11 = void + > +struct pack_options +{ + // join options + typedef + typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < DefaultOptions + , O1 + >::type + , O2 + >::type + , O3 + >::type + , O4 + >::type + , O5 + >::type + , O6 + >::type + , O7 + >::type + , O8 + >::type + , O9 + >::type + , O10 + >::type + , O11 + >::type + type; +}; +#else + +//index_tuple +template +struct index_tuple{}; + +//build_number_seq +template > +struct build_number_seq; + +template +struct build_number_seq > + : build_number_seq > +{}; + +template +struct build_number_seq<0, index_tuple > +{ typedef index_tuple type; }; + +template +struct typelist +{}; + +//invert_typelist +template +struct invert_typelist; + +template +struct typelist_element; + +template +struct typelist_element > +{ + typedef typename typelist_element >::type type; +}; + +template +struct typelist_element<0, typelist > +{ + typedef Head type; +}; + +template +typelist >::type...> + inverted_typelist(index_tuple, typelist) +{ + return typelist >::type...>(); +} + +//sizeof_typelist +template +struct sizeof_typelist; + +template +struct sizeof_typelist< typelist > +{ + static const std::size_t value = sizeof...(Types); +}; + +//invert_typelist_impl +template +struct invert_typelist_impl; + + +template +struct invert_typelist_impl< Typelist, index_tuple > +{ + static const std::size_t last_idx = sizeof_typelist::value - 1; + typedef typelist + ::type...> type; +}; + +template +struct invert_typelist_impl< Typelist, index_tuple > +{ + typedef Typelist type; +}; + +template +struct invert_typelist_impl< Typelist, index_tuple<> > +{ + typedef Typelist type; +}; + +//invert_typelist +template +struct invert_typelist; + +template +struct invert_typelist< typelist > +{ + typedef typelist typelist_t; + typedef typename build_number_seq::type indexes_t; + typedef typename invert_typelist_impl::type type; +}; + +//Do pack +template +struct do_pack; + +template<> +struct do_pack >; + +template +struct do_pack > +{ + typedef Prev type; +}; + +template +struct do_pack > +{ + typedef typename Prev::template pack type; +}; + +template +struct do_pack > +{ + typedef typename Prev::template pack + >::type> type; +}; + + +template +struct pack_options +{ + typedef typelist typelist_t; + typedef typename invert_typelist::type inverted_typelist; + typedef typename do_pack::type type; +}; + +#endif //!defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + +#define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) \ +template< class TYPE> \ +struct OPTION_NAME \ +{ \ + template \ + struct pack : Base \ + { \ + typedef TYPEDEF_EXPR TYPEDEF_NAME; \ + }; \ +}; \ +// + +#define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) \ +template< TYPE VALUE> \ +struct OPTION_NAME \ +{ \ + template \ + struct pack : Base \ + { \ + static const TYPE CONSTANT_NAME = VALUE; \ + }; \ +}; \ +// + +#else //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +//! This class is a utility that takes: +//! - a default options class defining initial static constant +//! and typedefs +//! - several options defined with BOOST_INTRUSIVE_OPTION_CONSTANT and +//! BOOST_INTRUSIVE_OPTION_TYPE +//! +//! and packs them together in a new type that defines all options as +//! member typedefs or static constant values. Given options of form: +//! +//! \code +//! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, VoidPointer, my_pointer_type) +//! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) +//! \endcode +//! +//! the following expression +//! +//! \code +//! +//! struct default_options +//! { +//! typedef long int_type; +//! static const int int_constant = -1; +//! }; +//! +//! pack_options< default_options, my_pointer, incremental >::type +//! \endcode +//! +//! will create a type that will contain the following typedefs/constants +//! +//! \code +//! struct unspecified_type +//! { +//! //Default options +//! typedef long int_type; +//! static const int int_constant = -1; +//! +//! //Packed options (will ovewrite any default option) +//! typedef void* my_pointer_type; +//! static const bool is_incremental = true; +//! }; +//! \endcode +//! +//! If an option is specified in the default options argument and later +//! redefined as an option, the last definition will prevail. +template +struct pack_options +{ + typedef unspecified_type type; +}; + +//! Defines an option class of name OPTION_NAME that can be used to specify a type +//! of type TYPE... +//! +//! \code +//! struct OPTION_NAME +//! { /*unspecified_content*/ }; +//! \endcode +//! +//! ...that after being combined with +//! boost::intrusive::pack_options, +//! will typedef TYPE as a typedef of name TYPEDEF_NAME. Example: +//! +//! \code +//! //[includes and namespaces omitted for brevity] +//! +//! //This macro will create the following class: +//! // template +//! // struct my_pointer +//! // { unspecified_content }; +//! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, boost::remove_pointer::type, my_pointer_type) +//! +//! struct empty_default{}; +//! +//! typedef pack_options< empty_default, typename my_pointer >::type::my_pointer_type type; +//! +//! BOOST_STATIC_ASSERT(( boost::is_same::value )); +//! +//! \endcode +#define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) + +//! Defines an option class of name OPTION_NAME that can be used to specify a constant +//! of type TYPE with value VALUE... +//! +//! \code +//! struct OPTION_NAME +//! { /*unspecified_content*/ }; +//! \endcode +//! +//! ...that after being combined with +//! boost::intrusive::pack_options, +//! will contain a CONSTANT_NAME static constant of value VALUE. Example: +//! +//! \code +//! //[includes and namespaces omitted for brevity] +//! +//! //This macro will create the following class: +//! // template +//! // struct incremental +//! // { unspecified_content }; +//! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) +//! +//! struct empty_default{}; +//! +//! const bool is_incremental = pack_options< empty_default, incremental >::type::is_incremental; +//! +//! BOOST_STATIC_ASSERT(( is_incremental == true )); +//! +//! \endcode +#define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) + +#endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + +} //namespace intrusive { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP diff --git a/proj/vc7ide/Intrusive.sln b/proj/vc7ide/Intrusive.sln index 54fcb68..890c29e 100644 --- a/proj/vc7ide/Intrusive.sln +++ b/proj/vc7ide/Intrusive.sln @@ -115,6 +115,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scary_iterators", "scary_it ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pack_options", "pack_options\pack_options.vcproj", "{77F4139B-281B-F694-7CB1-3495467B4D35}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -239,6 +243,10 @@ Global {7679B41B-C1C5-FA34-9614-3547B3140346}.Debug.Build.0 = Debug|Win32 {7679B41B-C1C5-FA34-9614-3547B3140346}.Release.ActiveCfg = Release|Win32 {7679B41B-C1C5-FA34-9614-3547B3140346}.Release.Build.0 = Release|Win32 + {77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.ActiveCfg = Debug|Win32 + {77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.Build.0 = Debug|Win32 + {77F4139B-281B-F694-7CB1-3495467B4D35}.Release.ActiveCfg = Release|Win32 + {77F4139B-281B-F694-7CB1-3495467B4D35}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj index 31c88f3..079a8ae 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -157,6 +157,9 @@ + + diff --git a/proj/vc7ide/pack_options/pack_options.vcproj b/proj/vc7ide/pack_options/pack_options.vcproj new file mode 100644 index 0000000..6da13c6 --- /dev/null +++ b/proj/vc7ide/pack_options/pack_options.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/set/set.vcproj b/proj/vc7ide/set/set.vcproj index f7a9976..2fb2369 100644 --- a/proj/vc7ide/set/set.vcproj +++ b/proj/vc7ide/set/set.vcproj @@ -21,6 +21,7 @@ Optimization="0" AdditionalIncludeDirectories="../../../../../" PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + GeneratePreprocessedFile="0" MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" diff --git a/test/pack_options_test.cpp b/test/pack_options_test.cpp new file mode 100644 index 0000000..2f0ef09 --- /dev/null +++ b/test/pack_options_test.cpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +struct empty_default{}; + +using namespace boost::intrusive; + +//Test BOOST_INTRUSIVE_OPTION_CONSTANT +BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) +const bool is_incremental_value = pack_options< empty_default, incremental >::type::is_incremental; +BOOST_STATIC_ASSERT(( is_incremental_value == true )); + +//Test BOOST_INTRUSIVE_OPTION_TYPE +BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, typename boost::remove_pointer::type, my_pointer_type) +typedef pack_options< empty_default, my_pointer >::type::my_pointer_type my_pointer_type; +BOOST_STATIC_ASSERT(( boost::is_same::value )); + +//test combination of BOOST_INTRUSIVE_OPTION_CONSTANT and BOOST_INTRUSIVE_OPTION_TYPE +// First add new options +struct default_options +{ + static const long long_constant = -3; + typedef double * double_typedef; +}; + +BOOST_INTRUSIVE_OPTION_CONSTANT(incremental2, bool, Enabled, is_incremental2) +BOOST_INTRUSIVE_OPTION_TYPE(my_pointer2, VoidPointer, typename boost::add_pointer::type, my_pointer_type2) +typedef pack_options < default_options + , incremental + , my_pointer + , incremental2 + , my_pointer2 + >::type combined_type; +BOOST_STATIC_ASSERT(( combined_type::is_incremental == false )); +BOOST_STATIC_ASSERT(( combined_type::is_incremental2 == true )); +BOOST_STATIC_ASSERT(( boost::is_same::value )); +BOOST_STATIC_ASSERT(( boost::is_same::value )); + +//test packing the default options leads to a default options type +BOOST_STATIC_ASSERT(( boost::is_same::type, default_options>::value )); + +int main() +{ + return 0; +} + +#include From 7093b464ca6a1637a22e21bf4ac1af273eb78086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 31 Dec 2013 12:31:11 +0100 Subject: [PATCH 11/18] Simplified rebalancing code extracting common operations to a local variable --- .../boost/intrusive/avltree_algorithms.hpp | 47 ++++++++++--------- include/boost/intrusive/rbtree_algorithms.hpp | 41 ++++------------ 2 files changed, 35 insertions(+), 53 deletions(-) diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 526649a..54f9fe0 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -364,13 +364,14 @@ class avltree_algorithms node_ptr x(xnode), x_parent(xnode_parent); for (node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)) { const balance x_parent_balance = NodeTraits::get_balance(x_parent); + node_ptr const x_parent_left(NodeTraits::get_left(x_parent)); if(x_parent_balance == NodeTraits::zero()){ - NodeTraits::set_balance(x_parent, - (x == NodeTraits::get_right(x_parent) ? NodeTraits::negative() : NodeTraits::positive())); + NodeTraits::set_balance( x_parent + , x == x_parent_left ? NodeTraits::positive() : NodeTraits::negative() ); break; // the height didn't change, let's stop here } else if(x_parent_balance == NodeTraits::negative()){ - if (x == NodeTraits::get_left(x_parent)) { + if (x == x_parent_left) { NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced x = x_parent; x_parent = NodeTraits::get_parent(x_parent); @@ -378,7 +379,7 @@ class avltree_algorithms else { // x is right child // a is left child - node_ptr a = NodeTraits::get_left(x_parent); + node_ptr a = x_parent_left; BOOST_INTRUSIVE_INVARIANT_ASSERT(a); if (NodeTraits::get_balance(a) == NodeTraits::positive()) { // a MUST have a right child @@ -441,38 +442,38 @@ class avltree_algorithms NodeTraits::set_balance(x, NodeTraits::zero()); // Rebalance. for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){ - const balance x_parent_balance = NodeTraits::get_balance(NodeTraits::get_parent(x)); - + node_ptr const x_parent(NodeTraits::get_parent(x)); + node_ptr const x_parent_left(NodeTraits::get_left(x_parent)); + const balance x_parent_balance = NodeTraits::get_balance(x_parent); if(x_parent_balance == NodeTraits::zero()){ // if x is left, parent will have parent->bal_factor = negative // else, parent->bal_factor = NodeTraits::positive() - NodeTraits::set_balance( NodeTraits::get_parent(x) - , x == NodeTraits::get_left(NodeTraits::get_parent(x)) - ? NodeTraits::negative() : NodeTraits::positive() ); - x = NodeTraits::get_parent(x); + NodeTraits::set_balance( x_parent, x == x_parent_left + ? NodeTraits::negative() : NodeTraits::positive() ); + x = x_parent; } else if(x_parent_balance == NodeTraits::positive()){ // if x is a left child, parent->bal_factor = zero - if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) - NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); + if (x == x_parent_left) + NodeTraits::set_balance(x_parent, NodeTraits::zero()); else{ // x is a right child, needs rebalancing if (NodeTraits::get_balance(x) == NodeTraits::negative()) - rotate_right_left(NodeTraits::get_parent(x), header); + rotate_right_left(x_parent, header); else - rotate_left(NodeTraits::get_parent(x), header); + rotate_left(x_parent, header); } break; } else if(x_parent_balance == NodeTraits::negative()){ // if x is a left child, needs rebalancing - if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) { + if (x == x_parent_left) { if (NodeTraits::get_balance(x) == NodeTraits::positive()) - rotate_left_right(NodeTraits::get_parent(x), header); + rotate_left_right(x_parent, header); else - rotate_right(NodeTraits::get_parent(x), header); + rotate_right(x_parent, header); } else - NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); + NodeTraits::set_balance(x_parent, NodeTraits::zero()); break; } else{ @@ -486,18 +487,20 @@ class avltree_algorithms // balancing... const balance c_balance = NodeTraits::get_balance(c); const balance zero_balance = NodeTraits::zero(); + const balance posi_balance = NodeTraits::positive(); + const balance nega_balance = NodeTraits::negative(); NodeTraits::set_balance(c, zero_balance); - if(c_balance == NodeTraits::negative()){ - NodeTraits::set_balance(a, NodeTraits::positive()); + if(c_balance == nega_balance){ + NodeTraits::set_balance(a, posi_balance); NodeTraits::set_balance(b, zero_balance); } else if(c_balance == zero_balance){ NodeTraits::set_balance(a, zero_balance); NodeTraits::set_balance(b, zero_balance); } - else if(c_balance == NodeTraits::positive()){ + else if(c_balance == posi_balance){ NodeTraits::set_balance(a, zero_balance); - NodeTraits::set_balance(b, NodeTraits::negative()); + NodeTraits::set_balance(b, nega_balance); } else{ BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 529ef90..e20b4d8 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -10,31 +10,6 @@ // See http://www.boost.org/libs/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// -// The internal implementation of red-black trees is based on that of SGI STL -// stl_tree.h file: -// -// Copyright (c) 1996,1997 -// Silicon Graphics Computer Systems, Inc. -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. Silicon Graphics makes no -// representations about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. -// -// -// Copyright (c) 1994 -// Hewlett-Packard Company -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. Hewlett-Packard Company makes no -// representations about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. // // The tree destruction algorithm is based on Julienne Walker and The EC Team code: // @@ -421,14 +396,16 @@ class rbtree_algorithms bstree_algo::rotate_left(x_parent, header); w = NodeTraits::get_right(x_parent); } - if((!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()) && - (!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black())){ + node_ptr const w_left (NodeTraits::get_left(w)); + node_ptr const w_right(NodeTraits::get_right(w)); + if((!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()) && + (!w_right || NodeTraits::get_color(w_right) == NodeTraits::black())){ NodeTraits::set_color(w, NodeTraits::red()); x = x_parent; x_parent = NodeTraits::get_parent(x_parent); } else { - if(!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()){ + if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){ NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); NodeTraits::set_color(w, NodeTraits::red()); bstree_algo::rotate_right(w, header); @@ -451,14 +428,16 @@ class rbtree_algorithms bstree_algo::rotate_right(x_parent, header); w = NodeTraits::get_left(x_parent); } - if((!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()) && - (!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black())){ + node_ptr const w_left (NodeTraits::get_left(w)); + node_ptr const w_right(NodeTraits::get_right(w)); + if((!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()) && + (!w_left || NodeTraits::get_color(w_left) == NodeTraits::black())){ NodeTraits::set_color(w, NodeTraits::red()); x = x_parent; x_parent = NodeTraits::get_parent(x_parent); } else { - if(!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()){ + if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){ NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); NodeTraits::set_color(w, NodeTraits::red()); bstree_algo::rotate_left(w, header); From fe39a4762120c4d5b19b32923b0b9d7caae266c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 2 Jan 2014 21:36:49 +0100 Subject: [PATCH 12/18] Fixed copy/paste error in "cache_last" option's documentation. --- doc/intrusive.qbk | 2 +- include/boost/intrusive/options.hpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index 4f37f12..aca3694 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -871,7 +871,7 @@ the section [link intrusive.usage How to use Boost.Intrusive]: * [*`linear`]: the singly linked list is implemented as a null-terminated list instead of a circular list. This allows `O(1)` swap, but losses some operations like `container_from_end_iterator`. -* [*`cache_last`]: the singly linked also stores a pointer to the +* [*`cache_last`]: `slist` also stores a pointer to the last element of the singly linked list. This allows `O(1)` swap, `splice_after(iterator, slist &)` and makes the list offer new functions like `push_back(reference)` and `back()`. Logically, the size an empty list is diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index cbbd123..f6854e4 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -316,12 +316,13 @@ BOOST_INTRUSIVE_OPTION_CONSTANT(link_mode, link_mode_type, LinkType, link_mode) //!should be optimized for size instead of for speed. BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size) -//!This option setter specifies if the list container should +//!This option setter specifies if the slist container should //!use a linear implementation instead of a circular one. BOOST_INTRUSIVE_OPTION_CONSTANT(linear, bool, Enabled, linear) -//!This option setter specifies if the list container should -//!use a linear implementation instead of a circular one. +//!If true, slist also stores a pointer to the last element of the singly linked list. +//!This allows O(1) swap and splice_after(iterator, slist &) for circular slists and makes +//!possible new functions like push_back(reference) and back(). BOOST_INTRUSIVE_OPTION_CONSTANT(cache_last, bool, Enabled, cache_last) //!This option setter specifies the bucket traits From 0e755330d98bb98f892f85b82a346ce666eb012f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 5 Jan 2014 22:16:29 +0100 Subject: [PATCH 13/18] Simplify splay algorithms avoiding redundant calls. --- include/boost/intrusive/bstree_algorithms.hpp | 1 - .../boost/intrusive/splaytree_algorithms.hpp | 59 ++++++++++--------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index 9ae1d32..1766e0d 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -825,7 +825,6 @@ class bstree_algorithms //If the upper_key is less than x, the target //range is on the left part else if(comp(upper_key, x)){ - //y > upper_key y = x; x = NodeTraits::get_left(x); } diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index 5d580a6..3627b8c 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -510,19 +510,20 @@ class splaytree_algorithms for( ;; ){ if(comp(key, t)){ - if(NodeTraits::get_left(t) == node_ptr() ) + node_ptr const t_left = NodeTraits::get_left(t); + if(!t_left) break; - if(comp(key, NodeTraits::get_left(t))){ + if(comp(key, t_left)){ t = bstree_algo::rotate_right(t); - if(NodeTraits::get_left(t) == node_ptr()) + if( !NodeTraits::get_left(t) ) break; link_right(t, r); } - else if(comp(NodeTraits::get_left(t), key)){ + else if(comp(t_left, key)){ link_right(t, r); - if(NodeTraits::get_right(t) == node_ptr() ) + if( !NodeTraits::get_right(t) ) break; link_left(t, l); } @@ -531,20 +532,21 @@ class splaytree_algorithms } } else if(comp(t, key)){ - if(NodeTraits::get_right(t) == node_ptr() ) + node_ptr const t_right = NodeTraits::get_right(t); + if(!t_right) break; - if(comp(NodeTraits::get_right(t), key)){ + if(comp(t_right, key)){ t = bstree_algo::rotate_left( t ); - if(NodeTraits::get_right(t) == node_ptr() ) + if( !NodeTraits::get_right(t) ) break; link_left(t, l); } - else if(comp(key, NodeTraits::get_right(t))){ + else if(comp(key, t_right)){ link_left(t, l); - if(NodeTraits::get_left(t) == node_ptr()) + if( !NodeTraits::get_left(t) ) break; link_right(t, r); @@ -580,26 +582,29 @@ class splaytree_algorithms // assemble the three sub-trees into new tree pointed to by t | complexity : constant | exception : nothrow static void assemble(const node_ptr &t, const node_ptr & l, const node_ptr & r, const const_node_ptr & null_node ) { - NodeTraits::set_right(l, NodeTraits::get_left(t)); - NodeTraits::set_left(r, NodeTraits::get_right(t)); + node_ptr const new_l_right = NodeTraits::get_left(t); + node_ptr const new_r_left = NodeTraits::get_right(t); + NodeTraits::set_right(l, new_l_right); + NodeTraits::set_left (r, new_r_left); - if(NodeTraits::get_right(l) != node_ptr()){ - NodeTraits::set_parent(NodeTraits::get_right(l), l); + if(new_l_right){ + NodeTraits::set_parent(new_l_right, l); + } + if(new_r_left){ + NodeTraits::set_parent(new_r_left, r); } - if(NodeTraits::get_left(r) != node_ptr()){ - NodeTraits::set_parent(NodeTraits::get_left(r), r); + node_ptr const t_new_left = NodeTraits::get_right(null_node); + node_ptr const t_new_right = NodeTraits::get_left(null_node); + NodeTraits::set_left (t, t_new_left); + NodeTraits::set_right(t, t_new_right); + + if(t_new_left){ + NodeTraits::set_parent(t_new_left, t); } - NodeTraits::set_left (t, NodeTraits::get_right(null_node)); - NodeTraits::set_right(t, NodeTraits::get_left(null_node)); - - if( NodeTraits::get_left(t) != node_ptr() ){ - NodeTraits::set_parent(NodeTraits::get_left(t), t); - } - - if( NodeTraits::get_right(t) ){ - NodeTraits::set_parent(NodeTraits::get_right(t), t); + if(t_new_right){ + NodeTraits::set_parent(t_new_right, t); } } @@ -632,13 +637,13 @@ class splaytree_algorithms if(NodeTraits::get_left(p) == n){ NodeTraits::set_left(p, NodeTraits::get_right(n)); - if(NodeTraits::get_left(p) != node_ptr()) + if(NodeTraits::get_left(p)) NodeTraits::set_parent(NodeTraits::get_left(p), p); NodeTraits::set_right(n, p); } else{ // must be ( p->right == n ) NodeTraits::set_right(p, NodeTraits::get_left(n)); - if(NodeTraits::get_right(p) != node_ptr()) + if(NodeTraits::get_right(p)) NodeTraits::set_parent(NodeTraits::get_right(p), p); NodeTraits::set_left(n, p); } From caee07a64356b9c42275fc243ed81d9fa9fc4fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 19 Jan 2014 14:27:06 +0100 Subject: [PATCH 14/18] Improved floor_log2 function with intrinsics when available. Used De Brujin multiplication method otherwise. --- include/boost/intrusive/detail/utilities.hpp | 162 +++++++++++++++++-- 1 file changed, 145 insertions(+), 17 deletions(-) diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index ab7b02c..c52227c 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -364,25 +364,153 @@ template void destructor_impl(Hook &, detail::link_dispatch) {} -//This function uses binary search to discover the -//highest set bit of the integer -inline std::size_t floor_log2 (std::size_t x) -{ - const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; - const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); - BOOST_STATIC_ASSERT(Size_t_Bits_Power_2); +/////////////////////////// +// floor_log2 Dispatcher +//////////////////////////// - std::size_t n = x; - std::size_t log2 = 0; +#if defined(_MSC_VER) && (_MSC_VER >= 1400) - for(std::size_t shift = Bits >> 1; shift; shift >>= 1){ - std::size_t tmp = n >> shift; - if (tmp) - log2 += shift, n = tmp; + }}} //namespace boost::intrusive::detail + + #include + + namespace boost { + namespace intrusive { + namespace detail { + + #if defined(_M_X64) || defined(_M_AMD64) || defined(_M_IA64) //64 bit target + #define BOOST_INTRUSIVE_BSR_INTRINSIC _BitScanReverse64 + #else //32 bit target + #define BOOST_INTRUSIVE_BSR_INTRINSIC _BitScanReverse + #endif + + inline std::size_t floor_log2 (std::size_t x) + { + unsigned long log2; + BOOST_INTRUSIVE_BSR_INTRINSIC( &log2, (unsigned long)x ); + return log2; } - return log2; -} + #undef BOOST_INTRUSIVE_BSR_INTRINSIC + +#elif defined(_MSC_VER) //visual 2003 + + inline std::size_t floor_log2 (std::size_t x) + { + unsigned long log2; + __asm + { + bsr eax, x + mov log2, eax + } + return static_cast(log2); + } + +#elif defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) //GCC >=3.4 + + #if SIZE_MAX > UINT_MAX + #define BOOST_INTRUSIVE_CLZ_INTRINSIC __builtin_clzll + #elif SIZE_MAX > UINT_MAX + #define BOOST_INTRUSIVE_CLZ_INTRINSIC __builtin_clzl + #else + #define BOOST_INTRUSIVE_CLZ_INTRINSIC __builtin_clz + #endif + + inline std::size_t floor_log2(std::size_t n) + { + return sizeof(std::size_t)*CHAR_BIT - 1 - BOOST_INTRUSIVE_CLZ_INTRINSIC(n); + } + + #undef BOOST_INTRUSIVE_CLZ_INTRINSIC + +#else //Portable methods + +//////////////////////////// +// Generic method +//////////////////////////// + + inline std::size_t floor_log2_get_shift(std::size_t n, true_ )//power of two size_t + { return n >> 1; } + + inline std::size_t floor_log2_get_shift(std::size_t n, false_ )//non-power of two size_t + { return (n >> 1) + ((n & 1u) & (n != 1)); } + + template + inline std::size_t floor_log2 (std::size_t x, integer) + { + const std::size_t Bits = N; + const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); + + std::size_t n = x; + std::size_t log2 = 0; + + std::size_t remaining_bits = Bits; + std::size_t shift = floor_log2_get_shift(remaining_bits, bool_()); + while(shift){ + std::size_t tmp = n >> shift; + if (tmp){ + log2 += shift, n = tmp; + } + shift = floor_log2_get_shift(shift, bool_()); + } + + return log2; + } + + //////////////////////////// + // DeBruijn method + //////////////////////////// + + //Taken from: + //http://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers + //Thanks to Desmond Hume + + inline std::size_t floor_log2 (std::size_t v, integer) + { + static const int MultiplyDeBruijnBitPosition[32] = + { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 + }; + + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + return MultiplyDeBruijnBitPosition[(std::size_t)(v * 0x07C4ACDDU) >> 27]; + } + + inline std::size_t floor_log2 (std::size_t v, integer) + { + static const std::size_t MultiplyDeBruijnBitPosition[64] = { + 63, 0, 58, 1, 59, 47, 53, 2, + 60, 39, 48, 27, 54, 33, 42, 3, + 61, 51, 37, 40, 49, 18, 28, 20, + 55, 30, 34, 11, 43, 14, 22, 4, + 62, 57, 46, 52, 38, 26, 32, 41, + 50, 36, 17, 19, 29, 10, 13, 21, + 56, 45, 25, 31, 35, 16, 9, 12, + 44, 24, 15, 8, 23, 7, 6, 5}; + + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + return MultiplyDeBruijnBitPosition[((std::size_t)((v - (v >> 1))*0x07EDD5E59A4E28C2ULL)) >> 58]; + } + + + inline std::size_t floor_log2 (std::size_t x) + { + const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; + return floor_log2(x, integer()); + } + +#endif //Thanks to Laurent de Soras in //http://www.flipcode.com/archives/Fast_log_Function.shtml @@ -404,13 +532,13 @@ inline float fast_log2 (float val) //1+log2(m), m ranging from 1 to 2 //3rd degree polynomial keeping first derivate continuity. //For less precision the line can be commented out - val = ((-1.0f/3.f) * val + 2.f) * val - (2.0f/3.f); + val = ((-1.f/3.f) * val + 2.f) * val - (2.f/3.f); return (val + log_2); } inline std::size_t ceil_log2 (std::size_t x) { - return ((x & (x-1))!= 0) + floor_log2(x); + return static_cast((x & (x-1)) != 0) + floor_log2(x); } template From 3c6f96a96a951fe46f13c681f14436ce21c9ef9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 19 Jan 2014 14:28:57 +0100 Subject: [PATCH 15/18] Improved "count" for unique associative containers. Instead of calling tree's count just use find() != end() to avoid iterations as there is only one potential key. Fixed some typos. --- doc/intrusive.qbk | 5 +- include/boost/intrusive/avl_set.hpp | 14 +- include/boost/intrusive/avltree.hpp | 2 +- .../boost/intrusive/avltree_algorithms.hpp | 1 + include/boost/intrusive/bs_set.hpp | 12 +- include/boost/intrusive/bstree.hpp | 70 ++-- include/boost/intrusive/bstree_algorithms.hpp | 10 +- include/boost/intrusive/detail/mpl.hpp | 6 + include/boost/intrusive/rbtree.hpp | 2 +- include/boost/intrusive/rbtree_algorithms.hpp | 1 + include/boost/intrusive/set.hpp | 14 +- include/boost/intrusive/sg_set.hpp | 12 +- include/boost/intrusive/sgtree.hpp | 27 +- include/boost/intrusive/sgtree_algorithms.hpp | 31 +- include/boost/intrusive/splay_set.hpp | 111 +----- include/boost/intrusive/splaytree.hpp | 90 +---- .../boost/intrusive/splaytree_algorithms.hpp | 315 +++++++++--------- include/boost/intrusive/treap.hpp | 2 +- include/boost/intrusive/treap_algorithms.hpp | 1 + include/boost/intrusive/treap_set.hpp | 12 +- test/test_container.hpp | 2 +- 21 files changed, 324 insertions(+), 416 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index aca3694..adc047b 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3788,8 +3788,9 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std * Improved Doxygen generated reference and updated and fixed forward-declaration header. -* [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers and - removed `splay_set_base_hook` and `splay_set_member_hook`from splay containers. +* [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers, + `splay_set_base_hook` and `splay_set_member_hook`from splay containers and `bool splay = true` + extra parameter is `splaytree_algorithms` functions. * Fixed bugs: * [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]]. diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index 061a086..b70fd89 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -249,13 +249,19 @@ class avl_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -692,7 +698,7 @@ class avl_multiset_impl //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index 225efcc..e87de01 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -296,7 +296,7 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 54f9fe0..31777d7 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -274,6 +274,7 @@ class avltree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) diff --git a/include/boost/intrusive/bs_set.hpp b/include/boost/intrusive/bs_set.hpp index 2062d49..ce3c490 100644 --- a/include/boost/intrusive/bs_set.hpp +++ b/include/boost/intrusive/bs_set.hpp @@ -247,13 +247,19 @@ class bs_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) == this->tree_type::cend()); } //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) == this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index 144415d..c880731 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -431,6 +431,16 @@ struct bstbase const size_traits &sz_traits() const { return *this; } + bool empty() const + { + if(ConstantTimeSize){ + return !this->sz_traits().get_size(); + } + else{ + return algo_type::unique(this->header_ptr()); + } + } + size_type count(const_reference value) const { return size_type(this->count(value, this->comp())); } @@ -441,14 +451,16 @@ struct bstbase return size_type(std::distance(ret.first, ret.second)); } - bool empty() const + //Add non-const overloads to theoretically const members + //as some algorithms have different behavior when non-const versions are used (like splay trees). + size_type count(const_reference value) + { return size_type(this->count(value, this->comp())); } + + template + size_type count(const KeyType &key, KeyValueCompare comp) { - if(ConstantTimeSize){ - return !this->sz_traits().get_size(); - } - else{ - return algo_type::unique(this->header_ptr()); - } + std::pair ret = this->equal_range(key, comp); + return size_type(std::distance(ret.first, ret.second)); } }; @@ -1364,7 +1376,7 @@ class bstree_impl //! Complexity: Logarithmic to the number of elements contained plus lineal //! to number of objects with the given value. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. size_type count(const_reference value) const; //! Effects: Returns the number of contained elements with the given key @@ -1372,7 +1384,7 @@ class bstree_impl //! Complexity: Logarithmic to the number of elements contained plus lineal //! to number of objects with the given key. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template size_type count(const KeyType &key, KeyValueCompare comp) const; @@ -1381,7 +1393,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. iterator lower_bound(const_reference value); //! Effects: Returns an iterator to the first element whose @@ -1389,7 +1401,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. const_iterator lower_bound(const_reference value) const; //! Effects: Returns an iterator to the first element whose @@ -1397,7 +1409,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template iterator lower_bound(const KeyType &key, KeyValueCompare comp); @@ -1406,7 +1418,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; @@ -1415,7 +1427,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. iterator upper_bound(const_reference value); //! Effects: Returns an iterator to the first element whose @@ -1424,7 +1436,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template iterator upper_bound(const KeyType &key, KeyValueCompare comp); @@ -1433,7 +1445,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. const_iterator upper_bound(const_reference value) const; //! Effects: Returns an iterator to the first element whose @@ -1442,7 +1454,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; @@ -1451,7 +1463,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. iterator find(const_reference value); //! Effects: Finds an iterator to the first element whose key is @@ -1459,7 +1471,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template iterator find(const KeyType &key, KeyValueCompare comp); @@ -1468,7 +1480,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. const_iterator find(const_reference value) const; //! Effects: Finds a const_iterator to the first element whose key is @@ -1476,7 +1488,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template const_iterator find(const KeyType &key, KeyValueCompare comp) const; @@ -1486,7 +1498,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. std::pair equal_range(const_reference value); //! Effects: Finds a range containing all elements whose key is k or @@ -1495,7 +1507,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template std::pair equal_range(const KeyType &key, KeyValueCompare comp); @@ -1505,7 +1517,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `value_compare` throws. std::pair equal_range(const_reference value) const; @@ -1515,7 +1527,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: Nothing. + //! Throws: If `comp` throws. template std::pair equal_range(const KeyType &key, KeyValueCompare comp) const; @@ -1531,7 +1543,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If the predicate throws. + //! Throws: If `value_compare` throws. //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_value and upper_value. @@ -1554,7 +1566,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If "comp" throws. + //! Throws: If `comp` throws. //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_key and upper_key. @@ -1575,7 +1587,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If the predicate throws. + //! Throws: If `value_compare` throws. //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_value and upper_value. @@ -1598,7 +1610,7 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If "comp" throws. + //! Throws: If `comp` throws. //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_key and upper_key. diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index 1766e0d..b94310b 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -173,7 +173,7 @@ class bstree_algorithms static node_ptr end_node(const const_node_ptr & header) { return detail::uncast(header); } - //! Requires: 'node' is a node of the tree or an node initialized + //! Requires: 'node' is a node of the tree or a node initialized //! by init(...) or init_node. //! //! Effects: Returns true if the node is initialized by init() or init_node(). @@ -766,7 +766,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the element that is equivalent to + //! Effects: Returns a node_ptr to the first element that is equivalent to //! "key" according to "comp" or "header" if that element does not exist. //! //! Complexity: Logarithmic. @@ -863,7 +863,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns the number of elements with a key equivalent to "key"pair of node_ptr delimiting a range containing + //! Effects: Returns the number of elements with a key equivalent to "key" //! according to "comp". //! //! Complexity: Logarithmic. @@ -907,7 +907,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the first element that is + //! Effects: Returns a node_ptr to the first element that is //! not less than "key" according to "comp" or "header" if that element does //! not exist. //! @@ -926,7 +926,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the first element that is greater + //! Effects: Returns a node_ptr to the first element that is greater //! than "key" according to "comp" or "header" if that element does not exist. //! //! Complexity: Logarithmic. diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 6f99d7c..4358aec 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -29,6 +29,12 @@ struct bool_ static const bool value = C_; }; +template< class Integer, Integer Value > +struct integer +{ + static const Integer value = Value; +}; + typedef bool_ true_; typedef bool_ false_; diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 326b13f..bff85de 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -292,7 +292,7 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index e20b4d8..457df31 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -297,6 +297,7 @@ class rbtree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index 208360d..43673e3 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -249,13 +249,19 @@ class set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -692,7 +698,7 @@ class multiset_impl //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index 7e5d072..11545ab 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -247,13 +247,19 @@ class sg_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 5b42185..b28b0ae 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -48,6 +48,12 @@ namespace intrusive { namespace detail{ +///////////////////////////////////////////////////////////// +// +// Halpha for fixed floating_point option +// +///////////////////////////////////////////////////////////// + //! Returns floor(log2(n)/log2(sqrt(2))) -> floor(2*log2(n)) //! Undefined if N is 0. //! @@ -55,7 +61,7 @@ namespace detail{ inline std::size_t calculate_h_sqrt2 (std::size_t n) { std::size_t f_log2 = detail::floor_log2(n); - return (2*f_log2) + (n >= detail::sqrt2_pow_2xplus1 (f_log2)); + return (2*f_log2) + static_cast(n >= detail::sqrt2_pow_2xplus1(f_log2)); } struct h_alpha_sqrt2_t @@ -76,6 +82,12 @@ struct alpha_0_75_by_max_size_t } }; +///////////////////////////////////////////////////////////// +// +// Halpha for fixed floating_point option +// +///////////////////////////////////////////////////////////// + struct h_alpha_t { explicit h_alpha_t(float inv_minus_logalpha) @@ -84,9 +96,12 @@ struct h_alpha_t std::size_t operator()(std::size_t n) const { - //Returns floor(log2(1/alpha(n))) -> - // floor(log2(n)/log(1/alpha)) -> - // floor(log2(n)/(-log2(alpha))) + //////////////////////////////////////////////////////////// + // This function must return "floor(log2(1/alpha(n)))" -> + // floor(log2(n)/log(1/alpha)) -> + // floor(log2(n)/-log2(alpha)) + // floor(log2(n)*(1/-log2(alpha))) + //////////////////////////////////////////////////////////// //return static_cast(std::log(float(n))*inv_minus_logalpha_); return static_cast(detail::fast_log2(float(n))*inv_minus_logalpha_); } @@ -119,7 +134,7 @@ struct alpha_holder typedef boost::intrusive::detail::alpha_by_max_size_t multiply_by_alpha_t; alpha_holder() : max_tree_size_(0) - { set_alpha(0.7f); } + { set_alpha(0.70711f); } // ~1/sqrt(2) float get_alpha() const { return alpha_; } @@ -666,7 +681,7 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index 65a76b1..2e4ce28 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -187,6 +187,7 @@ class sgtree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) @@ -330,25 +331,21 @@ class sgtree_algorithms //than the weight balanced method. node_ptr s = x; std::size_t size = 1; - for(std::size_t ancestor = 1; true; ++ancestor){ - if(ancestor == depth){ //Check if whole tree must be rebuilt - max_tree_size = tree_size; - bstree_algo::rebalance_subtree(NodeTraits::get_parent(s)); - break; - } - else{ //Go to the next scapegoat candidate - const node_ptr s_parent = NodeTraits::get_parent(s); - const node_ptr s_parent_left = NodeTraits::get_left(s_parent); - //Obtain parent's size (previous size + parent + sibling tree) - const node_ptr s_sibling = s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left; - size += 1 + bstree_algo::subtree_size(s_sibling); - s = s_parent; - if(ancestor > h_alpha(size)){ //is 's' scapegoat? - bstree_algo::rebalance_subtree(s); - break; - } + for(std::size_t ancestor = 1; ancestor != depth; ++ancestor){ + const node_ptr s_parent = NodeTraits::get_parent(s); + const node_ptr s_parent_left = NodeTraits::get_left(s_parent); + //Obtain parent's size (previous size + parent + sibling tree) + const node_ptr s_sibling = s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left; + size += 1 + bstree_algo::subtree_size(s_sibling); + s = s_parent; + if(ancestor > h_alpha(size)){ //is 's' scapegoat? + bstree_algo::rebalance_subtree(s); + return; } } + //The whole tree must be rebuilt + max_tree_size = tree_size; + bstree_algo::rebalance_subtree(NodeTraits::get_parent(s)); } } /// @endcond diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 0a80ce6..97654fc 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -247,12 +247,18 @@ class splay_set_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::splaytree::count(const_reference) - size_type count(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp); + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const size_type count(const_reference value) const; @@ -261,13 +267,6 @@ class splay_set_impl template size_type count(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const - size_type count_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const - template - size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -282,13 +281,6 @@ class splay_set_impl template const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const - const_iterator lower_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) iterator upper_bound(const_reference value); @@ -303,13 +295,6 @@ class splay_set_impl template const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const - const_iterator upper_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find(const_reference) iterator find(const_reference value); @@ -324,13 +309,6 @@ class splay_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const_reference)const - const_iterator find_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference) std::pair equal_range(const_reference value); @@ -347,15 +325,6 @@ class splay_set_impl std::pair equal_range(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const_reference)const - std::pair - equal_range_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const KeyType&,KeyValueCompare)const - template - std::pair - equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); @@ -374,15 +343,6 @@ class splay_set_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const_reference,const_reference,bool,bool)const - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -760,20 +720,6 @@ class splay_multiset_impl template size_type count(const KeyType& key, KeyValueCompare comp); - //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const - size_type count(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const - size_type count_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const - template - size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -788,13 +734,6 @@ class splay_multiset_impl template const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const - const_iterator lower_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) iterator upper_bound(const_reference value); @@ -809,13 +748,6 @@ class splay_multiset_impl template const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const - const_iterator upper_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find(const_reference) iterator find(const_reference value); @@ -830,13 +762,6 @@ class splay_multiset_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const_reference)const - const_iterator find_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference) std::pair equal_range(const_reference value); @@ -853,15 +778,6 @@ class splay_multiset_impl std::pair equal_range(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const_reference)const - std::pair - equal_range_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const KeyType&,KeyValueCompare)const - template - std::pair - equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); @@ -880,15 +796,6 @@ class splay_multiset_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const_reference,const_reference,bool,bool)const - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) static iterator s_iterator_to(reference value); diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index b0e4469..d754f5a 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -266,7 +266,6 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp); //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) @@ -292,60 +291,32 @@ class splaytree_impl template void clear_and_dispose(Disposer disposer); - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "value" - size_type count(const_reference value) - { return this->count(value, this->value_comp()); } + //! Additional note: non-const function, splaying is performed. + size_type count(const_reference value); //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "key" + //! Additional note: non-const function, splaying is performed. template - size_type count(const KeyType &key, KeyValueCompare comp) - { - std::pair ret = this->equal_range(key, comp); - return std::distance(ret.first, ret.second); - } + size_type count(const KeyType &key, KeyValueCompare comp); //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: Deprecated function, use count const overload instead. - size_type count(const_reference value) const - { return tree_type::count(value); } + //! Additional note: const function, no splaying is performed + size_type count(const_reference value) const; //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use count const overload instead. + //! Additional note: const function, no splaying is performed template - size_type count(const KeyType &key, KeyValueCompare comp) const - { return tree_type::count(key, comp); } + size_type count(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: Deprecated function, use count const overload instead. - size_type count_dont_splay(const_reference value) const - { return tree_type::count(value); } - - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use count const overload instead. - template - size_type count_dont_splay(const KeyType &key, KeyValueCompare comp) const - { return tree_type::count(key, comp); } - - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "value" + //! Additional note: non-const function, splaying is performed. iterator lower_bound(const_reference value); //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const //! Additional note: const function, no splaying is performed const_iterator lower_bound(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - //! Additional note: Deprecated function, use lower_bound const overload instead. - const_iterator lower_bound_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -357,11 +328,6 @@ class splaytree_impl template const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use lower_bound const overload instead. - template - iterator lower_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -371,10 +337,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed const_iterator upper_bound(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - //! Additional note: Deprecated function, use upper_bound const overload instead. - const_iterator upper_bound_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -386,11 +348,6 @@ class splaytree_impl template const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use upper_bound const overload instead. - template - const_iterator upper_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -400,10 +357,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed const_iterator find(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - //! Additional note: Deprecated function, use find const overload instead. - const_iterator find_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -415,11 +368,6 @@ class splaytree_impl template const_iterator find(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use find const overload instead. - template - const_iterator find_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -429,10 +377,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed std::pair equal_range(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const - //! Additional note: Deprecated function, use equal_range const overload instead. - std::pair equal_range_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -444,11 +388,6 @@ class splaytree_impl template std::pair equal_range(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use equal_range const overload instead. - template - std::pair equal_range_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); @@ -467,17 +406,6 @@ class splaytree_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const - //! Additional note: Deprecated function, use bounded_range const overload instead. - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - //! Additional note: Deprecated function, use bounded_range const overload instead. - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index 3627b8c..32130e6 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -45,33 +45,70 @@ namespace intrusive { namespace detail { template -struct splaydown_rollback +struct splaydown_assemble_and_fix_header { typedef typename NodeTraits::node_ptr node_ptr; - splaydown_rollback( const node_ptr *pcur_subtree, const node_ptr & header - , const node_ptr & leftmost , const node_ptr & rightmost) - : pcur_subtree_(pcur_subtree) , header_(header) - , leftmost_(leftmost) , rightmost_(rightmost) + + splaydown_assemble_and_fix_header(const node_ptr & t, const node_ptr & header, const node_ptr &leftmost, const node_ptr &rightmost) + : t_(t) + , null_node_(header) + , l_(null_node_) + , r_(null_node_) + , leftmost_(leftmost) + , rightmost_(rightmost) {} - void release() - { pcur_subtree_ = 0; } - - ~splaydown_rollback() + ~splaydown_assemble_and_fix_header() { - 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_); + this->assemble(); + + //Now recover the original header except for the + //splayed root node. + //"t_" is the current root and "null_node_" is the header node + NodeTraits::set_parent(null_node_, t_); + NodeTraits::set_parent(t_, null_node_); + //Recover leftmost/rightmost pointers + NodeTraits::set_left (null_node_, leftmost_); + NodeTraits::set_right(null_node_, rightmost_); + } + + private: + + void assemble() + { + //procedure assemble; + // left(r), right(l) := right(t), left(t); + // left(t), right(t) := right(null), left(null); + //end assemble; + { // left(r), right(l) := right(t), left(t); + + node_ptr const old_t_left = NodeTraits::get_left(t_); + node_ptr const old_t_right = NodeTraits::get_right(t_); + NodeTraits::set_right(l_, old_t_left); + NodeTraits::set_left (r_, old_t_right); + if(old_t_left){ + NodeTraits::set_parent(old_t_left, l_); + } + if(old_t_right){ + NodeTraits::set_parent(old_t_right, r_); + } + } + { // left(t), right(t) := right(null), left(null); + node_ptr const null_right = NodeTraits::get_right(null_node_); + node_ptr const null_left = NodeTraits::get_left(null_node_); + NodeTraits::set_left (t_, null_right); + NodeTraits::set_right(t_, null_left); + if(null_right){ + NodeTraits::set_parent(null_right, t_); + } + if(null_left){ + NodeTraits::set_parent(null_left, t_); + } } } - const node_ptr *pcur_subtree_; - node_ptr header_, leftmost_, rightmost_; + + public: + node_ptr t_, null_node_, l_, r_, leftmost_, rightmost_; }; } //namespace detail { @@ -184,32 +221,28 @@ class splaytree_algorithms #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) - //! Additional notes: the previous node of z is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. - static void erase(const node_ptr & header, const node_ptr & z, bool splay = true) + //! Additional notes: the previous node of z is splayed to speed up range deletions. + static void erase(const node_ptr & header, const node_ptr & z) { //posibility 1 - if(splay && NodeTraits::get_left(z)){ + if(NodeTraits::get_left(z)){ splay_up(bstree_algo::prev_node(z), header); } /* //possibility 2 - if(splay && NodeTraits::get_left(z)){ + if(NodeTraits::get_left(z)){ node_ptr l = NodeTraits::get_left(z); splay_up(l, header); - }*//* - if(splay && NodeTraits::get_left(z)){ + }*/ + /* + if(NodeTraits::get_left(z)){ node_ptr l = bstree_algo::prev_node(z); splay_up_impl(l, z); }*/ /* //possibility 4 - if(splay){ - splay_up(z, header); - }*/ - - //if(splay) - //splay_up(z, header); + splay_up(z, header); + */ bstree_algo::erase(header, z); } @@ -225,7 +258,7 @@ class splaytree_algorithms #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. + //! Additional notes: an element with key `key` is splayed. template static std::size_t count (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) @@ -247,15 +280,14 @@ class splaytree_algorithms { return bstree_algo::count(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static node_ptr lower_bound - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); node_ptr y = bstree_algo::lower_bound(header, key, comp); - if(splay) splay_up(y, detail::uncast(header)); + //splay_up(y, detail::uncast(header)); return y; } @@ -267,15 +299,14 @@ class splaytree_algorithms { return bstree_algo::lower_bound(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static node_ptr upper_bound - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); node_ptr y = bstree_algo::upper_bound(header, key, comp); - if(splay) splay_up(y, detail::uncast(header)); + //splay_up(y, detail::uncast(header)); return y; } @@ -287,17 +318,13 @@ class splaytree_algorithms { return bstree_algo::upper_bound(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) - //! Additional notes: the found node of the lower bound is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the found node of the lower bound is splayed. template static node_ptr find - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - if(splay) splay_down(detail::uncast(header), key, comp); - node_ptr end = detail::uncast(header); - node_ptr y = bstree_algo::lower_bound(header, key, comp); - node_ptr r = (y == end || comp(key, y)) ? end : y; - return r; + splay_down(detail::uncast(header), key, comp); + return bstree_algo::find(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) @@ -308,15 +335,14 @@ class splaytree_algorithms { return bstree_algo::find(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static std::pair equal_range - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); std::pair ret = bstree_algo::equal_range(header, key, comp); - if(splay) splay_up(ret.first, detail::uncast(header)); + //splay_up(ret.first, detail::uncast(header)); return ret; } @@ -328,16 +354,16 @@ class splaytree_algorithms { return bstree_algo::equal_range(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static std::pair bounded_range (const node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp - , bool left_closed, bool right_closed, bool splay = true) + , bool left_closed, bool right_closed) { + splay_down(detail::uncast(header), lower_key, comp); std::pair ret = bstree_algo::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); - if(splay) splay_up(ret.first, detail::uncast(header)); + //splay_up(ret.first, detail::uncast(header)); return ret; } @@ -445,6 +471,20 @@ class splaytree_algorithms // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow static void splay_up(const node_ptr & node, const node_ptr & header) + { priv_splay_up(node, header); } + + // top-down splay | complexity : logarithmic | exception : strong, note A + template + static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0) + { return priv_splay_down(header, key, comp, pfound); } + + private: + + /// @cond + + // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow + template + static void priv_splay_up(const node_ptr & node, const node_ptr & header) { // If (node == header) do a splay for the right most node instead // this is to boost performance of equal_range/count on equivalent containers in the case @@ -470,20 +510,19 @@ class splaytree_algorithms rotate(p); rotate(n); } - else{ + else { // zig-zag rotate(n); - rotate(n); + if(!SimpleSplay){ + rotate(n); + } } } } - // top-down splay | complexity : logarithmic | exception : strong, note A - template - static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + template + static node_ptr priv_splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0) { - if(!NodeTraits::get_parent(header)) - return header; //Most splay tree implementations use a dummy/null node to implement. //this function. This has some problems for a generic library like Intrusive: // @@ -494,123 +533,87 @@ class splaytree_algorithms //are not changed when splaying (because the invariants of the tree don't //change) We can back up them, use the header as the null node and //reassign old values after the function has been completed. - node_ptr t = NodeTraits::get_parent(header); - //Check if tree has a single node - if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t)) - return t; - //Backup leftmost/rightmost - node_ptr leftmost (NodeTraits::get_left(header)); - node_ptr rightmost(NodeTraits::get_right(header)); - { - //Anti-exception rollback, recovers the original header node if an exception is thrown. - detail::splaydown_rollback rollback(&t, header, leftmost, rightmost); - node_ptr null_node = header; - node_ptr l = null_node; - node_ptr r = null_node; + node_ptr const old_root = NodeTraits::get_parent(header); + node_ptr const leftmost = NodeTraits::get_left(header); + node_ptr const rightmost = NodeTraits::get_right(header); + if(leftmost == rightmost){ //Empty or unique node + if(pfound){ + *pfound = old_root && !comp(key, old_root) && !comp(old_root, key); + } + return old_root ? old_root : header; + } + else{ + //Initialize "null node" (the header in our case) + NodeTraits::set_left (header, node_ptr()); + NodeTraits::set_right(header, node_ptr()); + //Class that will backup leftmost/rightmost from header, commit the assemble(), + //and will restore leftmost/rightmost to header even if "comp" throws + detail::splaydown_assemble_and_fix_header commit(old_root, header, leftmost, rightmost); + bool found = false; for( ;; ){ - if(comp(key, t)){ - node_ptr const t_left = NodeTraits::get_left(t); + if(comp(key, commit.t_)){ + node_ptr const t_left = NodeTraits::get_left(commit.t_); if(!t_left) break; if(comp(key, t_left)){ - t = bstree_algo::rotate_right(t); + commit.t_ = bstree_algo::rotate_right(commit.t_); - if( !NodeTraits::get_left(t) ) + if( !NodeTraits::get_left(commit.t_) ) break; - link_right(t, r); - } - else if(comp(t_left, key)){ - link_right(t, r); - - if( !NodeTraits::get_right(t) ) - break; - link_left(t, l); + link_right(commit.t_, commit.r_); } else{ - link_right(t, r); + link_right(commit.t_, commit.r_); + if(!SimpleSplay && comp(t_left, key)){ + if( !NodeTraits::get_right(commit.t_) ) + break; + link_left(commit.t_, commit.l_); + } } } - else if(comp(t, key)){ - node_ptr const t_right = NodeTraits::get_right(t); + else if(comp(commit.t_, key)){ + node_ptr const t_right = NodeTraits::get_right(commit.t_); if(!t_right) break; if(comp(t_right, key)){ - t = bstree_algo::rotate_left( t ); + commit.t_ = bstree_algo::rotate_left( commit.t_ ); - if( !NodeTraits::get_right(t) ) + if( !NodeTraits::get_right(commit.t_) ) break; - link_left(t, l); - } - else if(comp(key, t_right)){ - link_left(t, l); - - if( !NodeTraits::get_left(t) ) - break; - - link_right(t, r); + link_left(commit.t_, commit.l_); } else{ - link_left(t, l); + link_left(commit.t_, commit.l_); + if(!SimpleSplay && comp(key, t_right)){ + if( !NodeTraits::get_left(commit.t_) ) + break; + link_right(commit.t_, commit.r_); + } } } else{ + found = true; break; } } - assemble(t, l, r, null_node); - rollback.release(); - } - - //Now recover the original header except for the - //splayed root node. - //t is the current root - NodeTraits::set_parent(header, t); - NodeTraits::set_parent(t, header); - //Recover leftmost/rightmost pointers - NodeTraits::set_left (header, leftmost); - NodeTraits::set_right(header, rightmost); - return t; - } - - private: - - /// @cond - - // assemble the three sub-trees into new tree pointed to by t | complexity : constant | exception : nothrow - static void assemble(const node_ptr &t, const node_ptr & l, const node_ptr & r, const const_node_ptr & null_node ) - { - node_ptr const new_l_right = NodeTraits::get_left(t); - node_ptr const new_r_left = NodeTraits::get_right(t); - NodeTraits::set_right(l, new_l_right); - NodeTraits::set_left (r, new_r_left); - - if(new_l_right){ - NodeTraits::set_parent(new_l_right, l); - } - if(new_r_left){ - NodeTraits::set_parent(new_r_left, r); - } - - node_ptr const t_new_left = NodeTraits::get_right(null_node); - node_ptr const t_new_right = NodeTraits::get_left(null_node); - NodeTraits::set_left (t, t_new_left); - NodeTraits::set_right(t, t_new_right); - - if(t_new_left){ - NodeTraits::set_parent(t_new_left, t); - } - - if(t_new_right){ - NodeTraits::set_parent(t_new_right, t); + //commit.~splaydown_assemble_and_fix_header() will first + //"assemble()" + link the new root & recover header's leftmost & rightmost + if(pfound){ + *pfound = found; + } + return commit.t_; } } // break link to left child node and attach it to left tree pointed to by l | complexity : constant | exception : nothrow static void link_left(node_ptr & t, node_ptr & l) { + //procedure link_left; + // t, l, right(l) := right(t), t, t + //end link_left NodeTraits::set_right(l, t); NodeTraits::set_parent(t, l); l = t; @@ -620,6 +623,9 @@ class splaytree_algorithms // break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow static void link_right(node_ptr & t, node_ptr & r) { + //procedure link_right; + // t, r, left(r) := left(t), t, t + //end link_right; NodeTraits::set_left(r, t); NodeTraits::set_parent(t, r); r = t; @@ -629,6 +635,9 @@ class splaytree_algorithms // rotate n with its parent | complexity : constant | exception : nothrow static void rotate(const node_ptr & n) { + //procedure rotate_left; + // t, right(t), left(right(t)) := right(t), left(right(t)), t + //end rotate_left; node_ptr p = NodeTraits::get_parent(n); node_ptr g = NodeTraits::get_parent(p); //Test if g is header before breaking tree diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index eb0e501..e3ced65 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -910,7 +910,7 @@ class treap_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index 6a61b7e..e7d887a 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -248,6 +248,7 @@ class treap_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Requires: "h" must be the header node of a tree. diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 739e56b..cb59a72 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -291,13 +291,19 @@ class treap_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/test/test_container.hpp b/test/test_container.hpp index bb6444d..47ac9e6 100644 --- a/test/test_container.hpp +++ b/test/test_container.hpp @@ -219,7 +219,7 @@ void test_common_unordered_and_associative_container(Container & c, Data & d, bo c.erase(*da, c.key_comp()); BOOST_TEST( c.size() == old_size-1 ); - //This should not eras anyone + //This should not erase any size_type second_erase = c.erase_and_dispose( *da, c.key_comp(), detail::null_disposer() ); BOOST_TEST( second_erase == 0 ); From f162078264c981687394ed05a93d2e0237933fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 20 Jan 2014 12:13:53 +0100 Subject: [PATCH 16/18] Implemented equal_range for unique associative containers using lower_bound_range. This might be a bit slower when comparison function is very lightweight, but shines when it's heavy as it just needs to perform a single additional comparison and a possible successor iteration. --- include/boost/intrusive/avl_set.hpp | 24 +++++++---- include/boost/intrusive/bs_set.hpp | 24 +++++++---- include/boost/intrusive/bstree.hpp | 37 ++++++++++++++++ include/boost/intrusive/bstree_algorithms.hpp | 43 +++++++++++++++---- include/boost/intrusive/set.hpp | 16 +++++-- include/boost/intrusive/sg_set.hpp | 24 +++++++---- include/boost/intrusive/splay_set.hpp | 24 +++++++---- .../boost/intrusive/splaytree_algorithms.hpp | 19 ++++++++ include/boost/intrusive/treap_set.hpp | 24 +++++++---- 9 files changed, 182 insertions(+), 53 deletions(-) diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index b70fd89..ce2d178 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -304,21 +304,29 @@ class avl_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range diff --git a/include/boost/intrusive/bs_set.hpp b/include/boost/intrusive/bs_set.hpp index ce3c490..9768382 100644 --- a/include/boost/intrusive/bs_set.hpp +++ b/include/boost/intrusive/bs_set.hpp @@ -302,21 +302,29 @@ class bs_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index c880731..19b50de 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -238,6 +238,7 @@ struct bstbase2 key_compare key_comp() const { return this->comp(); } + //lower_bound iterator lower_bound(const_reference value) { return this->lower_bound(value, this->comp()); } @@ -262,6 +263,7 @@ struct bstbase2 (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); } + //upper_bound iterator upper_bound(const_reference value) { return this->upper_bound(value, this->comp()); } @@ -286,6 +288,7 @@ struct bstbase2 (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); } + //find iterator find(const_reference value) { return this->find(value, this->comp()); } @@ -310,6 +313,7 @@ struct bstbase2 (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); } + //equal_range std::pair equal_range(const_reference value) { return this->equal_range(value, this->comp()); } @@ -340,6 +344,38 @@ struct bstbase2 , const_iterator(ret.second, this->real_value_traits_ptr())); } + //lower_bound_range + std::pair lower_bound_range(const_reference value) + { return this->lower_bound_range(value, this->comp()); } + + template + std::pair lower_bound_range(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + std::pair ret + (node_algorithms::lower_bound_range(this->header_ptr(), key, key_node_comp)); + return std::pair( iterator(ret.first, this->real_value_traits_ptr()) + , iterator(ret.second, this->real_value_traits_ptr())); + } + + std::pair + lower_bound_range(const_reference value) const + { return this->lower_bound_range(value, this->comp()); } + + template + std::pair + lower_bound_range(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + std::pair ret + (node_algorithms::lower_bound_range(this->header_ptr(), key, key_node_comp)); + return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) + , const_iterator(ret.second, this->real_value_traits_ptr())); + } + + //bounded_range std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) { return this->bounded_range(lower_value, upper_value, this->comp(), left_closed, right_closed); } @@ -374,6 +410,7 @@ struct bstbase2 , const_iterator(ret.second, this->real_value_traits_ptr())); } + //insert_unique_check template std::pair insert_unique_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index b94310b..d7f785f 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -487,18 +487,18 @@ class bstree_algorithms //! Throws: Nothing. static node_ptr next_node(const node_ptr & node) { - node_ptr p_right(NodeTraits::get_right(node)); - if(p_right){ - return minimum(p_right); + node_ptr const n_right(NodeTraits::get_right(node)); + if(n_right){ + return minimum(n_right); } else { - node_ptr p(node); - node_ptr x = NodeTraits::get_parent(p); - while(p == NodeTraits::get_right(x)){ - p = x; - x = NodeTraits::get_parent(x); + node_ptr n(node); + node_ptr p(NodeTraits::get_parent(n)); + while(n == NodeTraits::get_right(p)){ + n = p; + p = NodeTraits::get_parent(p); } - return NodeTraits::get_right(p) != x ? x : detail::uncast(p); + return NodeTraits::get_right(n) != p ? p : n; } } @@ -902,6 +902,31 @@ class bstree_algorithms return bounded_range(header, key, key, comp, true, true); } + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an a pair of node_ptr delimiting a range containing + //! the first element that is equivalent to "key" according to "comp" or an + //! empty range that indicates the position where that element would be + //! if there are no equivalent elements. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static std::pair lower_bound_range + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { + node_ptr const lb(lower_bound(header, key, comp)); + std::pair ret_ii(lb, lb); + if(lb != header && !comp(key, lb)){ + ret_ii.second = next_node(ret_ii.second); + } + return ret_ii; + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index 43673e3..b2e4290 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -304,21 +304,29 @@ class set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value); + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index 11545ab..1997696 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -302,21 +302,29 @@ class sg_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 97654fc..f47799c 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -309,21 +309,29 @@ class splay_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index 32130e6..313d6af 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -353,6 +353,25 @@ class splaytree_algorithms (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { return bstree_algo::equal_range(header, key, comp); } + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) + //! Additional notes: the first node of the range is splayed. + template + static std::pair lower_bound_range + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { + splay_down(detail::uncast(header), key, comp); + std::pair ret = bstree_algo::lower_bound_range(header, key, comp); + //splay_up(ret.first, detail::uncast(header)); + return ret; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) + //! Additional note: no splaying is performed + template + static std::pair lower_bound_range + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { return bstree_algo::lower_bound_range(header, key, comp); } + //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) //! Additional notes: the first node of the range is splayed. template diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index cb59a72..6812e1a 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -346,21 +346,29 @@ class treap_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::treap::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::treap::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range From 2ffe6b2f8298d485b60b6d8eb4feb8111d6ff488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 30 Jan 2014 14:22:04 +0100 Subject: [PATCH 17/18] Fixed ABI regression introduced in Boost 1.55 --- doc/intrusive.qbk | 2 + example/doc_external_value_traits.cpp | 129 ---- include/boost/intrusive/avltree.hpp | 3 +- include/boost/intrusive/bstree.hpp | 460 +++++++------- include/boost/intrusive/bstree_algorithms.hpp | 13 + .../boost/intrusive/detail/hashtable_node.hpp | 32 +- include/boost/intrusive/detail/utilities.hpp | 6 +- include/boost/intrusive/hashtable.hpp | 584 +++++++++--------- include/boost/intrusive/list.hpp | 121 ++-- include/boost/intrusive/options.hpp | 21 - include/boost/intrusive/priority_compare.hpp | 6 +- include/boost/intrusive/rbtree.hpp | 3 +- include/boost/intrusive/sgtree.hpp | 52 +- include/boost/intrusive/slist.hpp | 121 ++-- include/boost/intrusive/splaytree.hpp | 10 +- include/boost/intrusive/treap.hpp | 92 ++- include/boost/intrusive/treap_set.hpp | 1 + include/boost/intrusive/unordered_set.hpp | 12 +- proj/vc7ide/Intrusive.sln | 16 +- .../vc7ide/_intrusivelib/_intrusivelib.vcproj | 3 - .../container_size_test.vcproj} | 21 +- test/container_size_test.cpp | 187 ++++++ test/external_value_traits_test.cpp | 241 -------- 23 files changed, 971 insertions(+), 1165 deletions(-) delete mode 100644 example/doc_external_value_traits.cpp rename proj/vc7ide/{external_value_traits/external_value_traits.vcproj => container_size_test/container_size_test.vcproj} (82%) create mode 100644 test/container_size_test.cpp delete mode 100644 test/external_value_traits_test.cpp diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index adc047b..f1dba96 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3788,6 +3788,8 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std * Improved Doxygen generated reference and updated and fixed forward-declaration header. +* [*ABI breaking]: Fixed ABI regression introduced in Boost 1.55 version, mainly noticeable on MSVC compilers. + * [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers, `splay_set_base_hook` and `splay_set_member_hook`from splay containers and `bool splay = true` extra parameter is `splaytree_algorithms` functions. diff --git a/example/doc_external_value_traits.cpp b/example/doc_external_value_traits.cpp deleted file mode 100644 index c8ec1ce..0000000 --- a/example/doc_external_value_traits.cpp +++ /dev/null @@ -1,129 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-2013 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/intrusive for documentation. -// -///////////////////////////////////////////////////////////////////////////// -//[doc_external_value_traits -#include -#include - -using namespace boost::intrusive; - -//This type is not modifiable so we can't store hooks or custom nodes -typedef int identifier_t; - -//This value traits will associate elements from an array of identifiers with -//elements of an array of nodes. The element i of the value array will use the -//node i of the node array: -class external_traits -{ - //Non-copyable - external_traits(const external_traits &); - external_traits& operator=(const external_traits &); - - public: - typedef list_node_traits node_traits; - typedef node_traits::node node; - typedef node * node_ptr; - typedef const node * const_node_ptr; - typedef identifier_t value_type; - typedef identifier_t * pointer; - typedef const identifier_t * const_pointer; - static const link_mode_type link_mode = normal_link; - - external_traits(pointer ids, std::size_t NumElements) - : ids_(ids), nodes_(NumElements) - {} - - ///Note: non static functions! - node_ptr to_node_ptr (value_type &value) - { return &this->nodes_[0] + (&value - this->ids_); } - const_node_ptr to_node_ptr (const value_type &value) const - { return &this->nodes_[0] + (&value - this->ids_); } - pointer to_value_ptr(node_ptr n) - { return this->ids_ + (n - &this->nodes_[0]); } - const_pointer to_value_ptr(const_node_ptr n) const - { return this->ids_ + (n - &this->nodes_[0]); } - - private: - pointer ids_; - //This is an array of nodes that is necessary to form the linked list - std::vector::node> nodes_; -}; - -//This is the value traits class that will be stored in the container -//and that will lead to the external traits using the address -//of the container. -struct internal_traits -{ - static const bool external_value_traits = true; - typedef external_traits value_traits; - - template - value_traits &get_value_traits(Container &cont); - - template - const value_traits &get_value_traits(const Container &cont) const; -}; - -//The intrusive list that will use external value traits -typedef list > List; - -class data_holder - : public List -{ - public: - data_holder(identifier_t *ids, std::size_t NumElements) - : List() - , external_traits_(ids, NumElements) - {} - external_traits external_traits_; -}; - -template -internal_traits::value_traits &internal_traits::get_value_traits(Container &cont) -{ return static_cast(cont).external_traits_; } - -template -const internal_traits::value_traits &internal_traits::get_value_traits(const Container &cont) const -{ return static_cast(cont).external_traits_; } - -int main() -{ - const int NumElements = 100; - - //This is an array of ids that we want to "store" - identifier_t ids [NumElements]; - - //Initialize id objects, each one with a different number - for(int i = 0; i != NumElements; ++i) ids[i] = i; - - //The data holding the list and the external traits - data_holder data(ids, NumElements); - - //This list will store ids without modifying identifier_t instances - //Stateful value traits must be explicitly passed in the constructor. - List &my_list = data; - - //Insert ids in reverse order in the list - for(identifier_t * it(&ids[0]), *itend(&ids[NumElements]); it != itend; ++it) - my_list.push_front(*it); - - //Now test lists - List::const_iterator list_it (my_list.cbegin()); - identifier_t *it_val(&ids[NumElements]-1), *it_rbeg_val(&ids[0] -1); - - //Test the objects inserted in the base hook list - for(; it_val != it_rbeg_val; --it_val, ++list_it){ - if(&*list_it != &*it_val) return 1; - } - - return 0; -} -//] diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index e87de01..7a53b39 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -487,14 +487,13 @@ class avltree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit avltree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index 19b50de..c0cf6b3 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -34,6 +34,7 @@ #include #include #include +#include #include namespace boost { @@ -53,91 +54,93 @@ struct bstree_defaults template struct bstbase3 - : public detail::get_real_value_traits::type::node_traits::node - , public ValueTraits { typedef ValueTraits value_traits; - typedef typename detail::get_real_value_traits::type real_value_traits; - typedef typename real_value_traits::node_traits node_traits; + typedef typename value_traits::node_traits node_traits; typedef typename node_traits::node node_type; typedef typename get_algo::type node_algorithms; typedef typename node_traits::node_ptr node_ptr; typedef typename node_traits::const_node_ptr const_node_ptr; - bstbase3(const ValueTraits &vtraits) - : ValueTraits(vtraits) - {} + struct holder_t : public ValueTraits + { + explicit holder_t(const ValueTraits &vtraits) + : ValueTraits(vtraits) + {} + node_type root; + } holder; - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; + static bstbase3 &get_tree_base_from_root(node_type &root) + { + holder_t *holder = get_parent_from_member(&root, &holder_t::root); + bstbase3 *base = get_parent_from_member (holder, &bstbase3::holder); + return *base; + } + + bstbase3(const ValueTraits &vtraits) + : holder(vtraits) + { + node_algorithms::init_header(this->header_ptr()); + } node_ptr header_ptr() - { return pointer_traits::pointer_to(static_cast(*this)); } + { return pointer_traits::pointer_to(this->holder.root); } const_node_ptr header_ptr() const - { return pointer_traits::pointer_to(static_cast(*this)); } + { return pointer_traits::pointer_to(this->holder.root); } - const value_traits &val_traits() const - { return *this; } + const value_traits &get_value_traits() const + { return this->holder; } - value_traits &val_traits() - { return *this; } + value_traits &get_value_traits() + { return this->holder; } - const real_value_traits &get_real_value_traits(detail::bool_) const - { return *this; } + typedef typename pointer_traits::template + rebind_pointer::type const_value_traits_ptr; - const real_value_traits &get_real_value_traits(detail::bool_) const - { return this->val_traits().get_value_traits(*this); } + const_value_traits_ptr value_traits_ptr() const + { return pointer_traits::pointer_to(this->get_value_traits()); } - real_value_traits &get_real_value_traits(detail::bool_) - { return *this; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return this->val_traits().get_value_traits(*this); } - - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } - - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - - typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; - - const_real_value_traits_ptr real_value_traits_ptr() const - { return pointer_traits::pointer_to(this->get_real_value_traits()); } - - - typedef tree_iterator iterator; - typedef tree_iterator const_iterator; + typedef tree_iterator iterator; + typedef tree_iterator const_iterator; typedef boost::intrusive::detail::reverse_iterator reverse_iterator; typedef boost::intrusive::detail::reverse_iterator const_reverse_iterator; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) const_reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::difference_type) difference_type; - static const bool safemode_or_autounlink = is_safe_autounlink::value; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; iterator begin() - { return iterator (node_traits::get_left(this->header_ptr()), this->real_value_traits_ptr()); } + { return iterator(node_algorithms::begin_node(this->header_ptr()), this->value_traits_ptr()); } const_iterator begin() const { return cbegin(); } const_iterator cbegin() const - { return const_iterator (node_traits::get_left(this->header_ptr()), this->real_value_traits_ptr()); } + { return const_iterator(node_algorithms::begin_node(this->header_ptr()), this->value_traits_ptr()); } iterator end() - { return iterator (this->header_ptr(), this->real_value_traits_ptr()); } + { return iterator(node_algorithms::end_node(this->header_ptr()), this->value_traits_ptr()); } const_iterator end() const { return cend(); } const_iterator cend() const - { return const_iterator (detail::uncast(this->header_ptr()), this->real_value_traits_ptr()); } + { return const_iterator(node_algorithms::end_node(this->header_ptr()), this->value_traits_ptr()); } + + iterator root() + { return iterator(node_algorithms::root_node(this->header_ptr()), this->value_traits_ptr()); } + + const_iterator root() const + { return croot(); } + + const_iterator croot() const + { return const_iterator(node_algorithms::root_node(this->header_ptr()), this->value_traits_ptr()); } reverse_iterator rbegin() { return reverse_iterator(end()); } @@ -159,9 +162,9 @@ struct bstbase3 void replace_node(iterator replace_this, reference with_this) { - node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) + node_algorithms::replace_node( get_value_traits().to_node_ptr(*replace_this) , this->header_ptr() - , get_real_value_traits().to_node_ptr(with_this)); + , get_value_traits().to_node_ptr(with_this)); if(safemode_or_autounlink) node_algorithms::init(replace_this.pointed_node()); } @@ -170,25 +173,25 @@ struct bstbase3 { node_algorithms::rebalance(this->header_ptr()); } iterator rebalance_subtree(iterator root) - { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this->real_value_traits_ptr()); } + { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this->value_traits_ptr()); } static iterator s_iterator_to(reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - return iterator (value_traits::to_node_ptr(value), const_real_value_traits_ptr()); + return iterator (value_traits::to_node_ptr(value), const_value_traits_ptr()); } static const_iterator s_iterator_to(const_reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_value_traits_ptr()); } iterator iterator_to(reference value) - { return iterator (value_traits::to_node_ptr(value), this->real_value_traits_ptr()); } + { return iterator (value_traits::to_node_ptr(value), this->value_traits_ptr()); } const_iterator iterator_to(const_reference value) const - { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->real_value_traits_ptr()); } + { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->value_traits_ptr()); } static void init_node(reference value) { node_algorithms::init(value_traits::to_node_ptr(value)); } @@ -197,16 +200,17 @@ struct bstbase3 template struct bstbase2 - : public bstbase3 - , public detail::ebo_functor_holder::type::value_type + //Put the (possibly empty) functor in the first position to get EBO in MSVC + : public detail::ebo_functor_holder::type> + , public bstbase3 { typedef bstbase3 treeheader_t; - typedef typename treeheader_t::real_value_traits real_value_traits; + typedef typename treeheader_t::value_traits value_traits; typedef typename treeheader_t::node_algorithms node_algorithms; typedef typename get_less - < VoidOrKeyComp, typename real_value_traits::value_type>::type value_compare; + < VoidOrKeyComp, typename value_traits::value_type>::type value_compare; typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; typedef typename treeheader_t::iterator iterator; typedef typename treeheader_t::const_iterator const_iterator; @@ -214,7 +218,7 @@ struct bstbase2 typedef typename treeheader_t::const_node_ptr const_node_ptr; bstbase2(const value_compare &comp, const ValueTraits &vtraits) - : treeheader_t(vtraits), detail::ebo_functor_holder(comp) + : detail::ebo_functor_holder(comp), treeheader_t(vtraits) {} const value_compare &comp() const @@ -223,8 +227,8 @@ struct bstbase2 value_compare &comp() { return this->get(); } - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; @@ -248,19 +252,19 @@ struct bstbase2 template iterator lower_bound(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return iterator(node_algorithms::lower_bound - (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } template const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return const_iterator(node_algorithms::lower_bound - (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } //upper_bound @@ -270,10 +274,10 @@ struct bstbase2 template iterator upper_bound(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return iterator(node_algorithms::upper_bound - (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } const_iterator upper_bound(const_reference value) const @@ -282,10 +286,10 @@ struct bstbase2 template const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return const_iterator(node_algorithms::upper_bound - (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } //find @@ -295,10 +299,10 @@ struct bstbase2 template iterator find(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return iterator - (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } const_iterator find(const_reference value) const @@ -307,10 +311,10 @@ struct bstbase2 template const_iterator find(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return const_iterator - (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } //equal_range @@ -320,12 +324,12 @@ struct bstbase2 template std::pair equal_range(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::equal_range(this->header_ptr(), key, key_node_comp)); - return std::pair( iterator(ret.first, this->real_value_traits_ptr()) - , iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( iterator(ret.first, this->value_traits_ptr()) + , iterator(ret.second, this->value_traits_ptr())); } std::pair @@ -336,12 +340,12 @@ struct bstbase2 std::pair equal_range(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::equal_range(this->header_ptr(), key, key_node_comp)); - return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) - , const_iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( const_iterator(ret.first, this->value_traits_ptr()) + , const_iterator(ret.second, this->value_traits_ptr())); } //lower_bound_range @@ -351,12 +355,12 @@ struct bstbase2 template std::pair lower_bound_range(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::lower_bound_range(this->header_ptr(), key, key_node_comp)); - return std::pair( iterator(ret.first, this->real_value_traits_ptr()) - , iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( iterator(ret.first, this->value_traits_ptr()) + , iterator(ret.second, this->value_traits_ptr())); } std::pair @@ -367,12 +371,12 @@ struct bstbase2 std::pair lower_bound_range(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::lower_bound_range(this->header_ptr(), key, key_node_comp)); - return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) - , const_iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( const_iterator(ret.first, this->value_traits_ptr()) + , const_iterator(ret.second, this->value_traits_ptr())); } //bounded_range @@ -384,13 +388,13 @@ struct bstbase2 std::pair bounded_range (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::bounded_range (this->header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair( iterator(ret.first, this->real_value_traits_ptr()) - , iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( iterator(ret.first, this->value_traits_ptr()) + , iterator(ret.second, this->value_traits_ptr())); } std::pair bounded_range @@ -401,13 +405,13 @@ struct bstbase2 std::pair bounded_range (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::bounded_range (this->header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) - , const_iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( const_iterator(ret.first, this->value_traits_ptr()) + , const_iterator(ret.second, this->value_traits_ptr())); } //insert_unique_check @@ -415,12 +419,12 @@ struct bstbase2 std::pair insert_unique_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + ocomp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->header_ptr(), key, ocomp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } template @@ -428,76 +432,102 @@ struct bstbase2 (const_iterator hint, const KeyType &key ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + ocomp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->header_ptr(), hint.pointed_node(), key, ocomp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } }; +//Due to MSVC's EBO implementation, to save space and maintain the ABI, we must put the non-empty size member +//in the first position, but if size is not going to be stored then we'll use an specialization +//that doesn't inherit from size_holder template -struct bstbase +struct bstbase_hack : public detail::size_holder , public bstbase2 < ValueTraits, VoidOrKeyComp, AlgoType> { - typedef typename detail::get_real_value_traits::type real_value_traits; typedef bstbase2< ValueTraits, VoidOrKeyComp, AlgoType> base_type; typedef typename base_type::value_compare value_compare; - typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; + typedef SizeType size_type; + typedef typename base_type::node_traits node_traits; + typedef typename get_algo + ::type algo_type; + + bstbase_hack(const value_compare & comp, const ValueTraits &vtraits) + : base_type(comp, vtraits) + { + this->sz_traits().set_size(size_type(0)); + } + + typedef detail::size_holder size_traits; + + size_traits &sz_traits() + { return static_cast(*this); } + + const size_traits &sz_traits() const + { return static_cast(*this); } +}; + +//Specialization for ConstantTimeSize == false +template +struct bstbase_hack + : public bstbase2 < ValueTraits, VoidOrKeyComp, AlgoType> +{ + typedef bstbase2< ValueTraits, VoidOrKeyComp, AlgoType> base_type; + typedef typename base_type::value_compare value_compare; + bstbase_hack(const value_compare & comp, const ValueTraits &vtraits) + : base_type(comp, vtraits) + {} + + typedef detail::size_holder size_traits; + + size_traits &sz_traits() + { return s_size_traits; } + + const size_traits &sz_traits() const + { return s_size_traits; } + + static size_traits s_size_traits; +}; + +template +detail::size_holder bstbase_hack::s_size_traits; + +//This class will +template +struct bstbase + : public bstbase_hack< ValueTraits, VoidOrKeyComp, ConstantTimeSize, SizeType, AlgoType> +{ + typedef bstbase_hack< ValueTraits, VoidOrKeyComp, ConstantTimeSize, SizeType, AlgoType> base_type; + typedef ValueTraits value_traits; + typedef typename base_type::value_compare value_compare; + typedef value_compare key_compare; typedef typename base_type::const_reference const_reference; typedef typename base_type::reference reference; typedef typename base_type::iterator iterator; typedef typename base_type::const_iterator const_iterator; typedef typename base_type::node_traits node_traits; typedef typename get_algo - ::type algo_type; + ::type node_algorithms; typedef SizeType size_type; bstbase(const value_compare & comp, const ValueTraits &vtraits) : base_type(comp, vtraits) {} - public: - typedef detail::size_holder size_traits; - - size_traits &sz_traits() - { return *this; } - - const size_traits &sz_traits() const - { return *this; } - - bool empty() const + //Detach all inserted nodes. This will add exception safety to bstree_impl + //constructors inserting elements. + ~bstbase() { - if(ConstantTimeSize){ - return !this->sz_traits().get_size(); + if(is_safe_autounlink::value){ + node_algorithms::clear_and_dispose + ( this->header_ptr() + , detail::node_disposer + (detail::null_disposer(), &this->get_value_traits())); } - else{ - return algo_type::unique(this->header_ptr()); - } - } - - size_type count(const_reference value) const - { return size_type(this->count(value, this->comp())); } - - template - size_type count(const KeyType &key, KeyValueCompare comp) const - { - std::pair ret = this->equal_range(key, comp); - return size_type(std::distance(ret.first, ret.second)); - } - - //Add non-const overloads to theoretically const members - //as some algorithms have different behavior when non-const versions are used (like splay trees). - size_type count(const_reference value) - { return size_type(this->count(value, this->comp())); } - - template - size_type count(const KeyType &key, KeyValueCompare comp) - { - std::pair ret = this->equal_range(key, comp); - return size_type(std::distance(ret.first, ret.second)); } }; @@ -526,25 +556,18 @@ template - , private detail::clear_on_destructor_base - < bstree_impl - , is_safe_autounlink::type::link_mode>::value - > { template friend class detail::clear_on_destructor_base; public: - typedef ValueTraits value_traits; /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::get_real_value_traits::type real_value_traits; - typedef bstbase data_type; - typedef tree_iterator iterator_type; - typedef tree_iterator const_iterator_type; + typedef bstbase data_type; + typedef tree_iterator iterator_type; + typedef tree_iterator const_iterator_type; /// @endcond - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(ValueTraits) value_traits; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; @@ -557,7 +580,7 @@ class bstree_impl typedef BOOST_INTRUSIVE_IMPDEF(const_iterator_type) const_iterator; typedef BOOST_INTRUSIVE_IMPDEF(boost::intrusive::detail::reverse_iterator) reverse_iterator; typedef BOOST_INTRUSIVE_IMPDEF(boost::intrusive::detail::reverse_iterator) const_reverse_iterator; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::node_traits) node_traits; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::node_traits) node_traits; typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::node) node; typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::node_ptr) node_ptr; typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::const_node_ptr) const_node_ptr; @@ -567,17 +590,17 @@ class bstree_impl typedef BOOST_INTRUSIVE_IMPDEF(algo_type) node_algorithms; static const bool constant_time_size = ConstantTimeSize; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(bstree_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink))); protected: @@ -599,10 +622,7 @@ class bstree_impl explicit bstree_impl( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) : data_type(cmp, v_traits) - { - node_algorithms::init_header(this->header_ptr()); - this->sz_traits().set_size(size_type(0)); - } + {} //! Requires: Dereferencing iterator must yield an lvalue of type value_type. //! cmp must be a comparison function that induces a strict weak ordering. @@ -622,8 +642,6 @@ class bstree_impl , const value_traits &v_traits = value_traits()) : data_type(cmp, v_traits) { - node_algorithms::init_header(this->header_ptr()); - this->sz_traits().set_size(size_type(0)); if(unique) this->insert_unique(b, e); else @@ -633,10 +651,8 @@ class bstree_impl //! Effects: to-do //! bstree_impl(BOOST_RV_REF(bstree_impl) x) - : data_type(::boost::move(x.comp()), ::boost::move(x.val_traits())) + : data_type(::boost::move(x.comp()), ::boost::move(x.get_value_traits())) { - node_algorithms::init_header(this->header_ptr()); - this->sz_traits().set_size(size_type(0)); this->swap(x); } @@ -758,8 +774,8 @@ class bstree_impl //! Complexity: Constant. static bstree_impl &container_from_end_iterator(iterator end_iterator) { - return *static_cast - (boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node())); + return static_cast + (data_type::get_tree_base_from_root(*boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()))); } //! Precondition: end_iterator must be a valid end const_iterator @@ -772,8 +788,8 @@ class bstree_impl //! Complexity: Constant. static const bstree_impl &container_from_end_iterator(const_iterator end_iterator) { - return *static_cast - (boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node())); + return static_cast + (data_type::get_tree_base_from_root(*boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()))); } //! Precondition: it must be a valid iterator @@ -814,14 +830,22 @@ class bstree_impl //! Throws: If value_compare copy-constructor throws. value_compare value_comp() const; + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: Returns true if the container is empty. //! //! Complexity: Constant. //! //! Throws: Nothing. - bool empty() const; - - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + bool empty() const + { + if(ConstantTimeSize){ + return !this->data_type::sz_traits().get_size(); + } + else{ + return algo_type::unique(this->header_ptr()); + } + } //! Effects: Returns the number of elements stored in the container. //! @@ -881,8 +905,8 @@ class bstree_impl node_algorithms::clone (const_node_ptr(src.header_ptr()) ,node_ptr(this->header_ptr()) - ,detail::node_cloner (cloner, &this->get_real_value_traits()) - ,detail::node_disposer(disposer, &this->get_real_value_traits())); + ,detail::node_cloner (cloner, &this->get_value_traits()) + ,detail::node_disposer(disposer, &this->get_value_traits())); this->sz_traits().set_size(src.sz_traits().get_size()); this->comp() = src.comp(); rollback.release(); @@ -902,13 +926,13 @@ class bstree_impl //! No copy-constructors are called. iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->comp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->comp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal_upper_bound - (this->header_ptr(), to_insert, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), to_insert, key_node_comp), this->value_traits_ptr()); this->sz_traits().increment(); return ret; } @@ -929,13 +953,13 @@ class bstree_impl //! No copy-constructors are called. iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->comp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->comp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal - (this->header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this->value_traits_ptr()); this->sz_traits().increment(); return ret; } @@ -1127,13 +1151,13 @@ class bstree_impl //! erased between the "insert_check" and "insert_commit" calls. iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); node_algorithms::insert_unique_commit (this->header_ptr(), to_insert, commit_data); this->sz_traits().increment(); - return iterator(to_insert, this->real_value_traits_ptr()); + return iterator(to_insert, this->value_traits_ptr()); } //! Requires: value must be an lvalue, "pos" must be @@ -1152,12 +1176,12 @@ class bstree_impl //! by advanced users. iterator insert_before(const_iterator pos, reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); this->sz_traits().increment(); return iterator(node_algorithms::insert_before - (this->header_ptr(), pos.pointed_node(), to_insert), this->real_value_traits_ptr()); + (this->header_ptr(), pos.pointed_node(), to_insert), this->value_traits_ptr()); } //! Requires: value must be an lvalue, and it must be no less @@ -1176,7 +1200,7 @@ class bstree_impl //! by advanced users. void push_back(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); this->sz_traits().increment(); @@ -1199,7 +1223,7 @@ class bstree_impl //! by advanced users. void push_front(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); this->sz_traits().increment(); @@ -1293,7 +1317,7 @@ class bstree_impl { node_ptr to_erase(i.pointed_node()); iterator ret(this->erase(i)); - disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->get_value_traits().to_value_ptr(to_erase)); return ret; } @@ -1401,20 +1425,19 @@ class bstree_impl void clear_and_dispose(Disposer disposer) { node_algorithms::clear_and_dispose(this->header_ptr() - , detail::node_disposer(disposer, &this->get_real_value_traits())); + , detail::node_disposer(disposer, &this->get_value_traits())); node_algorithms::init_header(this->header_ptr()); this->sz_traits().set_size(0); } - #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - //! Effects: Returns the number of contained elements with the given value //! //! Complexity: Logarithmic to the number of elements contained plus lineal //! to number of objects with the given value. //! //! Throws: If `value_compare` throws. - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return size_type(this->count(value, this->comp())); } //! Effects: Returns the number of contained elements with the given key //! @@ -1423,7 +1446,27 @@ class bstree_impl //! //! Throws: If `comp` throws. template - size_type count(const KeyType &key, KeyValueCompare comp) const; + size_type count(const KeyType &key, KeyValueCompare comp) const + { + std::pair ret = this->equal_range(key, comp); + return size_type(std::distance(ret.first, ret.second)); + } + + #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + + //Add non-const overloads to theoretically const members + //as some algorithms have different behavior when non-const versions are used (like splay trees). + size_type count(const_reference value) + { return size_type(this->count(value, this->comp())); } + + template + size_type count(const KeyType &key, KeyValueCompare comp) + { + std::pair ret = this->equal_range(key, comp); + return size_type(std::distance(ret.first, ret.second)); + } + + #else //defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Returns an iterator to the first element whose //! key is not less than k or end() if that element does not exist. @@ -1741,7 +1784,7 @@ class bstree_impl this->sz_traits().decrement(); if(safemode_or_autounlink)//If this is commented does not work with normal_link node_algorithms::init(to_be_disposed); - return this->get_real_value_traits().to_value_ptr(to_be_disposed); + return this->get_value_traits().to_value_ptr(to_be_disposed); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) @@ -2016,12 +2059,11 @@ class bstree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); bstree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index d7f785f..e7f034b 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -173,6 +173,19 @@ class bstree_algorithms static node_ptr end_node(const const_node_ptr & header) { return detail::uncast(header); } + //! Requires: 'header' is the header node of a tree. + //! + //! Effects: Returns the root of the tree if any, header otherwise + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + static node_ptr root_node(const const_node_ptr & header) + { + node_ptr p = node_traits::get_parent(header); + return p ? p : detail::uncast(header); + } + //! Requires: 'node' is a node of the tree or a node initialized //! by init(...) or init_node. //! diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index d9a3c41..1972634 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -175,27 +175,27 @@ template class hashtable_iterator : public std::iterator < std::forward_iterator_tag - , typename BucketValueTraits::real_value_traits::value_type - , typename pointer_traits::difference_type + , typename BucketValueTraits::value_traits::value_type + , typename pointer_traits::difference_type , typename detail::add_const_if_c - ::type * + ::type * , typename detail::add_const_if_c - ::type & + ::type & > { - typedef typename BucketValueTraits::real_value_traits real_value_traits; - typedef typename BucketValueTraits::real_bucket_traits real_bucket_traits; - typedef typename real_value_traits::node_traits node_traits; + typedef typename BucketValueTraits::value_traits value_traits; + typedef typename BucketValueTraits::bucket_traits bucket_traits; + typedef typename value_traits::node_traits node_traits; typedef typename detail::get_slist_impl ::type + ::type >::type slist_impl; typedef typename slist_impl::iterator siterator; typedef typename slist_impl::const_iterator const_siterator; typedef detail::bucket_impl bucket_type; typedef typename pointer_traits - ::template rebind_pointer + ::template rebind_pointer < const BucketValueTraits >::type const_bucketvaltraits_ptr; typedef typename slist_impl::size_type size_type; @@ -207,7 +207,7 @@ class hashtable_iterator } public: - typedef typename real_value_traits::value_type value_type; + typedef typename value_traits::value_type value_type; typedef typename detail::add_const_if_c::type *pointer; typedef typename detail::add_const_if_c::type &reference; @@ -250,23 +250,23 @@ class hashtable_iterator pointer operator->() const { - return boost::intrusive::detail::to_raw_pointer(this->priv_real_value_traits().to_value_ptr + return boost::intrusive::detail::to_raw_pointer(this->priv_value_traits().to_value_ptr (downcast_bucket(slist_it_.pointed_node()))); } const const_bucketvaltraits_ptr &get_bucket_value_traits() const { return traitsptr_; } - const real_value_traits &priv_real_value_traits() const - { return traitsptr_->priv_real_value_traits(); } + const value_traits &priv_value_traits() const + { return traitsptr_->priv_value_traits(); } - const real_bucket_traits &priv_real_bucket_traits() const - { return traitsptr_->priv_real_bucket_traits(); } + const bucket_traits &priv_bucket_traits() const + { return traitsptr_->priv_bucket_traits(); } private: void increment() { - const real_bucket_traits &rbuck_traits = this->priv_real_bucket_traits(); + const bucket_traits &rbuck_traits = this->priv_bucket_traits(); bucket_type* const buckets = boost::intrusive::detail::to_raw_pointer(rbuck_traits.bucket_begin()); const size_type buckets_len = rbuck_traits.bucket_count(); diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index c52227c..dfb677c 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -89,8 +89,6 @@ struct TRAITS_PREFIX##_bool_is_true\ BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_base_hook, hooktags::is_base_hook) BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_any_hook, is_any_hook) -BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(external_value_traits, external_value_traits) -BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(external_bucket_traits, external_bucket_traits) BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(resizable, resizable) template @@ -163,8 +161,8 @@ struct size_holder SizeType size_; }; -template -struct size_holder +template +struct size_holder { static const bool constant_time_size = false; typedef SizeType size_type; diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index f4bfb85..c046095 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -58,10 +58,9 @@ namespace detail { template struct get_slist_impl_from_supposed_value_traits { - typedef typename detail::get_real_value_traits - ::type real_value_traits; + typedef SupposedValueTraits value_traits; typedef typename detail::get_node_traits - ::type node_traits; + ::type node_traits; typedef typename get_slist_impl ::type @@ -445,10 +444,10 @@ struct downcast_node_to_value_t { typedef detail::node_to_value base_t; typedef typename base_t::result_type result_type; - typedef RealValueTraits real_value_traits; + typedef RealValueTraits value_traits; typedef typename detail::get_slist_impl ::type + ::type >::type slist_impl; typedef typename detail::add_const_if_c ::type & first_argument_type; @@ -458,9 +457,9 @@ struct downcast_node_to_value_t typedef typename pointer_traits :: template rebind_pointer - ::type const_real_value_traits_ptr; + ::type const_value_traits_ptr; - downcast_node_to_value_t(const const_real_value_traits_ptr &ptr) + downcast_node_to_value_t(const const_value_traits_ptr &ptr) : base_t(ptr) {} @@ -497,30 +496,42 @@ static const std::size_t hashtable_data_bool_flags_mask = | hash_bool_flags::incremental_pos ); +//bucket_plus_vtraits stores ValueTraits + BucketTraits +//this data is needed by iterators to obtain the +//value from the iterator and detect the bucket template struct bucket_plus_vtraits : public ValueTraits { typedef BucketTraits bucket_traits; typedef ValueTraits value_traits; - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; - static const bool external_bucket_traits = - detail::external_bucket_traits_bool_is_true::value; - - typedef typename detail::get_real_value_traits::type real_value_traits; - - static const bool safemode_or_autounlink = is_safe_autounlink::value; - - typedef typename detail::eval_if_c - < external_bucket_traits - , detail::eval_bucket_traits - , detail::identity - >::type real_bucket_traits; typedef typename detail::get_slist_impl_from_supposed_value_traits - ::type slist_impl; + ::type slist_impl; + typedef typename value_traits::node_traits node_traits; + typedef unordered_group_adapter group_traits; + typedef typename slist_impl::iterator siterator; + typedef typename slist_impl::size_type size_type; + typedef detail::bucket_impl bucket_type; + typedef detail::group_functions group_functions_t; + typedef typename slist_impl::node_algorithms node_algorithms; + typedef typename slist_impl::node_ptr slist_node_ptr; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::node node; + typedef typename value_traits::value_type value_type; + typedef circular_slist_algorithms group_algorithms; + typedef typename pointer_traits + :: + template rebind_pointer + ::type const_value_traits_ptr; + typedef typename pointer_traits + :: + template rebind_pointer + ::type const_bucket_value_traits_ptr; + typedef typename detail::unordered_bucket_ptr_impl + ::type bucket_ptr; template bucket_plus_vtraits(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits) @@ -528,56 +539,10 @@ struct bucket_plus_vtraits : public ValueTraits {} bucket_plus_vtraits & operator =(const bucket_plus_vtraits &x) - { - bucket_traits_ = x.bucket_traits_; - return *this; - } + { bucket_traits_ = x.bucket_traits_; return *this; } - //real_value_traits - // - const real_value_traits &priv_real_value_traits(detail::false_) const - { return *this; } - - const real_value_traits &priv_real_value_traits(detail::true_) const - { return this->get_value_traits(*this); } - - real_value_traits &priv_real_value_traits(detail::false_) - { return *this; } - - real_value_traits &priv_real_value_traits(detail::true_) - { return this->get_value_traits(*this); } - - const real_value_traits &priv_real_value_traits() const - { return this->priv_real_value_traits(detail::bool_()); } - - real_value_traits &priv_real_value_traits() - { return this->priv_real_value_traits(detail::bool_()); } - - typedef typename pointer_traits:: - template rebind_pointer::type const_real_value_traits_ptr; - - const_real_value_traits_ptr real_value_traits_ptr() const - { return pointer_traits::pointer_to(this->priv_real_value_traits()); } - - //real_bucket_traits - // - const real_bucket_traits &priv_real_bucket_traits(detail::false_) const - { return this->bucket_traits_; } - - const real_bucket_traits &priv_real_bucket_traits(detail::true_) const - { return this->bucket_traits_.get_bucket_traits(*this); } - - real_bucket_traits &priv_real_bucket_traits(detail::false_) - { return bucket_traits_; } - - real_bucket_traits &priv_real_bucket_traits(detail::true_) - { return this->get_bucket_traits(*this); } - - const real_bucket_traits &priv_real_bucket_traits() const - { return this->priv_real_bucket_traits(detail::bool_()); } - - real_bucket_traits &priv_real_bucket_traits() - { return this->priv_real_bucket_traits(detail::bool_()); } + const_value_traits_ptr value_traits_ptr() const + { return pointer_traits::pointer_to(this->priv_value_traits()); } //bucket_value_traits // @@ -587,9 +552,6 @@ struct bucket_plus_vtraits : public ValueTraits bucket_plus_vtraits &get_bucket_value_traits() { return *this; } - typedef typename pointer_traits:: - template rebind_pointer::type const_bucket_value_traits_ptr; - const_bucket_value_traits_ptr bucket_value_traits_ptr() const { return pointer_traits::pointer_to(this->get_bucket_value_traits()); } @@ -609,45 +571,21 @@ struct bucket_plus_vtraits : public ValueTraits bucket_traits &priv_bucket_traits() { return this->bucket_traits_; } - //operations - typedef typename detail::unordered_bucket_ptr_impl::type bucket_ptr; - + //bucket operations bucket_ptr priv_bucket_pointer() const - { return this->priv_real_bucket_traits().bucket_begin(); } + { return this->priv_bucket_traits().bucket_begin(); } typename slist_impl::size_type priv_bucket_count() const - { return this->priv_real_bucket_traits().bucket_count(); } + { return this->priv_bucket_traits().bucket_count(); } bucket_ptr priv_invalid_bucket() const { - const real_bucket_traits &rbt = this->priv_real_bucket_traits(); + const bucket_traits &rbt = this->priv_bucket_traits(); return rbt.bucket_begin() + rbt.bucket_count(); } - - typedef typename real_value_traits::node_traits node_traits; - typedef unordered_group_adapter group_traits; - typedef typename slist_impl::iterator siterator; - typedef typename slist_impl::size_type size_type; - typedef detail::bucket_impl bucket_type; - typedef detail::group_functions group_functions_t; - typedef typename slist_impl::node_algorithms node_algorithms; - typedef typename slist_impl::node_ptr slist_node_ptr; - typedef typename node_traits::node_ptr node_ptr; - typedef typename node_traits::node node; - typedef typename real_value_traits::value_type value_type; - typedef circular_slist_algorithms group_algorithms; - - -/* siterator priv_invalid_local_it() const - { return this->priv_invalid_bucket()->end(); } -*/ - siterator priv_invalid_local_it() const - { - return this->priv_real_bucket_traits().bucket_begin()->before_begin(); - } + { return this->priv_bucket_traits().bucket_begin()->before_begin(); } - /// static siterator priv_get_last(bucket_type &b, detail::true_) //optimize multikey { //First find the last node of p's group. @@ -731,47 +669,44 @@ struct bucket_plus_vtraits : public ValueTraits static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) //store_hash { return node_traits::get_hash(detail::dcast_bucket_ptr(n)); } - static std::size_t priv_stored_hash(slist_node_ptr, detail::false_) //NO store_hash - { - //This code should never be reached! - BOOST_INTRUSIVE_INVARIANT_ASSERT(0); - return 0; - } + static std::size_t priv_stored_hash(slist_node_ptr, detail::false_) //NO store_hash (This should never be called) + { BOOST_INTRUSIVE_INVARIANT_ASSERT(0); return 0; } node &priv_value_to_node(value_type &v) - { return *this->priv_real_value_traits().to_node_ptr(v); } + { return *this->priv_value_traits().to_node_ptr(v); } const node &priv_value_to_node(const value_type &v) const - { return *this->priv_real_value_traits().to_node_ptr(v); } + { return *this->priv_value_traits().to_node_ptr(v); } value_type &priv_value_from_slist_node(slist_node_ptr n) - { return *this->priv_real_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } + { return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } const value_type &priv_value_from_slist_node(slist_node_ptr n) const - { return *this->priv_real_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } + { return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } bucket_traits bucket_traits_; }; +//bucket_hash_t +//Stores bucket_plus_vtraits plust the hash function template struct bucket_hash_t : public detail::ebo_functor_holder ::real_value_traits::value_type + , typename bucket_plus_vtraits::value_traits::value_type >::type > - , bucket_plus_vtraits { - typedef typename bucket_plus_vtraits::real_value_traits real_value_traits; - typedef typename real_value_traits::value_type value_type; - typedef typename real_value_traits::node_traits node_traits; - typedef typename get_hash< VoidOrKeyHash, value_type>::type hasher; + typedef typename bucket_plus_vtraits::value_traits value_traits; + typedef typename value_traits::value_type value_type; + typedef typename value_traits::node_traits node_traits; + typedef typename get_hash< VoidOrKeyHash, value_type>::type hasher; typedef BucketTraits bucket_traits; typedef bucket_plus_vtraits bucket_plus_vtraits_t; template bucket_hash_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h) - : detail::ebo_functor_holder(h), bucket_plus_vtraits_t(val_traits, ::boost::forward(b_traits)) + : detail::ebo_functor_holder(h), internal(val_traits, ::boost::forward(b_traits)) {} const hasher &priv_hasher() const @@ -781,44 +716,47 @@ struct bucket_hash_t { return this->detail::ebo_functor_holder::get(); } std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const //For store_hash == true - { return node_traits::get_hash(this->priv_real_value_traits().to_node_ptr(v)); } + { return node_traits::get_hash(this->internal.priv_value_traits().to_node_ptr(v)); } std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const //For store_hash == false { return this->priv_hasher()(v); } + + bucket_plus_vtraits_t internal; //4 }; +//bucket_hash_equal_t +//Stores bucket_hash_t and the equality function when the first +//non-empty bucket shall not be cached. template struct bucket_hash_equal_t : public detail::ebo_functor_holder //equal ::real_value_traits::value_type + , typename bucket_plus_vtraits::value_traits::value_type >::type > - , bucket_hash_t { - typedef bucket_hash_t bucket_hash_type; - typedef typename bucket_plus_vtraits::real_value_traits real_value_traits; + typedef bucket_hash_t bucket_hash_type; + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef typename bucket_plus_vtraits_t::value_traits value_traits; typedef typename get_equal_to< VoidOrKeyEqual - , typename real_value_traits::value_type + , typename value_traits::value_type >::type value_equal; typedef typename bucket_hash_type::hasher hasher; typedef BucketTraits bucket_traits; - typedef bucket_hash_t buckethash_t; - typedef typename bucket_hash_type::real_bucket_traits real_bucket_traits; - typedef typename bucket_hash_type::slist_impl slist_impl; - typedef typename slist_impl::size_type size_type; - typedef typename slist_impl::iterator siterator; - typedef detail::bucket_impl bucket_type; - typedef typename detail::unordered_bucket_ptr_impl::type bucket_ptr; + typedef typename bucket_plus_vtraits_t::slist_impl slist_impl; + typedef typename slist_impl::size_type size_type; + typedef typename slist_impl::iterator siterator; + typedef detail::bucket_impl bucket_type; + typedef typename detail::unordered_bucket_ptr_impl::type bucket_ptr; template bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) : detail::ebo_functor_holder(e) - , buckethash_t(val_traits, ::boost::forward(b_traits), h) + , internal(val_traits, ::boost::forward(b_traits), h) {} bucket_ptr priv_get_cache() - { return this->priv_bucket_pointer(); } + { return this->internal.internal.priv_bucket_pointer(); } void priv_set_cache(const bucket_ptr &) {} @@ -835,14 +773,14 @@ struct bucket_hash_equal_t siterator priv_begin() const { size_type n = 0; - size_type bucket_cnt = this->priv_bucket_count(); + size_type bucket_cnt = this->internal.internal.priv_bucket_count(); for (n = 0; n < bucket_cnt; ++n){ - bucket_type &b = this->priv_bucket_pointer()[n]; + bucket_type &b = this->internal.internal.priv_bucket_pointer()[n]; if(!b.empty()){ return b.begin(); } } - return this->priv_invalid_local_it(); + return this->internal.internal.priv_invalid_local_it(); } void priv_insertion_update_cache(size_type) @@ -859,34 +797,41 @@ struct bucket_hash_equal_t value_equal &priv_equal() { return this->detail::ebo_functor_holder::get(); } + + bucket_hash_t internal; //3 }; +//bucket_hash_equal_t +//Stores bucket_hash_t and the equality function when the first +//non-empty bucket shall be cached. template //cache_begin == true version struct bucket_hash_equal_t : public detail::ebo_functor_holder //equal - ::real_value_traits::value_type + ::value_traits::value_type >::type - > - , public bucket_hash_t + > { - typedef bucket_hash_t bucket_hash_type; - typedef typename get_equal_to< VoidOrKeyEqual - , typename bucket_plus_vtraits::real_value_traits::value_type - >::type value_equal; - typedef typename bucket_hash_type::hasher hasher; - typedef BucketTraits bucket_traits; - typedef typename bucket_hash_type::slist_impl::size_type size_type; - typedef typename bucket_hash_type::slist_impl::iterator siterator; + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef bucket_hash_t bucket_hash_type; + typedef typename bucket_plus_vtraits + ::value_traits value_traits; + typedef typename get_equal_to + < VoidOrKeyEqual + , typename value_traits::value_type>::type value_equal; + typedef typename bucket_hash_type::hasher hasher; + typedef BucketTraits bucket_traits; + typedef typename bucket_plus_vtraits_t::slist_impl::size_type size_type; + typedef typename bucket_plus_vtraits_t::slist_impl::iterator siterator; template bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) : detail::ebo_functor_holder(e) - , bucket_hash_type(val_traits, ::boost::forward(b_traits), h) + , internal(val_traits, ::boost::forward(b_traits), h) {} typedef typename detail::unordered_bucket_ptr_impl - ::type bucket_ptr; + ::type bucket_ptr; bucket_ptr &priv_get_cache() { return cached_begin_; } @@ -898,10 +843,10 @@ struct bucket_hash_equal_tcached_begin_ - this->priv_bucket_pointer(); } + { return this->cached_begin_ - this->internal.internal.priv_bucket_pointer(); } void priv_initialize_cache() - { this->cached_begin_ = this->priv_invalid_bucket(); } + { this->cached_begin_ = this->internal.internal.priv_invalid_bucket(); } void priv_swap_cache(bucket_hash_equal_t &other) { @@ -910,8 +855,8 @@ struct bucket_hash_equal_tcached_begin_ == this->priv_invalid_bucket()){ - return this->priv_invalid_local_it(); + if(this->cached_begin_ == this->internal.internal.priv_invalid_bucket()){ + return this->internal.internal.priv_invalid_local_it(); } else{ return this->cached_begin_->begin(); @@ -920,7 +865,7 @@ struct bucket_hash_equal_tpriv_bucket_pointer() + insertion_bucket; + bucket_ptr p = this->internal.internal.priv_bucket_pointer() + insertion_bucket; if(p < this->cached_begin_){ this->cached_begin_ = p; } @@ -937,17 +882,17 @@ struct bucket_hash_equal_tpriv_get_cache_bucket_num() == first_bucket_num && - this->priv_bucket_pointer()[first_bucket_num].empty() ){ - this->priv_set_cache(this->priv_bucket_pointer() + last_bucket_num); + this->internal.internal.priv_bucket_pointer()[first_bucket_num].empty() ){ + this->priv_set_cache(this->internal.internal.priv_bucket_pointer() + last_bucket_num); this->priv_erasure_update_cache(); } } void priv_erasure_update_cache() { - if(this->cached_begin_ != this->priv_invalid_bucket()){ - size_type current_n = this->priv_get_cache() - this->priv_bucket_pointer(); - for( const size_type num_buckets = this->priv_bucket_count() + if(this->cached_begin_ != this->internal.internal.priv_invalid_bucket()){ + size_type current_n = this->priv_get_cache() - this->internal.internal.priv_bucket_pointer(); + for( const size_type num_buckets = this->internal.internal.priv_bucket_count() ; current_n < num_buckets ; ++current_n, ++this->priv_get_cache()){ if(!this->priv_get_cache()->empty()){ @@ -958,90 +903,78 @@ struct bucket_hash_equal_t internal; //2 }; +//hashdata_internal +//Stores bucket_hash_equal_t and split_traits template struct hashdata_internal : public detail::size_holder< 0 != (BoolFlags & hash_bool_flags::incremental_pos), SizeType, int> //split_traits - , public bucket_hash_equal_t - < VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits - , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos) - > { typedef bucket_hash_equal_t - < VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits + < VoidOrKeyHash, VoidOrKeyEqual + , ValueTraits, BucketTraits , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos) - > bucket_hash_equal_type; - - typedef typename bucket_hash_equal_type::value_equal value_equal; - typedef typename bucket_hash_equal_type::hasher hasher; - typedef bucket_plus_vtraits bucket_plus_vtraits_t; - typedef typename bucket_plus_vtraits_t::size_type size_type; - typedef typename bucket_plus_vtraits_t::bucket_ptr bucket_ptr; - static const bool optimize_multikey - = detail::optimize_multikey_is_true::value; - - typedef detail::bool_ optimize_multikey_t; + > internal_type; + typedef typename internal_type::value_equal value_equal; + typedef typename internal_type::hasher hasher; + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef typename bucket_plus_vtraits_t::size_type size_type; + typedef typename bucket_plus_vtraits_t::bucket_ptr bucket_ptr; + typedef detail::size_holder + <0 != (BoolFlags & hash_bool_flags::incremental_pos) + , SizeType, int> split_traits; + typedef typename bucket_plus_vtraits_t:: + value_traits::node_traits node_traits; + typedef detail::bool_::value> optimize_multikey_t; template - hashdata_internal(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) - : bucket_hash_equal_type(val_traits, ::boost::forward(b_traits), h, e) + hashdata_internal( const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits + , const hasher & h, const value_equal &e) + : internal(val_traits, ::boost::forward(b_traits), h, e) {} - typedef detail::size_holder - <0 != (BoolFlags & hash_bool_flags::incremental_pos), SizeType, int> split_traits; - split_traits &priv_split_traits() { return *this; } const split_traits &priv_split_traits() const { return *this; } + + internal_type internal; //2 }; +//hashtable_data_t +//Stores hashdata_internal and size_traits template struct hashtable_data_t - : public detail::size_holder< 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos), SizeType> //size_traits - , public hashdata_internal - < SizeType, BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) - , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> + : public detail::size_holder + < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos), SizeType> //size_traits { - static const std::size_t bool_flags = BoolFlags; typedef detail::size_holder < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos) - , SizeType> size_traits; - + , SizeType> size_traits; typedef hashdata_internal - < SizeType, BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) - , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> internal_type; - - typedef ValueTraits value_traits; - typedef typename internal_type::value_equal value_equal; - typedef typename internal_type::hasher hasher; - typedef BucketTraits bucket_traits; + < SizeType + , BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) + , VoidOrKeyHash, VoidOrKeyEqual + , ValueTraits, BucketTraits> internal_type; + typedef ValueTraits value_traits; + typedef typename internal_type::value_equal value_equal; + typedef typename internal_type::hasher hasher; + typedef BucketTraits bucket_traits; typedef bucket_plus_vtraits - bucket_plus_vtraits_t; - - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - static const bool external_bucket_traits = bucket_plus_vtraits_t::external_bucket_traits; - - typedef typename bucket_plus_vtraits_t::real_value_traits real_value_traits; - typedef typename bucket_plus_vtraits_t::real_bucket_traits real_bucket_traits; - - size_traits &priv_size_traits() - { return *this; } - - const size_traits &priv_size_traits() const - { return *this; } + bucket_plus_vtraits_t; template hashtable_data_t( BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h , const value_equal &e, const value_traits &val_traits) - : size_traits() - , internal_type(val_traits, ::boost::forward(b_traits), h, e) + : internal(val_traits, ::boost::forward(b_traits), h, e) {} + + internal_type internal; //1 }; /// @endcond @@ -1088,53 +1021,45 @@ template template #endif class hashtable_impl - : public hashtable_data_t - < SizeType - , BoolFlags & hashtable_data_bool_flags_mask - , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> - , private detail::clear_on_destructor_base + : private detail::clear_on_destructor_base < hashtable_impl , true //To always clear the bucket array - //is_safe_autounlink::type::link_mode>::value + //is_safe_autounlink::type::link_mode>::value > { template friend class detail::clear_on_destructor_base; - public: - typedef ValueTraits value_traits; - typedef hashtable_data_t < SizeType , BoolFlags & hashtable_data_bool_flags_mask , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> data_type; + data_type data; + + public: + typedef ValueTraits value_traits; /// @cond - static const bool external_value_traits = data_type::external_value_traits; - static const bool external_bucket_traits = data_type::external_bucket_traits; - typedef BucketTraits bucket_traits; - typedef typename data_type::real_bucket_traits real_bucket_traits; - typedef typename data_type::real_value_traits real_value_traits; - typedef typename detail::get_slist_impl ::type - >::type slist_impl; - typedef bucket_plus_vtraits bucket_plus_vtraits_t; - typedef typename bucket_plus_vtraits_t::const_real_value_traits_ptr const_real_value_traits_ptr; + ::type + >::type slist_impl; + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef typename bucket_plus_vtraits_t::const_value_traits_ptr const_value_traits_ptr; /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; - typedef typename real_value_traits::value_type value_type; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; + typedef typename value_traits::value_type value_type; typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; typedef SizeType size_type; typedef value_type key_type; typedef typename data_type::value_equal key_equal; + typedef typename data_type::value_equal value_equal; typedef typename data_type::hasher hasher; typedef detail::bucket_impl bucket_type; typedef typename pointer_traits @@ -1144,7 +1069,7 @@ class hashtable_impl typedef typename slist_impl::const_iterator const_siterator; typedef hashtable_iterator iterator; typedef hashtable_iterator const_iterator; - typedef typename real_value_traits::node_traits node_traits; + typedef typename value_traits::node_traits node_traits; typedef typename node_traits::node node; typedef typename pointer_traits ::template rebind_pointer @@ -1154,7 +1079,7 @@ class hashtable_impl < const node >::type const_node_ptr; typedef typename slist_impl::node_algorithms node_algorithms; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; static const bool store_hash = detail::store_hash_is_true::value; static const bool unique_keys = 0 != (BoolFlags & hash_bool_flags::unique_keys_pos); @@ -1195,22 +1120,22 @@ class hashtable_impl //noncopyable, movable BOOST_MOVABLE_BUT_NOT_COPYABLE(hashtable_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink))); //Cache begin is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(cache_begin && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(cache_begin && ((int)value_traits::link_mode == (int)auto_unlink))); template - node_cast_adaptor< detail::node_disposer + node_cast_adaptor< detail::node_disposer , slist_node_ptr, node_ptr > make_node_disposer(const Disposer &disposer) const { return node_cast_adaptor - < detail::node_disposer + < detail::node_disposer , slist_node_ptr, node_ptr > - (disposer, &this->priv_real_value_traits()); + (disposer, &this->priv_value_traits()); } /// @endcond @@ -1221,13 +1146,13 @@ class hashtable_impl typedef detail::transform_iterator < typename slist_impl::iterator , downcast_node_to_value_t - < real_value_traits + < value_traits , false> > local_iterator; typedef detail::transform_iterator < typename slist_impl::iterator , downcast_node_to_value_t - < real_value_traits + < value_traits , true> > const_local_iterator; public: @@ -1249,7 +1174,7 @@ class hashtable_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : data_type(b_traits, hash_func, equal_func, v_traits) + : data(b_traits, hash_func, equal_func, v_traits) { this->priv_initialize_buckets(); this->priv_size_traits().set_size(size_type(0)); @@ -1264,7 +1189,7 @@ class hashtable_impl //! Effects: to-do //! hashtable_impl(BOOST_RV_REF(hashtable_impl) x) - : data_type( ::boost::move(x.priv_bucket_traits()) + : data( ::boost::move(x.priv_bucket_traits()) , ::boost::move(x.priv_hasher()) , ::boost::move(x.priv_equal()) , ::boost::move(x.priv_value_traits()) @@ -1431,7 +1356,7 @@ class hashtable_impl { using std::swap; //These can throw - swap(this->priv_equal(), other.priv_equal()); + swap(this->priv_equal(), other.priv_equal()); swap(this->priv_hasher(), other.priv_hasher()); //These can't throw swap(this->priv_bucket_traits(), other.priv_bucket_traits()); @@ -1488,11 +1413,11 @@ class hashtable_impl const bucket_ptr dst_buckets = this->priv_bucket_pointer(); size_type constructed; - typedef node_cast_adaptor< detail::node_disposer + typedef node_cast_adaptor< detail::node_disposer , slist_node_ptr, node_ptr > NodeDisposer; - typedef node_cast_adaptor< detail::node_cloner + typedef node_cast_adaptor< detail::node_cloner , slist_node_ptr, node_ptr > NodeCloner; - NodeDisposer node_disp(disposer, &this->priv_real_value_traits()); + NodeDisposer node_disp(disposer, &this->priv_value_traits()); detail::exception_array_disposer rollback(dst_buckets[0], node_disp, constructed); @@ -1501,7 +1426,7 @@ class hashtable_impl ; ++constructed){ dst_buckets[constructed].clone_from ( src_buckets[constructed] - , NodeCloner(cloner, &this->priv_real_value_traits()), node_disp); + , NodeCloner(cloner, &this->priv_value_traits()), node_disp); } if(src_bucket_count != dst_bucket_count){ //Now insert the remaining ones using the modulo trick @@ -1514,7 +1439,7 @@ class hashtable_impl for( siterator b(src_b.begin()), e(src_b.end()) ; b != e ; ++b){ - dst_b.push_front(*(NodeCloner(cloner, &this->priv_real_value_traits())(*b.pointed_node()))); + dst_b.push_front(*(NodeCloner(cloner, &this->priv_value_traits())(*b.pointed_node()))); } } } @@ -1529,7 +1454,7 @@ class hashtable_impl else if(store_hash){ //Unlike previous cloning algorithm, this can throw //if cloner, hasher or comparison functor throw - const_iterator b(src.begin()), e(src.end()); + const_iterator b(src.cbegin()), e(src.cend()); detail::exception_disposer rollback(*this, disposer); for(; b != e; ++b){ @@ -1541,7 +1466,7 @@ class hashtable_impl else{ //Unlike previous cloning algorithm, this can throw //if cloner, hasher or comparison functor throw - const_iterator b(src.begin()), e(src.end()); + const_iterator b(src.cbegin()), e(src.cend()); detail::exception_disposer rollback(*this, disposer); for(; b != e; ++b){ @@ -2153,7 +2078,8 @@ class hashtable_impl std::pair ret = this->priv_equal_range(key, hash_func, equal_func, bucket_n1, bucket_n2, cnt); return std::pair - (const_iterator(ret.first, &this->get_bucket_value_traits()), const_iterator(ret.second, &this->get_bucket_value_traits())); + ( const_iterator(ret.first, &this->get_bucket_value_traits()) + , const_iterator(ret.second, &this->get_bucket_value_traits())); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2167,7 +2093,8 @@ class hashtable_impl //! Throws: If the internal hash function throws. iterator iterator_to(reference value) { - return iterator(bucket_type::s_iterator_to(this->priv_value_to_node(value)), &this->get_bucket_value_traits()); + return iterator(bucket_type::s_iterator_to + (this->priv_value_to_node(value)), &this->get_bucket_value_traits()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2201,7 +2128,7 @@ class hashtable_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(value)); - return local_iterator(sit, const_real_value_traits_ptr()); + return local_iterator(sit, const_value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2220,7 +2147,7 @@ class hashtable_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(const_cast(value))); - return const_local_iterator(sit, const_real_value_traits_ptr()); + return const_local_iterator(sit, const_value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2235,7 +2162,7 @@ class hashtable_impl local_iterator local_iterator_to(reference value) { siterator sit = bucket_type::s_iterator_to(this->priv_value_to_node(value)); - return local_iterator(sit, this->real_value_traits_ptr()); + return local_iterator(sit, this->value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2251,7 +2178,7 @@ class hashtable_impl { siterator sit = bucket_type::s_iterator_to (const_cast(this->priv_value_to_node(value))); - return const_local_iterator(sit, this->real_value_traits_ptr()); + return const_local_iterator(sit, this->value_traits_ptr()); } //! Effects: Returns the number of buckets passed in the constructor @@ -2321,7 +2248,7 @@ class hashtable_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. local_iterator begin(size_type n) - { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->real_value_traits_ptr()); } + { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2351,7 +2278,7 @@ class hashtable_impl const_local_iterator cbegin(size_type n) const { siterator sit = const_cast(this->priv_bucket_pointer()[n]).begin(); - return const_local_iterator(sit, this->real_value_traits_ptr()); + return const_local_iterator(sit, this->value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). @@ -2366,7 +2293,7 @@ class hashtable_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. local_iterator end(size_type n) - { return local_iterator(this->priv_bucket_pointer()[n].end(), this->real_value_traits_ptr()); } + { return local_iterator(this->priv_bucket_pointer()[n].end(), this->value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2396,7 +2323,7 @@ class hashtable_impl const_local_iterator cend(size_type n) const { return const_local_iterator ( const_cast(this->priv_bucket_pointer()[n]).end() - , this->real_value_traits_ptr()); + , this->value_traits_ptr()); } //! Requires: new_bucket_traits can hold a pointer to a new bucket array @@ -2503,7 +2430,7 @@ class hashtable_impl this->priv_size_traits().set_size(size_backup); this->priv_split_traits().set_size(new_bucket_count); - this->priv_real_bucket_traits() = new_bucket_traits; + this->priv_bucket_traits() = new_bucket_traits; this->priv_initialize_cache(); this->priv_insertion_update_cache(new_first_bucket_num); rollback1.release(); @@ -2616,7 +2543,7 @@ class hashtable_impl const size_type ini_n = this->priv_get_cache_bucket_num(); const bucket_ptr old_buckets = this->priv_bucket_pointer(); - this->priv_real_bucket_traits() = new_bucket_traits; + this->priv_bucket_traits() = new_bucket_traits; if(new_bucket_traits.bucket_begin() != old_buckets){ for(size_type n = ini_n; n < split_idx; ++n){ bucket_type &new_bucket = new_bucket_traits.bucket_begin()[n]; @@ -2684,6 +2611,105 @@ class hashtable_impl /// @cond private: + size_traits &priv_size_traits() + { return this->data; } + + const size_traits &priv_size_traits() const + { return this->data; } + + bucket_ptr priv_bucket_pointer() const + { return this->data.internal.internal.internal.internal.priv_bucket_pointer(); } + + SizeType priv_bucket_count() const + { return this->data.internal.internal.internal.internal.priv_bucket_count(); } + + const bucket_plus_vtraits &get_bucket_value_traits() const + { return this->data.internal.internal.internal.internal.get_bucket_value_traits(); } + + bucket_plus_vtraits &get_bucket_value_traits() + { return this->data.internal.internal.internal.internal.get_bucket_value_traits(); } + + bucket_traits &priv_bucket_traits() + { return this->data.internal.internal.internal.internal.priv_bucket_traits(); } + + const bucket_traits &priv_bucket_traits() const + { return this->data.internal.internal.internal.internal.priv_bucket_traits(); } + + value_traits &priv_value_traits() + { return this->data.internal.internal.internal.internal.priv_value_traits(); } + + const value_traits &priv_value_traits() const + { return this->data.internal.internal.internal.internal.priv_value_traits(); } + + const_value_traits_ptr value_traits_ptr() const + { return this->data.internal.internal.internal.internal.value_traits_ptr(); } + + siterator priv_invalid_local_it() const + { return this->data.internal.internal.internal.internal.priv_invalid_local_it(); } + + split_traits &priv_split_traits() + { return this->data.internal.priv_split_traits(); } + + const split_traits &priv_split_traits() const + { return this->data.internal.priv_split_traits(); } + + bucket_ptr priv_get_cache() + { return this->data.internal.internal.priv_get_cache(); } + + void priv_initialize_cache() + { return this->data.internal.internal.priv_initialize_cache(); } + + siterator priv_begin() const + { return this->data.internal.internal.priv_begin(); } + + const value_equal &priv_equal() const + { return this->data.internal.internal.priv_equal(); } + + value_equal &priv_equal() + { return this->data.internal.internal.priv_equal(); } + + const hasher &priv_hasher() const + { return this->data.internal.internal.internal.priv_hasher(); } + + hasher &priv_hasher() + { return this->data.internal.internal.internal.priv_hasher(); } + + void priv_swap_cache(hashtable_impl &h) + { this->data.internal.internal.priv_swap_cache(h.data.internal.internal); } + + node &priv_value_to_node(value_type &v) + { return this->data.internal.internal.internal.internal.priv_value_to_node(v); } + + const node &priv_value_to_node(const value_type &v) const + { return this->data.internal.internal.internal.internal.priv_value_to_node(v); } + + SizeType priv_get_cache_bucket_num() + { return this->data.internal.internal.priv_get_cache_bucket_num(); } + + void priv_insertion_update_cache(SizeType n) + { return this->data.internal.internal.priv_insertion_update_cache(n); } + + template + std::size_t priv_stored_or_compute_hash(const value_type &v, detail::bool_ b) const + { return this->data.internal.internal.internal.priv_stored_or_compute_hash(v, b); } + + value_type &priv_value_from_slist_node(slist_node_ptr n) + { return this->data.internal.internal.internal.internal.priv_value_from_slist_node(n); } + + const value_type &priv_value_from_slist_node(slist_node_ptr n) const + { return this->data.internal.internal.internal.internal.priv_value_from_slist_node(n); } + + void priv_erasure_update_cache_range(SizeType first_bucket_num, SizeType last_bucket_num) + { return this->data.internal.internal.priv_erasure_update_cache_range(first_bucket_num, last_bucket_num); } + + void priv_erasure_update_cache() + { return this->data.internal.internal.priv_erasure_update_cache(); } + + static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_ true_value) + { return bucket_plus_vtraits::priv_stored_hash(n, true_value); } + + static std::size_t priv_stored_hash(slist_node_ptr n, detail::false_ false_value) + { return bucket_plus_vtraits::priv_stored_hash(n, false_value); } void priv_clear_buckets(bucket_ptr buckets_ptr, size_type bucket_cnt) { @@ -2712,7 +2738,7 @@ class hashtable_impl std::size_t priv_hash_to_bucket(std::size_t hash_value) const { return detail::hash_to_bucket_split - (hash_value, this->priv_real_bucket_traits().bucket_count(), this->priv_split_traits().get_size()); + (hash_value, this->priv_bucket_traits().bucket_count(), this->priv_split_traits().get_size()); } template @@ -2790,7 +2816,7 @@ class hashtable_impl } std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) //NO store_hash - { return this->priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } + { return this->data.internal.internal.internal.internal.priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } static siterator priv_get_previous(bucket_type &b, siterator i) { return bucket_plus_vtraits_t::priv_get_previous(b, i, optimize_multikey_t()); } @@ -3005,21 +3031,18 @@ template < class T #else template #endif -struct make_real_bucket_traits +struct make_bucket_traits { //Real value traits must be calculated from options typedef typename detail::get_value_traits ::type value_traits; -/* - static const bool resizable_bucket_traits = - detail::resizable_bool_is_true::value;*/ - typedef typename detail::get_real_value_traits::type real_value_traits; + typedef typename PackedOptions::bucket_traits specified_bucket_traits; //Real bucket traits must be calculated from options and calculated value_traits typedef typename detail::get_slist_impl ::type + ::type >::type slist_impl; typedef typename @@ -3060,15 +3083,15 @@ struct make_hashtable typedef typename detail::get_value_traits ::type value_traits; - typedef typename make_real_bucket_traits - ::type real_bucket_traits; + typedef typename make_bucket_traits + ::type bucket_traits; typedef hashtable_impl < value_traits , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type - , real_bucket_traits + , bucket_traits , (std::size_t(false)*hash_bool_flags::unique_keys_pos) | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) @@ -3108,7 +3131,6 @@ class hashtable public: typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::bucket_ptr bucket_ptr; @@ -3118,7 +3140,7 @@ class hashtable typedef typename Base::key_equal key_equal; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit hashtable ( const bucket_traits &b_traits , const hasher & hash_func = hasher() diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index ce2cda5..0048a91 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -65,37 +65,32 @@ template class list_impl : private detail::clear_on_destructor_base < list_impl - , is_safe_autounlink::type::link_mode>::value + , is_safe_autounlink::value > { template friend class detail::clear_on_destructor_base; //Public typedefs public: - typedef ValueTraits value_traits; - /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::get_real_value_traits::type real_value_traits; - /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; + typedef ValueTraits value_traits; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; typedef typename pointer_traits::element_type value_type; typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; typedef SizeType size_type; - typedef list_iterator iterator; - typedef list_iterator const_iterator; + typedef list_iterator iterator; + typedef list_iterator const_iterator; typedef boost::intrusive::detail::reverse_iterator reverse_iterator; typedef boost::intrusive::detail::reverse_iteratorconst_reverse_iterator; - typedef typename real_value_traits::node_traits node_traits; + typedef typename value_traits::node_traits node_traits; typedef typename node_traits::node node; typedef typename node_traits::node_ptr node_ptr; typedef typename node_traits::const_node_ptr const_node_ptr; typedef circular_list_algorithms node_algorithms; static const bool constant_time_size = ConstantTimeSize; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond @@ -105,11 +100,11 @@ class list_impl //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(list_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; //Constant-time size is incompatible with auto-unlink hooks! BOOST_STATIC_ASSERT(!(constant_time_size && - ((int)real_value_traits::link_mode == (int)auto_unlink) + ((int)value_traits::link_mode == (int)auto_unlink) )); node_ptr get_root_node() @@ -139,54 +134,27 @@ class list_impl const size_traits &priv_size_traits() const { return data_.root_plus_size_; } - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } - const value_traits &priv_value_traits() const { return data_; } value_traits &priv_value_traits() { return data_; } - protected: - node &prot_root_node() - { return data_.root_plus_size_.root_; } + typedef typename pointer_traits::template + rebind_pointer::type const_value_traits_ptr; - node const &prot_root_node() const - { return data_.root_plus_size_.root_; } - - void prot_set_size(size_type s) - { data_.root_plus_size_.set_size(s); } + const_value_traits_ptr value_traits_ptr() const + { return pointer_traits::pointer_to(this->priv_value_traits()); } /// @endcond public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } - - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - - typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; - - const_real_value_traits_ptr real_value_traits_ptr() const - { return pointer_traits::pointer_to(this->get_real_value_traits()); } - //! Effects: constructs an empty list. //! //! Complexity: Constant //! - //! Throws: If real_value_traits::node_traits::node + //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks). explicit list_impl(const value_traits &v_traits = value_traits()) : data_(v_traits) @@ -201,7 +169,7 @@ class list_impl //! //! Complexity: Linear in std::distance(b, e). No copy constructors are called. //! - //! Throws: If real_value_traits::node_traits::node + //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks). template list_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits()) @@ -253,7 +221,7 @@ class list_impl //! Note: Does not affect the validity of iterators and references. void push_back(reference value) { - node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + node_ptr to_insert = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); node_algorithms::link_before(this->get_root_node(), to_insert); @@ -272,7 +240,7 @@ class list_impl //! Note: Does not affect the validity of iterators and references. void push_front(reference value) { - node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + node_ptr to_insert = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert); @@ -309,7 +277,7 @@ class list_impl this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); } //! Effects: Erases the first element of the list. @@ -342,7 +310,7 @@ class list_impl this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); } //! Effects: Returns a reference to the first element of the list. @@ -351,7 +319,7 @@ class list_impl //! //! Complexity: Constant. reference front() - { return *get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } + { return *priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } //! Effects: Returns a const_reference to the first element of the list. //! @@ -359,7 +327,7 @@ class list_impl //! //! Complexity: Constant. const_reference front() const - { return *get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } + { return *priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } //! Effects: Returns a reference to the last element of the list. //! @@ -367,7 +335,7 @@ class list_impl //! //! Complexity: Constant. reference back() - { return *get_real_value_traits().to_value_ptr(node_traits::get_previous(this->get_root_node())); } + { return *priv_value_traits().to_value_ptr(node_traits::get_previous(this->get_root_node())); } //! Effects: Returns a const_reference to the last element of the list. //! @@ -375,7 +343,7 @@ class list_impl //! //! Complexity: Constant. const_reference back() const - { return *get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_previous(this->get_root_node()))); } + { return *priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_previous(this->get_root_node()))); } //! Effects: Returns an iterator to the first element contained in the list. //! @@ -383,7 +351,7 @@ class list_impl //! //! Complexity: Constant. iterator begin() - { return iterator(node_traits::get_next(this->get_root_node()), real_value_traits_ptr()); } + { return iterator(node_traits::get_next(this->get_root_node()), value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -399,7 +367,7 @@ class list_impl //! //! Complexity: Constant. const_iterator cbegin() const - { return const_iterator(node_traits::get_next(this->get_root_node()), real_value_traits_ptr()); } + { return const_iterator(node_traits::get_next(this->get_root_node()), value_traits_ptr()); } //! Effects: Returns an iterator to the end of the list. //! @@ -407,7 +375,7 @@ class list_impl //! //! Complexity: Constant. iterator end() - { return iterator(this->get_root_node(), real_value_traits_ptr()); } + { return iterator(this->get_root_node(), value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -423,7 +391,7 @@ class list_impl //! //! Complexity: Constant. const_iterator cend() const - { return const_iterator(detail::uncast(this->get_root_node()), real_value_traits_ptr()); } + { return const_iterator(detail::uncast(this->get_root_node()), value_traits_ptr()); } //! Effects: Returns a reverse_iterator pointing to the beginning //! of the reversed list. @@ -663,7 +631,7 @@ class list_impl this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->priv_value_traits().to_value_ptr(to_erase)); return i.unconst(); } @@ -697,7 +665,7 @@ class list_impl bp = node_traits::get_next(bp); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); this->priv_size_traits().decrement(); } return e.unconst(); @@ -743,7 +711,7 @@ class list_impl ++it; if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); } node_algorithms::init_header(this->get_root_node()); this->priv_size_traits().set_size(0); @@ -789,12 +757,12 @@ class list_impl //! Note: Does not affect the validity of iterators and references. iterator insert(const_iterator p, reference value) { - node_ptr to_insert = this->get_real_value_traits().to_node_ptr(value); + node_ptr to_insert = this->priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); node_algorithms::link_before(p.pointed_node(), to_insert); this->priv_size_traits().increment(); - return iterator(to_insert, real_value_traits_ptr()); + return iterator(to_insert, value_traits_ptr()); } //! Requires: Dereferencing iterator must yield @@ -957,7 +925,7 @@ class list_impl //! Effects: This function sorts the list *this according to std::less. //! The sort is stable, that is, the relative order of equivalent elements is preserved. //! - //! Throws: If real_value_traits::node_traits::node + //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) //! or std::less throws. Basic guarantee. //! @@ -973,7 +941,7 @@ class list_impl //! Effects: This function sorts the list *this according to p. The sort is //! stable, that is, the relative order of equivalent elements is preserved. //! - //! Throws: If real_value_traits::node_traits::node + //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) //! or the predicate throws. Basic guarantee. //! @@ -1227,8 +1195,8 @@ class list_impl static iterator s_iterator_to(reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value))); - return iterator(real_value_traits::to_node_ptr(value), const_real_value_traits_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(value))); + return iterator(value_traits::to_node_ptr(value), const_value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1245,8 +1213,8 @@ class list_impl static const_iterator s_iterator_to(const_reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value)))); - return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); + return const_iterator(value_traits::to_node_ptr(const_cast (value)), const_value_traits_ptr()); } //! Requires: value must be a reference to a value inserted in a list. @@ -1260,8 +1228,8 @@ class list_impl //! Note: Iterators and references are not invalidated. iterator iterator_to(reference value) { - BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value))); - return iterator(real_value_traits::to_node_ptr(value), real_value_traits_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(value))); + return iterator(value_traits::to_node_ptr(value), value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1275,8 +1243,8 @@ class list_impl //! Note: Iterators and references are not invalidated. const_iterator iterator_to(const_reference value) const { - BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value)))); - return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), real_value_traits_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); + return const_iterator(value_traits::to_node_ptr(const_cast (value)), value_traits_ptr()); } /// @cond @@ -1468,9 +1436,8 @@ class list Options... #endif >::type Base; - typedef typename Base::real_value_traits real_value_traits; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); BOOST_MOVABLE_BUT_NOT_COPYABLE(list) public: diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index f6854e4..7652f9a 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -51,27 +51,6 @@ BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bstree_hook); #undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION -template -struct eval_value_traits -{ - typedef typename ValueTraits::value_traits type; -}; - -template -struct get_real_value_traits - : public eval_if_c - < external_value_traits_bool_is_true::value - , eval_value_traits - , identity - > -{}; - -template -struct eval_bucket_traits -{ - typedef typename BucketTraits::bucket_traits type; -}; - template struct concrete_hook_base_value_traits { diff --git a/include/boost/intrusive/priority_compare.hpp b/include/boost/intrusive/priority_compare.hpp index 026af29..f6beee1 100644 --- a/include/boost/intrusive/priority_compare.hpp +++ b/include/boost/intrusive/priority_compare.hpp @@ -23,8 +23,12 @@ namespace intrusive { template struct priority_compare - : public std::binary_function { + //Compatibility with std::binary_function + typedef T first_argument_type; + typedef T second_argument_type; + typedef bool result_type; + bool operator()(const T &val, const T &val2) const { return priority_order(val, val2); diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index bff85de..c4ff5f4 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -483,14 +483,13 @@ class rbtree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit rbtree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index b28b0ae..8cb2b5c 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -226,7 +226,6 @@ class sgtree_impl typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType , true, SgTreeAlgorithms> tree_type; typedef tree_type implementation_defined; - typedef typename tree_type::real_value_traits real_value_traits; /// @endcond @@ -263,11 +262,11 @@ class sgtree_impl typedef typename alpha_traits::multiply_by_alpha_t multiply_by_alpha_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(sgtree_impl) - BOOST_STATIC_ASSERT(((int)real_value_traits::link_mode != (int)auto_unlink)); + BOOST_STATIC_ASSERT(((int)value_traits::link_mode != (int)auto_unlink)); enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; + (int)value_traits::link_mode == (int)auto_unlink || + (int)value_traits::link_mode == (int)safe_link }; /// @endcond @@ -412,9 +411,9 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->value_comp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -423,15 +422,15 @@ class sgtree_impl , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this->real_value_traits_ptr()); + return iterator(p, this->value_traits_ptr()); } //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference) iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->value_comp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -440,7 +439,7 @@ class sgtree_impl , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this->real_value_traits_ptr()); + return iterator(p, this->value_traits_ptr()); } //! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator) @@ -477,12 +476,12 @@ class sgtree_impl std::pair insert_unique_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - comp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + comp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->tree_type::header_ptr(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) @@ -491,18 +490,18 @@ class sgtree_impl (const_iterator hint, const KeyType &key ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - comp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + comp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->tree_type::header_ptr(), hint.pointed_node(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } //! @copydoc ::boost::intrusive::bstree::insert_unique_commit iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -511,7 +510,7 @@ class sgtree_impl , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; - return iterator(to_insert, this->real_value_traits_ptr()); + return iterator(to_insert, this->value_traits_ptr()); } //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator) @@ -532,7 +531,7 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::insert_before iterator insert_before(const_iterator pos, reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -541,13 +540,13 @@ class sgtree_impl , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this->real_value_traits_ptr()); + return iterator(p, this->value_traits_ptr()); } //! @copydoc ::boost::intrusive::bstree::push_back void push_back(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -561,7 +560,7 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::push_front void push_front(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -620,7 +619,7 @@ class sgtree_impl { node_ptr to_erase(i.pointed_node()); iterator ret(this->erase(i)); - disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->get_value_traits().to_value_ptr(to_erase)); return ret; } @@ -930,14 +929,13 @@ class sgtree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit sgtree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index e1f6688..1f192af 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -101,34 +101,29 @@ template class slist_impl : private detail::clear_on_destructor_base < slist_impl - , is_safe_autounlink::type::link_mode>::value + , is_safe_autounlink::value > { template friend class detail::clear_on_destructor_base; //Public typedefs public: typedef ValueTraits value_traits; - /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::get_real_value_traits::type real_value_traits; - /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; typedef typename pointer_traits::element_type value_type; typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; typedef SizeType size_type; - typedef slist_iterator iterator; - typedef slist_iterator const_iterator; - typedef typename real_value_traits::node_traits node_traits; + typedef slist_iterator iterator; + typedef slist_iterator const_iterator; + typedef typename value_traits::node_traits node_traits; typedef typename node_traits::node node; typedef typename node_traits::node_ptr node_ptr; typedef typename node_traits::const_node_ptr const_node_ptr; static const bool constant_time_size = 0 != (BoolFlags & slist_bool_flags::constant_time_size_pos); - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; static const bool linear = 0 != (BoolFlags & slist_bool_flags::linear_pos); static const bool cache_last = 0 != (BoolFlags & slist_bool_flags::cache_last_pos); @@ -145,14 +140,14 @@ class slist_impl //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(slist_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink))); //Linear singly linked lists are incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(linear && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(linear && ((int)value_traits::link_mode == (int)auto_unlink))); //A list with cached last node is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(cache_last && ((int)value_traits::link_mode == (int)auto_unlink))); node_ptr get_end_node() { return node_ptr(linear ? node_ptr() : this->get_root_node()); } @@ -230,18 +225,6 @@ class slist_impl const size_traits &priv_size_traits() const { return data_.root_plus_size_; } - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } - const value_traits &priv_value_traits() const { return data_; } @@ -258,20 +241,15 @@ class slist_impl void prot_set_size(size_type s) { data_.root_plus_size_.set_size(s); } - /// @endcond - public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } + typedef typename pointer_traits::template + rebind_pointer::type const_value_traits_ptr; - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } + const_value_traits_ptr value_traits_ptr() const + { return pointer_traits::pointer_to(this->priv_value_traits()); } - typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; - - const_real_value_traits_ptr real_value_traits_ptr() const - { return pointer_traits::pointer_to(this->get_real_value_traits()); } + /// @endcond public: @@ -403,7 +381,7 @@ class slist_impl ++it; if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); } this->set_default_constructed_state(); } @@ -420,7 +398,7 @@ class slist_impl //! Note: Does not affect the validity of iterators and references. void push_front(reference value) { - node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + node_ptr to_insert = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); if(cache_last){ @@ -446,7 +424,7 @@ class slist_impl void push_back(reference value) { BOOST_STATIC_ASSERT((cache_last)); - node_ptr n = get_real_value_traits().to_node_ptr(value); + node_ptr n = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); node_algorithms::link_after(this->get_last_node(), n); @@ -485,7 +463,7 @@ class slist_impl this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); if(cache_last){ if(this->empty()){ this->set_last_node(this->get_root_node()); @@ -499,7 +477,7 @@ class slist_impl //! //! Complexity: Constant. reference front() - { return *this->get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } + { return *this->priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } //! Effects: Returns a const_reference to the first element of the list. //! @@ -507,7 +485,7 @@ class slist_impl //! //! Complexity: Constant. const_reference front() const - { return *this->get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } + { return *this->priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } //! Effects: Returns a reference to the last element of the list. //! @@ -520,7 +498,7 @@ class slist_impl reference back() { BOOST_STATIC_ASSERT((cache_last)); - return *this->get_real_value_traits().to_value_ptr(this->get_last_node()); + return *this->priv_value_traits().to_value_ptr(this->get_last_node()); } //! Effects: Returns a const_reference to the last element of the list. @@ -534,7 +512,7 @@ class slist_impl const_reference back() const { BOOST_STATIC_ASSERT((cache_last)); - return *this->get_real_value_traits().to_value_ptr(this->get_last_node()); + return *this->priv_value_traits().to_value_ptr(this->get_last_node()); } //! Effects: Returns an iterator to the first element contained in the list. @@ -543,7 +521,7 @@ class slist_impl //! //! Complexity: Constant. iterator begin() - { return iterator (node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } + { return iterator (node_traits::get_next(this->get_root_node()), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -551,7 +529,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator begin() const - { return const_iterator (node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } + { return const_iterator (node_traits::get_next(this->get_root_node()), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -559,7 +537,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator cbegin() const - { return const_iterator(node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } + { return const_iterator(node_traits::get_next(this->get_root_node()), this->value_traits_ptr()); } //! Effects: Returns an iterator to the end of the list. //! @@ -567,7 +545,7 @@ class slist_impl //! //! Complexity: Constant. iterator end() - { return iterator(this->get_end_node(), this->real_value_traits_ptr()); } + { return iterator(this->get_end_node(), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -575,7 +553,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator end() const - { return const_iterator(detail::uncast(this->get_end_node()), this->real_value_traits_ptr()); } + { return const_iterator(detail::uncast(this->get_end_node()), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -592,7 +570,7 @@ class slist_impl //! //! Complexity: Constant. iterator before_begin() - { return iterator(this->get_root_node(), this->real_value_traits_ptr()); } + { return iterator(this->get_root_node(), this->value_traits_ptr()); } //! Effects: Returns an iterator that points to a position //! before the first element. Equivalent to "end()" @@ -601,7 +579,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator before_begin() const - { return const_iterator(detail::uncast(this->get_root_node()), this->real_value_traits_ptr()); } + { return const_iterator(detail::uncast(this->get_root_node()), this->value_traits_ptr()); } //! Effects: Returns an iterator that points to a position //! before the first element. Equivalent to "end()" @@ -623,7 +601,7 @@ class slist_impl { //This function shall not be used if cache_last is not true BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last); - return iterator (this->get_last_node(), this->real_value_traits_ptr()); + return iterator (this->get_last_node(), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the last element contained in the list. @@ -637,7 +615,7 @@ class slist_impl { //This function shall not be used if cache_last is not true BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last); - return const_iterator (this->get_last_node(), this->real_value_traits_ptr()); + return const_iterator (this->get_last_node(), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the last element contained in the list. @@ -648,7 +626,7 @@ class slist_impl //! //! Note: This function is present only if cached_last<> option is true. const_iterator clast() const - { return const_iterator(this->get_last_node(), this->real_value_traits_ptr()); } + { return const_iterator(this->get_last_node(), this->value_traits_ptr()); } //! Precondition: end_iterator must be a valid end iterator //! of slist. @@ -788,7 +766,7 @@ class slist_impl //! Note: Does not affect the validity of iterators and references. iterator insert_after(const_iterator prev_p, reference value) { - node_ptr n = get_real_value_traits().to_node_ptr(value); + node_ptr n = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); node_ptr prev_n(prev_p.pointed_node()); @@ -797,7 +775,7 @@ class slist_impl this->set_last_node(n); } this->priv_size_traits().increment(); - return iterator (n, this->real_value_traits_ptr()); + return iterator (n, this->value_traits_ptr()); } //! Requires: Dereferencing iterator must yield @@ -819,7 +797,7 @@ class slist_impl size_type count = 0; node_ptr prev_n(prev_p.pointed_node()); for (; f != l; ++f, ++count){ - const node_ptr n = get_real_value_traits().to_node_ptr(*f); + const node_ptr n = priv_value_traits().to_node_ptr(*f); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); node_algorithms::link_after(prev_n, n); @@ -1026,7 +1004,7 @@ class slist_impl } if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); this->priv_size_traits().decrement(); return it.unconst(); } @@ -1045,7 +1023,7 @@ class slist_impl node_algorithms::unlink_after(prev_n); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(real_value_traits::to_value_ptr(to_erase)); + disposer(value_traits::to_value_ptr(to_erase)); return it.unconst(); } @@ -1079,7 +1057,7 @@ class slist_impl fp = node_traits::get_next(fp); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); this->priv_size_traits().decrement(); } if(cache_last && (node_traits::get_next(bfp) == this->get_end_node())){ @@ -1692,7 +1670,7 @@ class slist_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value))); - return iterator (value_traits::to_node_ptr(value), const_real_value_traits_ptr()); + return iterator (value_traits::to_node_ptr(value), const_value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1710,7 +1688,7 @@ class slist_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_value_traits_ptr()); } //! Requires: value must be a reference to a value inserted in a list. @@ -1725,7 +1703,7 @@ class slist_impl iterator iterator_to(reference value) { //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value))); - return iterator (value_traits::to_node_ptr(value), this->real_value_traits_ptr()); + return iterator (value_traits::to_node_ptr(value), this->value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1740,7 +1718,7 @@ class slist_impl const_iterator iterator_to(const_reference value) const { //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->real_value_traits_ptr()); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->value_traits_ptr()); } //! Returns: The iterator to the element before i in the list. @@ -1789,11 +1767,11 @@ class slist_impl const_iterator previous(const_iterator prev_from, const_iterator i) const { if(cache_last && (i.pointed_node() == this->get_end_node())){ - return const_iterator(detail::uncast(this->get_last_node()), this->real_value_traits_ptr()); + return const_iterator(detail::uncast(this->get_last_node()), this->value_traits_ptr()); } return const_iterator (node_algorithms::get_previous_node - (prev_from.pointed_node(), i.pointed_node()), this->real_value_traits_ptr()); + (prev_from.pointed_node(), i.pointed_node()), this->value_traits_ptr()); } ///@cond @@ -1844,8 +1822,8 @@ class slist_impl BOOST_INTRUSIVE_INVARIANT_ASSERT(n > 0); BOOST_INTRUSIVE_INVARIANT_ASSERT (size_type(std::distance - ( iterator(f, this->real_value_traits_ptr()) - , iterator(before_l, this->real_value_traits_ptr()))) + ( iterator(f, this->value_traits_ptr()) + , iterator(before_l, this->value_traits_ptr()))) +1 == n); this->priv_incorporate_after(prev_pos.pointed_node(), f, before_l); if(constant_time_size){ @@ -2171,9 +2149,8 @@ class slist Options... #endif >::type Base; - typedef typename Base::real_value_traits real_value_traits; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); BOOST_MOVABLE_BUT_NOT_COPYABLE(slist) public: diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index d754f5a..24e4c74 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -76,7 +76,6 @@ class splaytree_impl /// @cond typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType , ConstantTimeSize, SplayTreeAlgorithms> tree_type; - typedef typename tree_type::real_value_traits real_value_traits; typedef tree_type implementation_defined; /// @endcond @@ -456,10 +455,10 @@ class splaytree_impl template iterator splay_down(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); node_ptr r = node_algorithms::splay_down(tree_type::header_ptr(), key, key_node_comp); - return iterator(r, this->real_value_traits_ptr()); + return iterator(r, this->value_traits_ptr()); } //! Effects: Rearranges the container so that if *this stores an element @@ -571,14 +570,13 @@ class splaytree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit splaytree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index e3ced65..3bda6db 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -72,8 +72,8 @@ template - , public detail::ebo_functor_holder + : public bstree_impl + , public detail::ebo_functor_holder < typename get_prio < VoidOrPrioComp , typename bstree_impl @@ -87,7 +87,6 @@ class treap_impl typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType , ConstantTimeSize, BsTreeAlgorithms> tree_type; typedef tree_type implementation_defined; - typedef typename tree_type::real_value_traits real_value_traits; typedef get_prio < VoidOrPrioComp , typename tree_type::value_type> get_prio_type; @@ -96,7 +95,7 @@ class treap_impl prio_base; /// @endcond - + typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::value_type value_type; @@ -120,7 +119,7 @@ class treap_impl static const bool constant_time_size = implementation_defined::constant_time_size; static const bool stateful_value_traits = implementation_defined::stateful_value_traits; - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; /// @cond private: @@ -217,7 +216,7 @@ class treap_impl //! //! Throws: Nothing. iterator top() - { return this->empty() ? this->end() : iterator(node_traits::get_parent(this->tree_type::header_ptr()), this); } + { return this->tree_type::root(); } //! Effects: Returns a const_iterator pointing to the highest priority object of the treap.. //! @@ -233,7 +232,7 @@ class treap_impl //! //! Throws: Nothing. const_iterator ctop() const - { return this->empty() ? this->cend() : const_iterator(node_traits::get_parent(this->tree_type::header_ptr()), this); } + { return this->tree_type::root(); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::rbegin() @@ -363,15 +362,15 @@ class treap_impl //! No copy-constructors are called. iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_real_value_traits()); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->value_comp(), &this->get_value_traits()); + detail::key_nodeptr_comp + key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal_upper_bound - (this->tree_type::header_ptr(), to_insert, key_node_comp, key_node_pcomp), this->real_value_traits_ptr()); + (this->tree_type::header_ptr(), to_insert, key_node_comp, key_node_pcomp), this->value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -392,15 +391,15 @@ class treap_impl //! No copy-constructors are called. iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_real_value_traits()); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->value_comp(), &this->get_value_traits()); + detail::key_nodeptr_comp + key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret (node_algorithms::insert_equal - (this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this->real_value_traits_ptr()); + (this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this->value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -540,14 +539,14 @@ class treap_impl ( const KeyType &key, KeyValueCompare key_value_comp , KeyValuePrioCompare key_value_pcomp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_real_value_traits()); - detail::key_nodeptr_comp - pcomp(key_value_pcomp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + ocomp(key_value_comp, &this->get_value_traits()); + detail::key_nodeptr_comp + pcomp(key_value_pcomp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->tree_type::header_ptr(), key, ocomp, pcomp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } //! Requires: key_value_comp must be a comparison function that induces @@ -592,14 +591,14 @@ class treap_impl , KeyValuePrioCompare key_value_pcomp , insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_real_value_traits()); - detail::key_nodeptr_comp - pcomp(key_value_pcomp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + ocomp(key_value_comp, &this->get_value_traits()); + detail::key_nodeptr_comp + pcomp(key_value_pcomp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->tree_type::header_ptr(), hint.pointed_node(), key, ocomp, pcomp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } //! Requires: value must be an lvalue of type value_type. commit_data @@ -621,12 +620,12 @@ class treap_impl //! erased between the "insert_check" and "insert_commit" calls. iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); node_algorithms::insert_unique_commit(this->tree_type::header_ptr(), to_insert, commit_data); this->tree_type::sz_traits().increment(); - return iterator(to_insert, this->real_value_traits_ptr()); + return iterator(to_insert, this->value_traits_ptr()); } //! Requires: value must be an lvalue, "pos" must be @@ -645,13 +644,13 @@ class treap_impl //! by advanced users. iterator insert_before(const_iterator pos, reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_value_traits()); iterator ret (node_algorithms::insert_before - (this->tree_type::header_ptr(), pos.pointed_node(), to_insert, pcomp), this->real_value_traits_ptr()); + (this->tree_type::header_ptr(), pos.pointed_node(), to_insert, pcomp), this->value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -672,11 +671,11 @@ class treap_impl //! by advanced users. void push_back(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_value_traits()); node_algorithms::push_back(this->tree_type::header_ptr(), to_insert, pcomp); this->tree_type::sz_traits().increment(); } @@ -697,11 +696,11 @@ class treap_impl //! by advanced users. void push_front(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_value_traits()); node_algorithms::push_front(this->tree_type::header_ptr(), to_insert, pcomp); this->tree_type::sz_traits().increment(); } @@ -721,8 +720,8 @@ class treap_impl node_ptr to_erase(i.pointed_node()); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); node_algorithms::erase(this->tree_type::header_ptr(), to_erase, key_node_pcomp); this->tree_type::sz_traits().decrement(); if(safemode_or_autounlink) @@ -796,7 +795,7 @@ class treap_impl { node_ptr to_erase(i.pointed_node()); iterator ret(this->erase(i)); - disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->get_value_traits().to_value_ptr(to_erase)); return ret; } @@ -898,7 +897,7 @@ class treap_impl void clear_and_dispose(Disposer disposer) { node_algorithms::clear_and_dispose(this->tree_type::header_ptr() - , detail::node_disposer(disposer, &this->get_real_value_traits())); + , detail::node_disposer(disposer, &this->get_value_traits())); node_algorithms::init_header(this->tree_type::header_ptr()); this->tree_type::sz_traits().set_size(0); } @@ -1120,14 +1119,13 @@ class treap typedef typename Base::value_compare value_compare; typedef typename Base::priority_compare priority_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit treap( const value_compare &cmp = value_compare() , const priority_compare &pcmp = priority_compare() diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 6812e1a..caad0df 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -44,6 +44,7 @@ class treap_set_impl #endif { /// @cond + public: typedef treap_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_set_impl) diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index 5ba36fe..f91fc76 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -1029,15 +1029,15 @@ struct make_unordered_set typedef typename detail::get_value_traits ::type value_traits; - typedef typename make_real_bucket_traits - ::type real_bucket_traits; + typedef typename make_bucket_traits + ::type bucket_traits; typedef unordered_set_impl < value_traits , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type - , real_bucket_traits + , bucket_traits , (std::size_t(true)*hash_bool_flags::unique_keys_pos) | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) @@ -2066,15 +2066,15 @@ struct make_unordered_multiset typedef typename detail::get_value_traits ::type value_traits; - typedef typename make_real_bucket_traits - ::type real_bucket_traits; + typedef typename make_bucket_traits + ::type bucket_traits; typedef unordered_multiset_impl < value_traits , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type - , real_bucket_traits + , bucket_traits , (std::size_t(false)*hash_bool_flags::unique_keys_pos) | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) diff --git a/proj/vc7ide/Intrusive.sln b/proj/vc7ide/Intrusive.sln index 890c29e..aecfe69 100644 --- a/proj/vc7ide/Intrusive.sln +++ b/proj/vc7ide/Intrusive.sln @@ -31,10 +31,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "custom_bucket_traits", "cus 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 @@ -119,6 +115,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pack_options", "pack_option ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "container_size_test", "container_size_test\container_size_test.vcproj", "{9E721E26-45AF-192C-AD67-A4CC7D096497}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -159,10 +159,6 @@ Global {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 @@ -247,6 +243,10 @@ Global {77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.Build.0 = Debug|Win32 {77F4139B-281B-F694-7CB1-3495467B4D35}.Release.ActiveCfg = Release|Win32 {77F4139B-281B-F694-7CB1-3495467B4D35}.Release.Build.0 = Release|Win32 + {9E721E26-45AF-192C-AD67-A4CC7D096497}.Debug.ActiveCfg = Debug|Win32 + {9E721E26-45AF-192C-AD67-A4CC7D096497}.Debug.Build.0 = Debug|Win32 + {9E721E26-45AF-192C-AD67-A4CC7D096497}.Release.ActiveCfg = Release|Win32 + {9E721E26-45AF-192C-AD67-A4CC7D096497}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj index 079a8ae..fc4e758 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -364,9 +364,6 @@ - - diff --git a/proj/vc7ide/external_value_traits/external_value_traits.vcproj b/proj/vc7ide/container_size_test/container_size_test.vcproj similarity index 82% rename from proj/vc7ide/external_value_traits/external_value_traits.vcproj rename to proj/vc7ide/container_size_test/container_size_test.vcproj index 87ebd51..dad1be0 100644 --- a/proj/vc7ide/external_value_traits/external_value_traits.vcproj +++ b/proj/vc7ide/container_size_test/container_size_test.vcproj @@ -2,9 +2,8 @@ + UniqueIdentifier="{4F0C713E-750E-B78A-4373-52D2204C1ACA}"> + RelativePath="..\..\..\test\container_size_test.cpp"> diff --git a/test/container_size_test.cpp b/test/container_size_test.cpp new file mode 100644 index 0000000..d95cee5 --- /dev/null +++ b/test/container_size_test.cpp @@ -0,0 +1,187 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014 +// +// 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::intrusive; + +template +struct boolean +{ + static const bool value = Value; +}; + +template +struct pow2_and_equal_sizes +{ + static const std::size_t a_size = sizeof(A); + static const std::size_t b_size = sizeof(B); + static const bool a_b_sizes_equal = a_size == b_size; + static const bool value = !(a_size & (a_size - 1u)); +}; + +template +struct node : Hook +{}; + +//Avoid testing for uncommon architectures +void test_sizes(boolean, std::size_t) +{} + +template +void test_iterator_sizes(C &, std::size_t size) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + BOOST_TEST_EQ(sizeof(iterator), size); + BOOST_TEST_EQ(sizeof(const_iterator), size); +} + +//Test sizes for common 32 and 64 bit architectures +void test_sizes(boolean, std::size_t wordsize) +{ + { //list + list > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { + list > >, constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { //slist + slist > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { + slist > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes(c, wordsize); + } + { + slist > > , cache_last > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //set + set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*5); + test_iterator_sizes(c, wordsize); + } + { + set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + set > > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //avl + avl_set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*5); + test_iterator_sizes(c, wordsize); + } + { + avl_set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + avl_set > > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //splay + splay_set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + splay_set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //scapegoat + sg_set > > c; + BOOST_TEST_EQ(sizeof(c), (wordsize*5+sizeof(float)*2)); + test_iterator_sizes(c, wordsize); + } + { //treap + treap_set > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + treap_set > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //unordered + typedef unordered_set > > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > , power_2_buckets > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set >, constant_time_size > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > >, constant_time_size > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > >, incremental > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize*2); + } +} + +int main() +{ + test_sizes(boolean< pow2_and_equal_sizes::value >(), sizeof(std::size_t)); + return ::boost::report_errors(); +} + +#include diff --git a/test/external_value_traits_test.cpp b/test/external_value_traits_test.cpp deleted file mode 100644 index 60efc9d..0000000 --- a/test/external_value_traits_test.cpp +++ /dev/null @@ -1,241 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-2013 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/intrusive for documentation. -// -///////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include - -using namespace boost::intrusive; - -class MyClass -{ - public: - int int_; - - MyClass(int i = 0) - : int_(i) - {} - 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 &v) - { return boost::hash_value(v.int_); } -}; - -const int NumElements = 100; - -template -struct external_traits -{ - typedef NodeTraits node_traits; - typedef typename node_traits::node node; - typedef typename node_traits::node_ptr node_ptr; - typedef typename node_traits::const_node_ptr const_node_ptr; - typedef MyClass value_type; - typedef typename pointer_traits:: - template rebind_pointer::type pointer; - typedef typename pointer_traits:: - template rebind_pointer - ::type const_pointer; - static const link_mode_type link_mode = normal_link; - - external_traits(pointer values, std::size_t NumElem) - : values_(values), node_array_(NumElem) - {} - - node_ptr to_node_ptr (value_type &value) - { return (&node_array_[0]) + (&value - values_); } - - const_node_ptr to_node_ptr (const value_type &value) const - { return &node_array_[0] + (&value - values_); } - - pointer to_value_ptr(node_ptr n) - { return values_ + (n - &node_array_[0]); } - - const_pointer to_value_ptr(const_node_ptr n) const - { return values_ + (n - &node_array_[0]); } - - pointer values_; - std::vector node_array_; -}; - -template -struct value_traits_proxy; - -template -struct traits_holder - : public T -{}; - -typedef value_traits_proxy > list_value_traits_proxy; -typedef value_traits_proxy > slist_value_traits_proxy; -typedef value_traits_proxy > rbtree_value_traits_proxy; -typedef value_traits_proxy > > hash_value_traits_proxy; - -struct uset_bucket_traits -{ - private: - typedef unordered_bucket > > > >::type bucket_type; - - //Non-copyable - uset_bucket_traits(const uset_bucket_traits &other); - uset_bucket_traits & operator=(const uset_bucket_traits &other); - - public: - static const std::size_t NumBuckets = 100; - - uset_bucket_traits(){} - - bucket_type * bucket_begin() const - { return buckets_; } - - std::size_t bucket_count() const - { return NumBuckets; } - - mutable bucket_type buckets_[NumBuckets]; -}; - -struct bucket_traits_proxy -{ - static const bool external_bucket_traits = true; - typedef uset_bucket_traits bucket_traits; - - template - bucket_traits &get_bucket_traits(Container &cont); - - template - const bucket_traits &get_bucket_traits(const Container &cont) const; -}; - -//Define a list that will store MyClass using the external hook -typedef list > List; -//Define a slist that will store MyClass using the external hook -typedef slist > Slist; -//Define a rbtree that will store MyClass using the external hook -typedef rbtree< MyClass - , value_traits - , compare > > Rbtree; -//Define a hashtable that will store MyClass using the external hook - -typedef hashtable< MyClass - , value_traits - , bucket_traits - > Hash; - -template -struct value_traits_proxy -{ - static const bool external_value_traits = true; - typedef external_traits value_traits; - - template - const value_traits &get_value_traits(const Container &cont) const; - - template - value_traits &get_value_traits(Container &cont); -}; - -struct ContainerHolder - : public uset_bucket_traits - , public List - , public external_traits > - , public Slist - , public external_traits > - , public Rbtree - , public external_traits > - , public Hash - , public external_traits > > -{ - static const std::size_t NumBucket = 100; - ContainerHolder(MyClass *values, std::size_t num_elem) - : uset_bucket_traits() - , List() - , external_traits >(values, num_elem) - , Slist() - , external_traits >(values, num_elem) - , Rbtree() - , external_traits >(values, num_elem) - , Hash(Hash::bucket_traits()) - , external_traits > >(values, num_elem) - {} -}; - -template -template -typename value_traits_proxy::value_traits & - value_traits_proxy::get_value_traits(Container &cont) -{ return static_cast(static_cast(cont)); } - -template -template -const typename value_traits_proxy::value_traits & - value_traits_proxy::get_value_traits(const Container &cont) const -{ return static_cast(static_cast(cont)); } - -template -typename bucket_traits_proxy::bucket_traits & - bucket_traits_proxy::get_bucket_traits(Container &cont) -{ return static_cast(static_cast(cont)); } - -template -const typename bucket_traits_proxy::bucket_traits & - bucket_traits_proxy::get_bucket_traits(const Container &cont) const -{ return static_cast(static_cast(cont)); } - -int main() -{ - MyClass values [NumElements]; - //Create several MyClass objects, each one with a different value - for(int i = 0; i < NumElements; ++i) - values[i].int_ = i; - - ContainerHolder cont_holder(values, NumElements); - List &my_list = static_cast (cont_holder); - Slist &my_slist = static_cast (cont_holder); - Rbtree &my_rbtree = static_cast (cont_holder); - Hash &my_hash = static_cast (cont_holder); - - //Now insert them in containers - for(MyClass * it(&values[0]), *itend(&values[NumElements]) - ; it != itend; ++it){ - my_list.push_front(*it); - my_slist.push_front(*it); - my_rbtree.insert_unique(*it); - my_hash.insert_unique(*it); - } - - //Now test containers - { - List::const_iterator list_it (my_list.cbegin()); - Slist::const_iterator slist_it (my_slist.cbegin()); - Rbtree::const_iterator rbtree_it (my_rbtree.cbegin()); - Hash::const_iterator hash_it (my_hash.cbegin()); - MyClass *it_val(&values[NumElements] - 1), *it_rbeg_val(&values[0]-1); - - //Test inserted objects - for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++rbtree_it){ - if(&*list_it != &*it_val) return 1; - if(&*slist_it != &*it_val) return 1; - if(&*rbtree_it != &*it_val) return 1; - hash_it = my_hash.find(*it_val); - if(hash_it == my_hash.cend() || &*hash_it != &*it_val) - return 1; - } - } - - return 0; -} From c1fdae5eb46ccddc08c0666cac069e63ff1091a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 6 Feb 2014 11:10:47 +0100 Subject: [PATCH 18/18] Optimized tree-rebalancing code to avoid redundant pointer updates. --- doc/intrusive.qbk | 2 + .../boost/intrusive/avltree_algorithms.hpp | 207 +++++++---- include/boost/intrusive/bstree_algorithms.hpp | 351 +++++++++--------- include/boost/intrusive/rbtree_algorithms.hpp | 144 +++---- .../boost/intrusive/splaytree_algorithms.hpp | 8 +- include/boost/intrusive/treap_algorithms.hpp | 43 +-- 6 files changed, 389 insertions(+), 366 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index f1dba96..a7b15ac 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3797,6 +3797,8 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std * Fixed bugs: * [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]]. +* Optimized tree rebalancing code to avoid redundant assignments. + [endsect] [section:release_notes_boost_1_55_00 Boost 1.55 Release] diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 31777d7..e6127b8 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -49,15 +49,6 @@ struct avltree_node_cloner } }; -template -struct avltree_erase_fixup -{ - typedef typename NodeTraits::node_ptr node_ptr; - - void operator()(const node_ptr & to_erase, const node_ptr & successor) - { NodeTraits::set_balance(successor, NodeTraits::get_balance(to_erase)); } -}; - /// @endcond //! avltree_algorithms is configured with a NodeTraits class, which encapsulates the @@ -225,7 +216,10 @@ class avltree_algorithms static node_ptr erase(const node_ptr & header, const node_ptr & z) { typename bstree_algo::data_for_rebalance info; - bstree_algo::erase(header, z, avltree_erase_fixup(), info); + bstree_algo::erase(header, z, info); + if(info.y != z){ + NodeTraits::set_balance(info.y, NodeTraits::get_balance(z)); + } //Rebalance avltree rebalance_after_erasure(header, info.x, info.x_parent); return z; @@ -358,41 +352,92 @@ class avltree_algorithms /// @cond + static bool verify(const node_ptr &header) + { + std::size_t height; + std::size_t count; + return verify_recursion(NodeTraits::get_parent(header), count, height); + } + private: - static void rebalance_after_erasure(const node_ptr & header, const node_ptr & xnode, const node_ptr & xnode_parent) + static bool verify_recursion(node_ptr n, std::size_t &count, std::size_t &height) + { + if (!n){ + count = 0; + height = 0; + return true; + } + std::size_t leftcount, rightcount; + std::size_t leftheight, rightheight; + if(!verify_recursion(NodeTraits::get_left (n), leftcount, leftheight) || + !verify_recursion(NodeTraits::get_right(n), rightcount, rightheight) ){ + return false; + } + count = 1u + leftcount + rightcount; + height = 1u + (leftheight > rightheight ? leftheight : rightheight); + + //If equal height, balance must be zero + if(rightheight == leftheight){ + if(NodeTraits::get_balance(n) != NodeTraits::zero()){ + BOOST_ASSERT(0); + return false; + } + } + //If right is taller than left, then the difference must be at least 1 and the balance positive + else if(rightheight > leftheight){ + if(rightheight - leftheight > 1 ){ + BOOST_ASSERT(0); + return false; + } + else if(NodeTraits::get_balance(n) != NodeTraits::positive()){ + BOOST_ASSERT(0); + return false; + } + } + //If left is taller than right, then the difference must be at least 1 and the balance negative + else{ + if(leftheight - rightheight > 1 ){ + BOOST_ASSERT(0); + return false; + } + else if(NodeTraits::get_balance(n) != NodeTraits::negative()){ + BOOST_ASSERT(0); + return false; + } + } + return true; + } + + static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent) { - node_ptr x(xnode), x_parent(xnode_parent); for (node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)) { const balance x_parent_balance = NodeTraits::get_balance(x_parent); - node_ptr const x_parent_left(NodeTraits::get_left(x_parent)); + //Don't cache x_is_leftchild or similar because x can be null and + //equal to both x_parent_left and x_parent_right + const node_ptr x_parent_left (NodeTraits::get_left(x_parent)); + const node_ptr x_parent_right(NodeTraits::get_right(x_parent)); + if(x_parent_balance == NodeTraits::zero()){ - NodeTraits::set_balance( x_parent - , x == x_parent_left ? NodeTraits::positive() : NodeTraits::negative() ); + NodeTraits::set_balance( x_parent, x == x_parent_right ? NodeTraits::negative() : NodeTraits::positive() ); break; // the height didn't change, let's stop here } else if(x_parent_balance == NodeTraits::negative()){ - if (x == x_parent_left) { + if (x == x_parent_left) { ////x is left child or x and sibling are null NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced x = x_parent; - x_parent = NodeTraits::get_parent(x_parent); } else { - // x is right child - // a is left child - node_ptr a = x_parent_left; - BOOST_INTRUSIVE_INVARIANT_ASSERT(a); - if (NodeTraits::get_balance(a) == NodeTraits::positive()) { - // a MUST have a right child - BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(a)); - rotate_left_right(x_parent, header); - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + // x is right child (x_parent_left is the left child) + BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_left); + if (NodeTraits::get_balance(x_parent_left) == NodeTraits::positive()) { + // x_parent_left MUST have a right child + BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(x_parent_left)); + x = avl_rotate_left_right(x_parent, x_parent_left, header); } else { - rotate_right(x_parent, header); - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + avl_rotate_right(x_parent, x_parent_left, header); + x = x_parent_left; } // if changed from negative to NodeTraits::positive(), no need to check above @@ -402,28 +447,22 @@ class avltree_algorithms } } else if(x_parent_balance == NodeTraits::positive()){ - if (x == NodeTraits::get_right(x_parent)) { + if (x == x_parent_right) { //x is right child or x and sibling are null NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced x = x_parent; - x_parent = NodeTraits::get_parent(x_parent); } else { - // x is left child - // a is right child - node_ptr a = NodeTraits::get_right(x_parent); - BOOST_INTRUSIVE_INVARIANT_ASSERT(a); - if (NodeTraits::get_balance(a) == NodeTraits::negative()) { - // a MUST have then a left child - BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(a)); - rotate_right_left(x_parent, header); - - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + // x is left child (x_parent_right is the right child) + const node_ptr x_parent_right(NodeTraits::get_right(x_parent)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_right); + if (NodeTraits::get_balance(x_parent_right) == NodeTraits::negative()) { + // x_parent_right MUST have then a left child + BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(x_parent_right)); + x = avl_rotate_right_left(x_parent, x_parent_right, header); } else { - rotate_left(x_parent, header); - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + avl_rotate_left(x_parent, x_parent_right, header); + x = x_parent_right; } // if changed from NodeTraits::positive() to negative, no need to check above if (NodeTraits::get_balance(x) == NodeTraits::negative()){ @@ -434,44 +473,44 @@ class avltree_algorithms else{ BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached } + x_parent = NodeTraits::get_parent(x); } } - static void rebalance_after_insertion(const node_ptr & header, const node_ptr & xnode) + static void rebalance_after_insertion(const node_ptr & header, node_ptr x) { - node_ptr x(xnode); NodeTraits::set_balance(x, NodeTraits::zero()); // Rebalance. for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){ node_ptr const x_parent(NodeTraits::get_parent(x)); node_ptr const x_parent_left(NodeTraits::get_left(x_parent)); const balance x_parent_balance = NodeTraits::get_balance(x_parent); + const bool x_is_leftchild(x == x_parent_left); if(x_parent_balance == NodeTraits::zero()){ // if x is left, parent will have parent->bal_factor = negative // else, parent->bal_factor = NodeTraits::positive() - NodeTraits::set_balance( x_parent, x == x_parent_left - ? NodeTraits::negative() : NodeTraits::positive() ); + NodeTraits::set_balance( x_parent, x_is_leftchild ? NodeTraits::negative() : NodeTraits::positive() ); x = x_parent; } else if(x_parent_balance == NodeTraits::positive()){ // if x is a left child, parent->bal_factor = zero - if (x == x_parent_left) + if (x_is_leftchild) NodeTraits::set_balance(x_parent, NodeTraits::zero()); else{ // x is a right child, needs rebalancing if (NodeTraits::get_balance(x) == NodeTraits::negative()) - rotate_right_left(x_parent, header); + avl_rotate_right_left(x_parent, x, header); else - rotate_left(x_parent, header); + avl_rotate_left(x_parent, x, header); } break; } else if(x_parent_balance == NodeTraits::negative()){ // if x is a left child, needs rebalancing - if (x == x_parent_left) { + if (x_is_leftchild) { if (NodeTraits::get_balance(x) == NodeTraits::positive()) - rotate_left_right(x_parent, header); + avl_rotate_left_right(x_parent, x, header); else - rotate_right(x_parent, header); + avl_rotate_right(x_parent, x, header); } else NodeTraits::set_balance(x_parent, NodeTraits::zero()); @@ -508,8 +547,8 @@ class avltree_algorithms } } - static void rotate_left_right(const node_ptr a, const node_ptr & hdr) - { + static node_ptr avl_rotate_left_right(const node_ptr a, const node_ptr a_oldleft, const node_ptr & hdr) + { // [note: 'a_oldleft' is 'b'] // | | // // a(-2) c // // / \ / \ // @@ -517,16 +556,19 @@ class avltree_algorithms // (pos)b [g] b a // // / \ / \ / \ // // [d] c [d] e f [g] // - // / \ // - // e f // - node_ptr b = NodeTraits::get_left(a), c = NodeTraits::get_right(b); - bstree_algo::rotate_left(b, hdr); - bstree_algo::rotate_right(a, hdr); - left_right_balancing(a, b, c); + // / \ // + // e f // + const node_ptr c = NodeTraits::get_right(a_oldleft); + bstree_algo::rotate_left_no_parent_fix(a_oldleft, c); + //No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_left(a, c)] + //as c is not root and another rotation is coming + bstree_algo::rotate_right(a, c, NodeTraits::get_parent(a), hdr); + left_right_balancing(a, a_oldleft, c); + return c; } - static void rotate_right_left(const node_ptr a, const node_ptr & hdr) - { + static node_ptr avl_rotate_right_left(const node_ptr a, const node_ptr a_oldright, const node_ptr & hdr) + { // [note: 'a_oldright' is 'b'] // | | // // a(pos) c // // / \ / \ // @@ -536,41 +578,42 @@ class avltree_algorithms // c [g] [d] e f [g] // // / \ // // e f // - node_ptr b = NodeTraits::get_right(a), c = NodeTraits::get_left(b); - bstree_algo::rotate_right(b, hdr); - bstree_algo::rotate_left(a, hdr); - left_right_balancing(b, a, c); + const node_ptr c (NodeTraits::get_left(a_oldright)); + bstree_algo::rotate_right_no_parent_fix(a_oldright, c); + //No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_right(a, c)] + //as c is not root and another rotation is coming. + bstree_algo::rotate_left(a, c, NodeTraits::get_parent(a), hdr); + left_right_balancing(a_oldright, a, c); + return c; } - static void rotate_left(const node_ptr x, const node_ptr & hdr) + static void avl_rotate_left(const node_ptr &x, const node_ptr &x_oldright, const node_ptr & hdr) { - const node_ptr y = NodeTraits::get_right(x); - bstree_algo::rotate_left(x, hdr); + bstree_algo::rotate_left(x, x_oldright, NodeTraits::get_parent(x), hdr); // reset the balancing factor - if (NodeTraits::get_balance(y) == NodeTraits::positive()) { + if (NodeTraits::get_balance(x_oldright) == NodeTraits::positive()) { NodeTraits::set_balance(x, NodeTraits::zero()); - NodeTraits::set_balance(y, NodeTraits::zero()); + NodeTraits::set_balance(x_oldright, NodeTraits::zero()); } else { // this doesn't happen during insertions NodeTraits::set_balance(x, NodeTraits::positive()); - NodeTraits::set_balance(y, NodeTraits::negative()); + NodeTraits::set_balance(x_oldright, NodeTraits::negative()); } } - static void rotate_right(const node_ptr x, const node_ptr & hdr) + static void avl_rotate_right(const node_ptr &x, const node_ptr &x_oldleft, const node_ptr & hdr) { - const node_ptr y = NodeTraits::get_left(x); - bstree_algo::rotate_right(x, hdr); + bstree_algo::rotate_right(x, x_oldleft, NodeTraits::get_parent(x), hdr); // reset the balancing factor - if (NodeTraits::get_balance(y) == NodeTraits::negative()) { + if (NodeTraits::get_balance(x_oldleft) == NodeTraits::negative()) { NodeTraits::set_balance(x, NodeTraits::zero()); - NodeTraits::set_balance(y, NodeTraits::zero()); + NodeTraits::set_balance(x_oldleft, NodeTraits::zero()); } else { // this doesn't happen during insertions NodeTraits::set_balance(x, NodeTraits::negative()); - NodeTraits::set_balance(y, NodeTraits::positive()); + NodeTraits::set_balance(x_oldleft, NodeTraits::positive()); } } diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index e7f034b..0a7cef0 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -549,7 +549,7 @@ class bstree_algorithms //! Complexity: Logarithmic to the size of the subtree. //! //! Throws: Nothing. - static node_ptr minimum (node_ptr node) + static node_ptr minimum(node_ptr node) { for(node_ptr p_left = NodeTraits::get_left(node) ;p_left @@ -1062,16 +1062,12 @@ class bstree_algorithms //Since we've found the upper bound there is no other value with the same key if: // - There is no previous node // - The previous node is less than the key - if(!prev || comp(prev, key)){ + const bool not_present = !prev || comp(prev, key); + if(not_present){ commit_data.link_left = left_child; commit_data.node = y; - return std::pair(node_ptr(), true); - } - //If the previous value was not less than key, it means that it's equal - //(because we've checked the upper bound) - else{ - return std::pair(prev, false); } + return std::pair(prev, not_present); } //! Requires: "header" must be the header node of a tree. @@ -1362,7 +1358,7 @@ class bstree_algorithms static void erase(const node_ptr & header, const node_ptr & z) { data_for_rebalance ignored; - erase_impl(header, z, ignored); + erase(header, z, ignored); } //! Requires: node is a tree node but not the header. @@ -1447,6 +1443,88 @@ class bstree_algorithms } protected: + static void erase(const node_ptr & header, const node_ptr & z, data_for_rebalance &info) + { + node_ptr y(z); + node_ptr x; + const node_ptr z_left(NodeTraits::get_left(z)); + const node_ptr z_right(NodeTraits::get_right(z)); + + if(!z_left){ + x = z_right; // x might be null. + } + else if(!z_right){ // z has exactly one non-null child. y == z. + x = z_left; // x is not null. + BOOST_ASSERT(x); + } + else{ //make y != z + // y = find z's successor + y = bstree_algorithms::minimum(z_right); + x = NodeTraits::get_right(y); // x might be null. + } + + node_ptr x_parent; + const node_ptr z_parent(NodeTraits::get_parent(z)); + const bool z_is_leftchild(NodeTraits::get_left(z_parent) == z); + + if(y != z){ //has two children and y is the minimum of z + //y is z's successor and it has a null left child. + //x is the right child of y (it can be null) + //Relink y in place of z and link x with y's old parent + NodeTraits::set_parent(z_left, y); + NodeTraits::set_left(y, z_left); + if(y != z_right){ + //Link y with the right tree of z + NodeTraits::set_right(y, z_right); + NodeTraits::set_parent(z_right, y); + //Link x with y's old parent (y must be a left child) + x_parent = NodeTraits::get_parent(y); + BOOST_ASSERT(NodeTraits::get_left(x_parent) == y); + if(x) + NodeTraits::set_parent(x, x_parent); + //Since y was the successor and not the right child of z, it must be a left child + NodeTraits::set_left(x_parent, x); + } + else{ //y was the right child of y so no need to fix x's position + x_parent = y; + } + NodeTraits::set_parent(y, z_parent); + bstree_algorithms::set_child(header, y, z_parent, z_is_leftchild); + } + else { // z has zero or one child, x is one child (it can be null) + //Just link x to z's parent + x_parent = z_parent; + if(x) + NodeTraits::set_parent(x, z_parent); + bstree_algorithms::set_child(header, x, z_parent, z_is_leftchild); + + //Now update leftmost/rightmost in case z was one of them + if(NodeTraits::get_left(header) == z){ + //z_left must be null because z is the leftmost + BOOST_ASSERT(!z_left); + NodeTraits::set_left(header, !z_right ? + z_parent : // makes leftmost == header if z == root + bstree_algorithms::minimum(z_right)); + } + if(NodeTraits::get_right(header) == z){ + //z_right must be null because z is the rightmost + BOOST_ASSERT(!z_right); + NodeTraits::set_right(header, !z_left ? + z_parent : // makes rightmost == header if z == root + bstree_algorithms::maximum(z_left)); + } + } + + //If z had 0/1 child, y == z and one of its children (and maybe null) + //If z had 2 children, y is the successor of z and x is the right child of y + info.x = x; + info.y = y; + //If z had 0/1 child, x_parent is the new parent of the old right child of y (z's successor) + //If z had 2 children, x_parent is the new parent of y (z_parent) + BOOST_ASSERT(!x || NodeTraits::get_parent(x) == x_parent); + info.x_parent = x_parent; + } + //! Requires: node is a node of the tree but it's not the header. //! //! Effects: Returns the number of nodes of the subtree. @@ -1510,83 +1588,6 @@ class bstree_algorithms static bool is_right_child(const node_ptr & p) { return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; } - template - static void erase(const node_ptr & header, const node_ptr & z, F z_and_successor_fixup, data_for_rebalance &info) - { - erase_impl(header, z, info); - if(info.y != z){ - z_and_successor_fixup(z, info.y); - } - } - - //Fix header and own's parent data when replacing x with own, providing own's old data with parent - static void replace_own_impl(const node_ptr & own, const node_ptr & x, const node_ptr & header, const node_ptr & own_parent, bool own_was_left) - { - if(NodeTraits::get_parent(header) == own) - NodeTraits::set_parent(header, x); - else if(own_was_left) - NodeTraits::set_left(own_parent, x); - else - NodeTraits::set_right(own_parent, x); - } - - //Fix header and own's parent data when replacing x with own, supposing own - //links with its parent are still ok - static void replace_own(const node_ptr & own, const node_ptr & x, const node_ptr & header) - { - node_ptr own_parent(NodeTraits::get_parent(own)); - bool own_is_left(NodeTraits::get_left(own_parent) == own); - replace_own_impl(own, x, header, own_parent, own_is_left); - } - - // rotate parent p to left (no header and p's parent fixup) - static node_ptr rotate_left(const node_ptr & p) - { - node_ptr x(NodeTraits::get_right(p)); - node_ptr x_left(NodeTraits::get_left(x)); - NodeTraits::set_right(p, x_left); - if(x_left){ - NodeTraits::set_parent(x_left, p); - } - NodeTraits::set_left(x, p); - NodeTraits::set_parent(p, x); - return x; - } - - // rotate parent p to left (with header and p's parent fixup) - static void rotate_left(const node_ptr & p, const node_ptr & header) - { - bool p_was_left(is_left_child(p)); - node_ptr p_old_parent(NodeTraits::get_parent(p)); - node_ptr x(rotate_left(p)); - NodeTraits::set_parent(x, p_old_parent); - replace_own_impl(p, x, header, p_old_parent, p_was_left); - } - - // rotate parent p to right (no header and p's parent fixup) - static node_ptr rotate_right(const node_ptr & p) - { - node_ptr x(NodeTraits::get_left(p)); - node_ptr x_right(NodeTraits::get_right(x)); - NodeTraits::set_left(p, x_right); - if(x_right){ - NodeTraits::set_parent(x_right, p); - } - NodeTraits::set_right(x, p); - NodeTraits::set_parent(p, x); - return x; - } - - // rotate parent p to right (with header and p's parent fixup) - static void rotate_right(const node_ptr & p, const node_ptr & header) - { - bool p_was_left(is_left_child(p)); - node_ptr p_old_parent(NodeTraits::get_parent(p)); - node_ptr x(rotate_right(p)); - NodeTraits::set_parent(x, p_old_parent); - replace_own_impl(p, x, header, p_old_parent, p_was_left); - } - static void insert_before_check (const node_ptr &header, const node_ptr & pos , insert_commit_data &commit_data @@ -1668,12 +1669,40 @@ class bstree_algorithms template static void insert_equal_upper_bound_check (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) - { insert_equal_check_impl(true, h, new_node, comp, commit_data, pdepth); } + { + std::size_t depth = 0; + node_ptr y(h); + node_ptr x(NodeTraits::get_parent(y)); + + while(x){ + ++depth; + y = x; + x = comp(new_node, x) ? + NodeTraits::get_left(x) : NodeTraits::get_right(x); + } + if(pdepth) *pdepth = depth; + commit_data.link_left = (y == h) || comp(new_node, y); + commit_data.node = y; + } template static void insert_equal_lower_bound_check (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) - { insert_equal_check_impl(false, h, new_node, comp, commit_data, pdepth); } + { + std::size_t depth = 0; + node_ptr y(h); + node_ptr x(NodeTraits::get_parent(y)); + + while(x){ + ++depth; + y = x; + x = !comp(x, new_node) ? + NodeTraits::get_left(x) : NodeTraits::get_right(x); + } + if(pdepth) *pdepth = depth; + commit_data.link_left = (y == h) || !comp(y, new_node); + commit_data.node = y; + } static void insert_commit (const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data) @@ -1701,7 +1730,61 @@ class bstree_algorithms NodeTraits::set_left(new_node, node_ptr()); } + //Fix header and own's parent data when replacing x with own, providing own's old data with parent + static void set_child(const node_ptr & header, const node_ptr & new_child, const node_ptr & new_parent, const bool link_left) + { + if(new_parent == header) + NodeTraits::set_parent(header, new_child); + else if(link_left) + NodeTraits::set_left(new_parent, new_child); + else + NodeTraits::set_right(new_parent, new_child); + } + + // rotate p to left (no header and p's parent fixup) + static void rotate_left_no_parent_fix(const node_ptr & p, const node_ptr &p_right) + { + node_ptr p_right_left(NodeTraits::get_left(p_right)); + NodeTraits::set_right(p, p_right_left); + if(p_right_left){ + NodeTraits::set_parent(p_right_left, p); + } + NodeTraits::set_left(p_right, p); + NodeTraits::set_parent(p, p_right); + } + + // rotate p to left (with header and p's parent fixup) + static void rotate_left(const node_ptr & p, const node_ptr & p_right, const node_ptr & p_parent, const node_ptr & header) + { + const bool p_was_left(NodeTraits::get_left(p_parent) == p); + rotate_left_no_parent_fix(p, p_right); + NodeTraits::set_parent(p_right, p_parent); + set_child(header, p_right, p_parent, p_was_left); + } + + // rotate p to right (no header and p's parent fixup) + static void rotate_right_no_parent_fix(const node_ptr & p, const node_ptr &p_left) + { + node_ptr p_left_right(NodeTraits::get_right(p_left)); + NodeTraits::set_left(p, p_left_right); + if(p_left_right){ + NodeTraits::set_parent(p_left_right, p); + } + NodeTraits::set_right(p_left, p); + NodeTraits::set_parent(p, p_left); + } + + // rotate p to right (with header and p's parent fixup) + static void rotate_right(const node_ptr & p, const node_ptr & p_left, const node_ptr & p_parent, const node_ptr & header) + { + const bool p_was_left(NodeTraits::get_left(p_parent) == p); + rotate_right_no_parent_fix(p, p_left); + NodeTraits::set_parent(p_left, p_parent); + set_child(header, p_left, p_parent, p_was_left); + } + private: + static void subtree_to_vine(node_ptr vine_tail, std::size_t &size) { //Inspired by LibAVL: @@ -1913,98 +1996,6 @@ class bstree_algorithms } return y; } - - - template - static void insert_equal_check_impl - (bool upper, const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) - { - std::size_t depth = 0; - node_ptr y(h); - node_ptr x(NodeTraits::get_parent(y)); - bool link_left; - - if(upper){ - while(x){ - ++depth; - y = x; - x = comp(new_node, x) ? - NodeTraits::get_left(x) : NodeTraits::get_right(x); - } - link_left = (y == h) || comp(new_node, y); - } - else{ - while(x){ - ++depth; - y = x; - x = !comp(x, new_node) ? - NodeTraits::get_left(x) : NodeTraits::get_right(x); - } - link_left = (y == h) || !comp(y, new_node); - } - - commit_data.link_left = link_left; - commit_data.node = y; - if(pdepth) *pdepth = depth; - } - - static void erase_impl(const node_ptr & header, const node_ptr & z, data_for_rebalance &info) - { - node_ptr y(z); - node_ptr x; - node_ptr x_parent = node_ptr(); - node_ptr z_left(NodeTraits::get_left(z)); - node_ptr z_right(NodeTraits::get_right(z)); - if(!z_left){ - x = z_right; // x might be null. - } - else if(!z_right){ // z has exactly one non-null child. y == z. - x = z_left; // x is not null. - } - else{ - // find z's successor - y = bstree_algorithms::minimum (z_right); - x = NodeTraits::get_right(y); // x might be null. - } - - if(y != z){ - // relink y in place of z. y is z's successor - NodeTraits::set_parent(NodeTraits::get_left(z), y); - NodeTraits::set_left(y, NodeTraits::get_left(z)); - if(y != NodeTraits::get_right(z)){ - x_parent = NodeTraits::get_parent(y); - if(x) - NodeTraits::set_parent(x, x_parent); - NodeTraits::set_left(x_parent, x); // y must be a child of left_ - NodeTraits::set_right(y, NodeTraits::get_right(z)); - NodeTraits::set_parent(NodeTraits::get_right(z), y); - } - else - x_parent = y; - bstree_algorithms::replace_own (z, y, header); - NodeTraits::set_parent(y, NodeTraits::get_parent(z)); - } - else { // y == z --> z has only one child, or void - x_parent = NodeTraits::get_parent(z); - if(x) - NodeTraits::set_parent(x, x_parent); - bstree_algorithms::replace_own (z, x, header); - if(NodeTraits::get_left(header) == z){ - NodeTraits::set_left(header, !NodeTraits::get_right(z) ? // z->get_left() must be null also - NodeTraits::get_parent(z) : // makes leftmost == header if z == root - bstree_algorithms::minimum (x)); - } - if(NodeTraits::get_right(header) == z){ - NodeTraits::set_right(header, !NodeTraits::get_left(z) ? // z->get_right() must be null also - NodeTraits::get_parent(z) : // makes rightmost == header if z == root - bstree_algorithms::maximum(x)); - } - } - - info.x = x; - info.x_parent = x_parent; - info.y = y; - } }; /// @cond diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 457df31..0c1225e 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -57,21 +57,6 @@ struct rbtree_node_cloner } }; -template -struct rbtree_erase_fixup -{ - typedef typename NodeTraits::node_ptr node_ptr; - typedef typename NodeTraits::color color; - - void operator()(const node_ptr & to_erase, const node_ptr & successor) - { - //Swap color of y and z - color tmp(NodeTraits::get_color(successor)); - NodeTraits::set_color(successor, NodeTraits::get_color(to_erase)); - NodeTraits::set_color(to_erase, tmp); - } -}; - #endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! rbtree_algorithms provides basic algorithms to manipulate @@ -245,10 +230,18 @@ class rbtree_algorithms static node_ptr erase(const node_ptr & header, const node_ptr & z) { typename bstree_algo::data_for_rebalance info; - bstree_algo::erase(header, z, rbtree_erase_fixup(), info); + bstree_algo::erase(header, z, info); - //Rebalance rbtree - if(NodeTraits::get_color(z) != NodeTraits::red()){ + color new_z_color; + if(info.y != z){ + new_z_color = NodeTraits::get_color(info.y); + NodeTraits::set_color(info.y, NodeTraits::get_color(z)); + } + else{ + new_z_color = NodeTraits::get_color(z); + } + //Rebalance rbtree if needed + if(new_z_color != NodeTraits::red()){ rebalance_after_erasure(header, info.x, info.x_parent); } return z; @@ -387,14 +380,20 @@ class rbtree_algorithms static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent) { - while(x != NodeTraits::get_parent(header) && (!x || NodeTraits::get_color(x) == NodeTraits::black())){ - if(x == NodeTraits::get_left(x_parent)){ + while(1){ + if(x_parent == header || (x && NodeTraits::get_color(x) != NodeTraits::black())){ + break; + } + //Don't cache x_is_leftchild or similar because x can be null and + //equal to both x_parent_left and x_parent_right + const node_ptr x_parent_left(NodeTraits::get_left(x_parent)); + if(x == x_parent_left){ //x is left child node_ptr w = NodeTraits::get_right(x_parent); BOOST_ASSERT(w); if(NodeTraits::get_color(w) == NodeTraits::red()){ NodeTraits::set_color(w, NodeTraits::black()); NodeTraits::set_color(x_parent, NodeTraits::red()); - bstree_algo::rotate_left(x_parent, header); + bstree_algo::rotate_left(x_parent, w, NodeTraits::get_parent(x_parent), header); w = NodeTraits::get_right(x_parent); } node_ptr const w_left (NodeTraits::get_left(w)); @@ -407,26 +406,27 @@ class rbtree_algorithms } else { if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){ - NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); + NodeTraits::set_color(w_left, NodeTraits::black()); NodeTraits::set_color(w, NodeTraits::red()); - bstree_algo::rotate_right(w, header); + bstree_algo::rotate_right(w, w_left, NodeTraits::get_parent(w), header); w = NodeTraits::get_right(x_parent); } NodeTraits::set_color(w, NodeTraits::get_color(x_parent)); NodeTraits::set_color(x_parent, NodeTraits::black()); - if(NodeTraits::get_right(w)) - NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); - bstree_algo::rotate_left(x_parent, header); + const node_ptr new_wright(NodeTraits::get_right(w)); + if(new_wright) + NodeTraits::set_color(new_wright, NodeTraits::black()); + bstree_algo::rotate_left(x_parent, NodeTraits::get_right(x_parent), NodeTraits::get_parent(x_parent), header); break; } } else { // same as above, with right_ <-> left_. - node_ptr w = NodeTraits::get_left(x_parent); + node_ptr w = x_parent_left; if(NodeTraits::get_color(w) == NodeTraits::red()){ NodeTraits::set_color(w, NodeTraits::black()); NodeTraits::set_color(x_parent, NodeTraits::red()); - bstree_algo::rotate_right(x_parent, header); + bstree_algo::rotate_right(x_parent, w, NodeTraits::get_parent(x_parent), header); w = NodeTraits::get_left(x_parent); } node_ptr const w_left (NodeTraits::get_left(w)); @@ -439,16 +439,17 @@ class rbtree_algorithms } else { if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){ - NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); + NodeTraits::set_color(w_right, NodeTraits::black()); NodeTraits::set_color(w, NodeTraits::red()); - bstree_algo::rotate_left(w, header); + bstree_algo::rotate_left(w, w_right, NodeTraits::get_parent(w), header); w = NodeTraits::get_left(x_parent); } NodeTraits::set_color(w, NodeTraits::get_color(x_parent)); NodeTraits::set_color(x_parent, NodeTraits::black()); - if(NodeTraits::get_left(w)) - NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); - bstree_algo::rotate_right(x_parent, header); + const node_ptr new_wleft(NodeTraits::get_left(w)); + if(new_wleft) + NodeTraits::set_color(new_wleft, NodeTraits::black()); + bstree_algo::rotate_right(x_parent, NodeTraits::get_left(x_parent), NodeTraits::get_parent(x_parent), header); break; } } @@ -460,48 +461,49 @@ class rbtree_algorithms static void rebalance_after_insertion(const node_ptr & header, node_ptr p) { NodeTraits::set_color(p, NodeTraits::red()); - while(p != NodeTraits::get_parent(header) && NodeTraits::get_color(NodeTraits::get_parent(p)) == NodeTraits::red()){ + while(1){ node_ptr p_parent(NodeTraits::get_parent(p)); - node_ptr p_parent_parent(NodeTraits::get_parent(p_parent)); - if(bstree_algo::is_left_child(p_parent)){ - node_ptr x = NodeTraits::get_right(p_parent_parent); - if(x && NodeTraits::get_color(x) == NodeTraits::red()){ - NodeTraits::set_color(p_parent, NodeTraits::black()); - NodeTraits::set_color(p_parent_parent, NodeTraits::red()); - NodeTraits::set_color(x, NodeTraits::black()); - p = p_parent_parent; - } - else { - if(!bstree_algo::is_left_child(p)){ - p = p_parent; - bstree_algo::rotate_left(p, header); - } - node_ptr new_p_parent(NodeTraits::get_parent(p)); - node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent)); - NodeTraits::set_color(new_p_parent, NodeTraits::black()); - NodeTraits::set_color(new_p_parent_parent, NodeTraits::red()); - bstree_algo::rotate_right(new_p_parent_parent, header); - } + const node_ptr p_grandparent(NodeTraits::get_parent(p_parent)); + if(p_parent == header || NodeTraits::get_color(p_parent) == NodeTraits::black() || p_grandparent == header){ + break; } - else{ - node_ptr x = NodeTraits::get_left(p_parent_parent); - if(x && NodeTraits::get_color(x) == NodeTraits::red()){ - NodeTraits::set_color(p_parent, NodeTraits::black()); - NodeTraits::set_color(p_parent_parent, NodeTraits::red()); - NodeTraits::set_color(x, NodeTraits::black()); - p = p_parent_parent; - } - else{ - if(bstree_algo::is_left_child(p)){ - p = p_parent; - bstree_algo::rotate_right(p, header); + + NodeTraits::set_color(p_grandparent, NodeTraits::red()); + node_ptr const p_grandparent_left (NodeTraits::get_left (p_grandparent)); + bool const p_parent_is_left_child = p_parent == p_grandparent_left; + node_ptr const x(p_parent_is_left_child ? NodeTraits::get_right(p_grandparent) : p_grandparent_left); + + if(x && NodeTraits::get_color(x) == NodeTraits::red()){ + NodeTraits::set_color(x, NodeTraits::black()); + NodeTraits::set_color(p_parent, NodeTraits::black()); + p = p_grandparent; + } + else{ //Final step + const bool p_is_left_child(NodeTraits::get_left(p_parent) == p); + if(p_parent_is_left_child){ //p_parent is left child + if(!p_is_left_child){ //p is right child + bstree_algo::rotate_left_no_parent_fix(p_parent, p); + //No need to link p and p_grandparent: + // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_left(p_grandparent, p)] + //as p_grandparent is not the header, another rotation is coming and p_parent + //will be the left child of p_grandparent + p_parent = p; } - node_ptr new_p_parent(NodeTraits::get_parent(p)); - node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent)); - NodeTraits::set_color(new_p_parent, NodeTraits::black()); - NodeTraits::set_color(new_p_parent_parent, NodeTraits::red()); - bstree_algo::rotate_left(new_p_parent_parent, header); + bstree_algo::rotate_right(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header); } + else{ //p_parent is right child + if(p_is_left_child){ //p is left child + bstree_algo::rotate_right_no_parent_fix(p_parent, p); + //No need to link p and p_grandparent: + // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_right(p_grandparent, p)] + //as p_grandparent is not the header, another rotation is coming and p_parent + //will be the right child of p_grandparent + p_parent = p; + } + bstree_algo::rotate_left(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header); + } + NodeTraits::set_color(p_parent, NodeTraits::black()); + break; } } NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black()); diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index 313d6af..b70bd86 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -576,8 +576,8 @@ class splaytree_algorithms if(!t_left) break; if(comp(key, t_left)){ - commit.t_ = bstree_algo::rotate_right(commit.t_); - + bstree_algo::rotate_right_no_parent_fix(commit.t_, t_left); + commit.t_ = t_left; if( !NodeTraits::get_left(commit.t_) ) break; link_right(commit.t_, commit.r_); @@ -597,8 +597,8 @@ class splaytree_algorithms break; if(comp(t_right, key)){ - commit.t_ = bstree_algo::rotate_left( commit.t_ ); - + bstree_algo::rotate_left_no_parent_fix(commit.t_, t_right); + commit.t_ = t_right; if( !NodeTraits::get_right(commit.t_) ) break; link_left(commit.t_, commit.l_); diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index e7d887a..2b0704b 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -110,16 +110,17 @@ class treap_algorithms static void rotate_up_n(const node_ptr header, const node_ptr p, std::size_t n) { - for( node_ptr p_parent = NodeTraits::get_parent(p) - ; n-- - ; p_parent = NodeTraits::get_parent(p)){ - //Check if left child - if(p == NodeTraits::get_left(p_parent)){ - bstree_algo::rotate_right(p_parent, header); + node_ptr p_parent(NodeTraits::get_parent(p)); + node_ptr p_grandparent(NodeTraits::get_parent(p_parent)); + while(n--){ + if(p == NodeTraits::get_left(p_parent)){ //p is left child + bstree_algo::rotate_right(p_parent, p, p_grandparent, header); } - else{ //Right child - bstree_algo::rotate_left(p_parent, header); + else{ //p is right child + bstree_algo::rotate_left(p_parent, p, p_grandparent, header); } + p_parent = p_grandparent; + p_grandparent = NodeTraits::get_parent(p_parent); } } @@ -526,7 +527,7 @@ class treap_algorithms (const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data) { bstree_algo::insert_unique_commit(header, new_node, commit_data); - rebalance_after_insertion_commit(header, new_node, commit_data.rotations); + rotate_up_n(header, new_node, commit_data.rotations); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED @@ -547,11 +548,12 @@ class treap_algorithms node_ptr z_left = NodeTraits::get_left(z); node_ptr z_right = NodeTraits::get_right(z); while(z_left || z_right){ + const node_ptr z_parent(NodeTraits::get_parent(z)); if(!z_right || (z_left && pcomp(z_left, z_right))){ - bstree_algo::rotate_right(z, header); + bstree_algo::rotate_right(z, z_left, z_parent, header); } else{ - bstree_algo::rotate_left(z, header); + bstree_algo::rotate_left(z, z_right, z_parent, header); } ++n; z_left = NodeTraits::get_left(z); @@ -567,10 +569,9 @@ class treap_algorithms rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); //No-throw bstree_algo::insert_unique_commit(h, new_node, commit_data); - rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + rotate_up_n(h, new_node, commit_data.rotations); } - template static void rebalance_after_insertion_check (const const_node_ptr &header, const const_node_ptr & up, const Key &k @@ -587,22 +588,6 @@ class treap_algorithms num_rotations = n; } - static void rebalance_after_insertion_commit(const node_ptr & header, const node_ptr & p, std::size_t n) - { - // Now execute n rotations - for( node_ptr p_parent = NodeTraits::get_parent(p) - ; n-- - ; p_parent = NodeTraits::get_parent(p)){ - //Check if left child - if(p == NodeTraits::get_left(p_parent)){ - bstree_algo::rotate_right(p_parent, header); - } - else{ //Right child - bstree_algo::rotate_left(p_parent, header); - } - } - } - template static bool check_invariant(const const_node_ptr & header, NodePtrPriorityCompare pcomp) {