From 60c6f40336f5a9d918c5461f816997c2bbaebbcd Mon Sep 17 00:00:00 2001 From: Matei David Date: Mon, 28 Apr 2014 20:08:24 -0400 Subject: [PATCH 1/3] added tests for intrusive hooks not derived from the default hooks --- test/Makefile | 21 +++++++ test/avl_multiset_test.cpp | 10 +++ test/avl_set_test.cpp | 10 +++ test/itestvalue.hpp | 7 ++- test/list_test.cpp | 9 +++ test/multiset_test.cpp | 10 +++ test/nonhook_node.hpp | 101 +++++++++++++++++++++++++++++++ test/set_test.cpp | 10 +++ test/sg_multiset_test.cpp | 10 +++ test/sg_set_test.cpp | 10 +++ test/slist_test.cpp | 11 ++++ test/splay_multiset_test.cpp | 11 ++++ test/splay_set_test.cpp | 10 +++ test/treap_multiset_test.cpp | 10 +++ test/treap_set_test.cpp | 10 +++ test/unordered_multiset_test.cpp | 12 ++++ test/unordered_set_test.cpp | 12 ++++ 17 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 test/Makefile create mode 100644 test/nonhook_node.hpp diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..a889a98 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,21 @@ +SRC_LIST = $(wildcard *.cpp) +TGT_LIST = $(basename $(SRC_LIST)) + +CPPFLAGS = -I${BOOST_INTRUSIVE}/include -I${BOOST}/include +CXXFLAGS = -Wall -Wextra -pedantic -Wno-ignored-qualifiers -Wno-long-long -g3 -O0 + +.PHONY: all run clean + +all: $(TGT_LIST) + +%: %.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -o $@ + +run: $(TGT_LIST) + for f in $^; do \ + echo "===== running: $$f"; \ + ./$$f || break; \ + done + +clean: + rm -f $(TGT_LIST) diff --git a/test/avl_multiset_test.cpp b/test/avl_multiset_test.cpp index ecad395..be6d3c2 100644 --- a/test/avl_multiset_test.cpp +++ b/test/avl_multiset_test.cpp @@ -55,6 +55,9 @@ struct hooks typedef avl_set_member_hook < link_mode , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< avltree_node_traits, + avltree_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -96,6 +99,13 @@ class test_main_template >::type , GetContainer >::test_all(); + test::test_generic_multiset < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainer + >::test_all(); return 0; } }; diff --git a/test/avl_set_test.cpp b/test/avl_set_test.cpp index 8c04e46..36d0731 100644 --- a/test/avl_set_test.cpp +++ b/test/avl_set_test.cpp @@ -55,6 +55,9 @@ struct hooks typedef avl_set_member_hook < link_mode , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< avltree_node_traits, + avltree_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -96,6 +99,13 @@ class test_main_template >::type , GetContainer >::test_all(); + test::test_generic_set < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainer + >::test_all(); return 0; } }; diff --git a/test/itestvalue.hpp b/test/itestvalue.hpp index 91bd182..4168501 100644 --- a/test/itestvalue.hpp +++ b/test/itestvalue.hpp @@ -16,6 +16,7 @@ #include #include #include +#include "nonhook_node.hpp" namespace boost{ namespace intrusive{ @@ -33,6 +34,7 @@ struct testvalue { typename Hooks::member_hook_type node_; typename Hooks::auto_member_hook_type auto_node_; + typename Hooks::nonhook_node_member_type nhn_member_; int value_; static const bool constant_time_size = ConstantTimeSize; @@ -56,6 +58,7 @@ struct testvalue Hooks::auto_base_hook_type::operator=(static_cast(src)); this->node_ = src.node_; this->auto_node_ = src.auto_node_; + this->nhn_member_ = src.nhn_member_; value_ = src.value_; return *this; } @@ -66,6 +69,7 @@ struct testvalue Hooks::auto_base_hook_type::swap_nodes(static_cast(other)); node_.swap_nodes(other.node_); auto_node_.swap_nodes(other.auto_node_); + nhn_member_.swap_nodes(other.nhn_member_); } bool is_linked() const @@ -73,7 +77,8 @@ struct testvalue return Hooks::base_hook_type::is_linked() || Hooks::auto_base_hook_type::is_linked() || node_.is_linked() || - auto_node_.is_linked(); + auto_node_.is_linked() || + nhn_member_.is_linked(); } ~testvalue() diff --git a/test/list_test.cpp b/test/list_test.cpp index 54d3061..7301dcf 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -34,6 +34,9 @@ struct hooks typedef list_member_hook, tag > member_hook_type; typedef list_member_hook< link_mode , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< list_node_traits< VoidPointer >, + circular_list_algorithms + > nonhook_node_member_type; }; template @@ -436,6 +439,12 @@ class test_main_template > >::type >::test_all(data); + test_list < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + > + >::test_all(data); return 0; } }; diff --git a/test/multiset_test.cpp b/test/multiset_test.cpp index ba503a2..dd52cfe 100644 --- a/test/multiset_test.cpp +++ b/test/multiset_test.cpp @@ -54,6 +54,9 @@ struct hooks , optimize_size > member_hook_type; typedef set_member_hook , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< rbtree_node_traits , + rbtree_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -95,6 +98,13 @@ class test_main_template >::type , GetContainer >::test_all(); + test::test_generic_multiset < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainer + >::test_all(); return 0; } }; diff --git a/test/nonhook_node.hpp b/test/nonhook_node.hpp new file mode 100644 index 0000000..ef5494b --- /dev/null +++ b/test/nonhook_node.hpp @@ -0,0 +1,101 @@ +#ifndef BOOST_INTRUSIVE_DETAIL_NONHOOK_NODE_HPP +#define BOOST_INTRUSIVE_DETAIL_NONHOOK_NODE_HPP + +#include +#include +#include +#include + + +namespace boost{ +namespace intrusive{ + + +template < typename Node_Traits, template class Node_Algorithms > +struct nonhook_node_member : public Node_Traits::node +{ + typedef 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 Node_Algorithms< node_traits > node_algorithms; + + nonhook_node_member() + { + node_algorithms::init(pointer_traits::pointer_to(static_cast< node& >(*this))); + } + nonhook_node_member(const nonhook_node_member& rhs) + { + if (rhs.is_linked()) + { + std::cerr << "nonhook_node_member copy ctor from linked: &=" << (void*)this << ", rhs=" << (void*)&rhs << std::endl; + } + *this = rhs; + } + nonhook_node_member& operator = (const nonhook_node_member& rhs) + { + if (is_linked() or rhs.is_linked()) + { + std::cerr << "nonhook_node_member copy asop to/from linked: &=" << (void*)this << ", rhs=" << (void*)&rhs << std::endl; + } + static_cast< node& >(*this) = rhs; + return *this; + } + + void swap_nodes(nonhook_node_member& other) + { + node_algorithms::swap_nodes(pointer_traits::pointer_to(static_cast< node& >(*this)), + pointer_traits::pointer_to(static_cast< node& >(other))); + } + bool is_linked() const + { + return !node_algorithms::unique(pointer_traits::pointer_to(static_cast< const node& >(*this))); + } +}; + +template < typename T, typename NonHook_Member, NonHook_Member T::* P, link_mode_type Link_Mode > +struct nonhook_node_member_value_traits +{ + typedef T value_type; + typedef typename NonHook_Member::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 typename pointer_traits:: + template rebind_pointer::type pointer; + typedef typename pointer_traits:: + template rebind_pointer::type const_pointer; + typedef T & reference; + typedef const T & const_reference; + + static const link_mode_type link_mode = Link_Mode; + + static node_ptr to_node_ptr(reference value) + { + return pointer_traits::pointer_to(static_cast(value.*P)); + } + + static const_node_ptr to_node_ptr(const_reference value) + { + return pointer_traits::pointer_to(static_cast(value.*P)); + } + + static pointer to_value_ptr(node_ptr n) + { + return pointer_traits::pointer_to + (*detail::parent_from_member + (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); + } + + static const_pointer to_value_ptr(const_node_ptr n) + { + return pointer_traits::pointer_to + (*detail::parent_from_member + (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); + } +}; + +} +} + +#endif diff --git a/test/set_test.cpp b/test/set_test.cpp index 4e4e91d..8d5c490 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -55,6 +55,9 @@ struct hooks , optimize_size > member_hook_type; typedef set_member_hook , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< rbtree_node_traits , + rbtree_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -96,6 +99,13 @@ class test_main_template >::type , GetContainer >::test_all(); + test::test_generic_set < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainer + >::test_all(); return 0; } }; diff --git a/test/sg_multiset_test.cpp b/test/sg_multiset_test.cpp index 5accea7..4eee56c 100644 --- a/test/sg_multiset_test.cpp +++ b/test/sg_multiset_test.cpp @@ -66,6 +66,9 @@ struct hooks struct auto_base_hook_type : bs_set_base_hook, tag > {}; + typedef nonhook_node_member< tree_node_traits < VoidPointer >, + sgtree_algorithms + > nonhook_node_member_type; }; @@ -139,6 +142,13 @@ class test_main_template >::type , GetContainerFixedAlpha >::test_all(); + test::test_generic_multiset < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainerFixedAlpha + >::test_all(); return 0; } }; diff --git a/test/sg_set_test.cpp b/test/sg_set_test.cpp index f447425..00926e1 100644 --- a/test/sg_set_test.cpp +++ b/test/sg_set_test.cpp @@ -65,6 +65,9 @@ struct hooks struct auto_base_hook_type : bs_set_base_hook, tag > {}; + typedef nonhook_node_member< tree_node_traits < VoidPointer >, + sgtree_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -138,6 +141,13 @@ class test_main_template >::type , GetContainerFixedAlpha >::test_all(); + test::test_generic_set < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainerFixedAlpha + >::test_all(); return 0; } }; diff --git a/test/slist_test.cpp b/test/slist_test.cpp index 0ea0c2b..cde9a31 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -35,6 +35,9 @@ struct hooks typedef slist_member_hook, tag > member_hook_type; typedef slist_member_hook< link_mode , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< slist_node_traits< VoidPointer >, + circular_slist_algorithms + > nonhook_node_member_type; }; template @@ -564,6 +567,14 @@ class test_main_template , false , false >::test_all(data); + test_slist < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + false, + false + >::test_all(data); //Now linear slists test_slist < typename detail::get_base_value_traits diff --git a/test/splay_multiset_test.cpp b/test/splay_multiset_test.cpp index 7a21f07..c22706e 100644 --- a/test/splay_multiset_test.cpp +++ b/test/splay_multiset_test.cpp @@ -86,6 +86,9 @@ struct hooks typedef bs_set_member_hook < link_mode , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< tree_node_traits< VoidPointer >, + splaytree_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -127,6 +130,14 @@ class test_main_template >::type , GetContainer >::test_all(); + test::test_generic_multiset < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainer + >::test_all(); + return 0; } }; diff --git a/test/splay_set_test.cpp b/test/splay_set_test.cpp index 8e62f2c..7fc3fce 100644 --- a/test/splay_set_test.cpp +++ b/test/splay_set_test.cpp @@ -83,6 +83,9 @@ struct hooks typedef bs_set_member_hook < link_mode , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< tree_node_traits< VoidPointer >, + splaytree_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -124,6 +127,13 @@ class test_main_template >::type , GetContainer >::test_all(); + test::test_generic_set < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainer + >::test_all(); return 0; } }; diff --git a/test/treap_multiset_test.cpp b/test/treap_multiset_test.cpp index 1982397..7918082 100644 --- a/test/treap_multiset_test.cpp +++ b/test/treap_multiset_test.cpp @@ -52,6 +52,9 @@ struct hooks < void_pointer > member_hook_type; typedef bs_set_member_hook < void_pointer > auto_member_hook_type; + typedef nonhook_node_member< tree_node_traits< VoidPointer >, + treap_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -93,6 +96,13 @@ class test_main_template >::type , GetContainer >::test_all(); + test::test_generic_multiset < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainer + >::test_all(); return 0; } }; diff --git a/test/treap_set_test.cpp b/test/treap_set_test.cpp index f0deb47..8d1cd49 100644 --- a/test/treap_set_test.cpp +++ b/test/treap_set_test.cpp @@ -67,6 +67,9 @@ struct hooks < void_pointer > member_hook_type; typedef bs_set_member_hook < void_pointer > auto_member_hook_type; + typedef nonhook_node_member< tree_node_traits< VoidPointer >, + treap_algorithms + > nonhook_node_member_type; }; template< class ValueType @@ -108,6 +111,13 @@ class test_main_template >::type , GetContainer >::test_all(); + test::test_generic_set < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + GetContainer + >::test_all(); return 0; } }; diff --git a/test/unordered_multiset_test.cpp b/test/unordered_multiset_test.cpp index a4da129..f0e8373 100644 --- a/test/unordered_multiset_test.cpp +++ b/test/unordered_multiset_test.cpp @@ -67,6 +67,9 @@ struct hooks , store_hash , optimize_multikey > auto_member_hook_type; + typedef nonhook_node_member< unordered_node_traits< VoidPointer, true, true >, + unordered_algorithms + > nonhook_node_member_type; }; static const std::size_t BucketSize = 8; @@ -805,6 +808,15 @@ class test_main_template , false , Incremental >::test_all(data); + test_unordered_multiset < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + false, + false, + Incremental + >::test_all(data); return 0; } }; diff --git a/test/unordered_set_test.cpp b/test/unordered_set_test.cpp index 4555405..0a60c5f 100644 --- a/test/unordered_set_test.cpp +++ b/test/unordered_set_test.cpp @@ -66,6 +66,9 @@ struct hooks , store_hash , optimize_multikey > auto_member_hook_type; + typedef nonhook_node_member< unordered_node_traits< VoidPointer, true, true >, + unordered_algorithms + > nonhook_node_member_type; }; static const std::size_t BucketSize = 8; @@ -657,6 +660,15 @@ class test_main_template , false , incremental >::test_all(data); + test_unordered_set < nonhook_node_member_value_traits< value_type, + typename hooks::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + false, + false, + incremental + >::test_all(data); return 0; } From 09991acfb5833138bdd3e0c31f1921339d37b77f Mon Sep 17 00:00:00 2001 From: Matei David Date: Mon, 28 Apr 2014 20:23:44 -0400 Subject: [PATCH 2/3] log destructor as well --- test/nonhook_node.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/nonhook_node.hpp b/test/nonhook_node.hpp index ef5494b..0297140 100644 --- a/test/nonhook_node.hpp +++ b/test/nonhook_node.hpp @@ -41,6 +41,14 @@ struct nonhook_node_member : public Node_Traits::node static_cast< node& >(*this) = rhs; return *this; } + ~nonhook_node_member() + { + if (is_linked()) + { + std::cerr << "nonhook_node_member dtor of linked: &=" << (void*)this << std::endl; + } + node_algorithms::init(pointer_traits::pointer_to(static_cast< node& >(*this))); + } void swap_nodes(nonhook_node_member& other) { From 9169db7f5742f87058ed535f07aea9fc312ea595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 1 May 2014 10:21:40 +0200 Subject: [PATCH 3/3] Fixed #9961: tests for hooks not derived frorm generic_hook --- doc/intrusive.qbk | 1 + .../vc7ide/_intrusivelib/_intrusivelib.vcproj | 3 + test/nonhook_node.hpp | 167 ++++++++++-------- 3 files changed, 93 insertions(+), 78 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index a0cf973..4d47228 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3800,6 +3800,7 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std * [@https://svn.boost.org/trac/boost/ticket/9746 #9746: Modern Sun CC compiler detects error in intrusive library header] * [@https://svn.boost.org/trac/boost/ticket/9940 #9940: bad bug in intrusive list with safe_link (or auto_unlink) hooks] * [@https://svn.boost.org/trac/boost/ticket/9949 #9949: clear header node hooks upon intrusive container destruction] + * [@https://svn.boost.org/trac/boost/ticket/9961 #9961: tests for hooks not derived frorm generic_hook] * Optimized tree rebalancing code to avoid redundant assignments. diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj index fc4e758..cfa6a7a 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -318,6 +318,9 @@ + + diff --git a/test/nonhook_node.hpp b/test/nonhook_node.hpp index 0297140..06ba155 100644 --- a/test/nonhook_node.hpp +++ b/test/nonhook_node.hpp @@ -1,106 +1,117 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Matei David 2014-2014. +// (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. +// +///////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTRUSIVE_DETAIL_NONHOOK_NODE_HPP #define BOOST_INTRUSIVE_DETAIL_NONHOOK_NODE_HPP #include -#include #include #include +#include +#include namespace boost{ namespace intrusive{ - +//This node will only be used in safe or auto unlink modes +//so test it's been properly released template < typename Node_Traits, template class Node_Algorithms > struct nonhook_node_member : public Node_Traits::node { - typedef 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 Node_Algorithms< node_traits > node_algorithms; + typedef 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 Node_Algorithms< node_traits > node_algorithms; - nonhook_node_member() - { - node_algorithms::init(pointer_traits::pointer_to(static_cast< node& >(*this))); - } - nonhook_node_member(const nonhook_node_member& rhs) - { - if (rhs.is_linked()) - { - std::cerr << "nonhook_node_member copy ctor from linked: &=" << (void*)this << ", rhs=" << (void*)&rhs << std::endl; - } - *this = rhs; - } - nonhook_node_member& operator = (const nonhook_node_member& rhs) - { - if (is_linked() or rhs.is_linked()) - { - std::cerr << "nonhook_node_member copy asop to/from linked: &=" << (void*)this << ", rhs=" << (void*)&rhs << std::endl; - } - static_cast< node& >(*this) = rhs; - return *this; - } - ~nonhook_node_member() - { - if (is_linked()) - { - std::cerr << "nonhook_node_member dtor of linked: &=" << (void*)this << std::endl; - } - node_algorithms::init(pointer_traits::pointer_to(static_cast< node& >(*this))); - } + nonhook_node_member() + { + node_algorithms::init(pointer_traits::pointer_to(static_cast< node& >(*this))); + } - void swap_nodes(nonhook_node_member& other) - { - node_algorithms::swap_nodes(pointer_traits::pointer_to(static_cast< node& >(*this)), - pointer_traits::pointer_to(static_cast< node& >(other))); - } - bool is_linked() const - { - return !node_algorithms::unique(pointer_traits::pointer_to(static_cast< const node& >(*this))); - } + nonhook_node_member(const nonhook_node_member& rhs) + { + BOOST_TEST(!rhs.is_linked()); + *this = rhs; + } + + nonhook_node_member& operator = (const nonhook_node_member& rhs) + { + BOOST_TEST(!this->is_linked() && !rhs.is_linked()); + static_cast< node& >(*this) = rhs; + return *this; + } + + ~nonhook_node_member() + { + BOOST_TEST(!this->is_linked()); + node_algorithms::init(pointer_traits::pointer_to(static_cast< node& >(*this))); + } + + void swap_nodes(nonhook_node_member& other) + { + node_algorithms::swap_nodes(pointer_traits::pointer_to(static_cast< node& >(*this)), + pointer_traits::pointer_to(static_cast< node& >(other))); + } + + bool is_linked() const + { + return !node_algorithms::unique(pointer_traits::pointer_to(static_cast< const node& >(*this))); + } }; template < typename T, typename NonHook_Member, NonHook_Member T::* P, link_mode_type Link_Mode > struct nonhook_node_member_value_traits { - typedef T value_type; - typedef typename NonHook_Member::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 typename pointer_traits:: - template rebind_pointer::type pointer; - typedef typename pointer_traits:: - template rebind_pointer::type const_pointer; - typedef T & reference; - typedef const T & const_reference; + typedef T value_type; + typedef typename NonHook_Member::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 typename pointer_traits:: + template rebind_pointer::type pointer; + typedef typename pointer_traits:: + template rebind_pointer::type const_pointer; + typedef T & reference; + typedef const T & const_reference; - static const link_mode_type link_mode = Link_Mode; + static const link_mode_type link_mode = Link_Mode; - static node_ptr to_node_ptr(reference value) - { - return pointer_traits::pointer_to(static_cast(value.*P)); - } + BOOST_STATIC_ASSERT((Link_Mode == safe_link || Link_Mode == auto_unlink)); - static const_node_ptr to_node_ptr(const_reference value) - { - return pointer_traits::pointer_to(static_cast(value.*P)); - } - - static pointer to_value_ptr(node_ptr n) - { - return pointer_traits::pointer_to - (*detail::parent_from_member - (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); - } + static node_ptr to_node_ptr(reference value) + { + return pointer_traits::pointer_to(static_cast(value.*P)); + } - static const_pointer to_value_ptr(const_node_ptr n) - { - return pointer_traits::pointer_to - (*detail::parent_from_member - (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); - } + static const_node_ptr to_node_ptr(const_reference value) + { + return pointer_traits::pointer_to(static_cast(value.*P)); + } + + static pointer to_value_ptr(node_ptr n) + { + return pointer_traits::pointer_to + (*detail::parent_from_member + (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); + } + + static const_pointer to_value_ptr(const_node_ptr n) + { + return pointer_traits::pointer_to + (*detail::parent_from_member + (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); + } }; }