1 ///////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Olaf Krzikalla 2004-2006. 4 // (C) Copyright Ion Gaztanaga 2006-2013 5 // 6 // Distributed under the Boost Software License, Version 1.0. 7 // (See accompanying file LICENSE_1_0.txt or copy at 8 // http://www.boost.org/LICENSE_1_0.txt) 9 // 10 // See http://www.boost.org/libs/intrusive for documentation. 11 // 12 ///////////////////////////////////////////////////////////////////////////// 13 14 #ifndef BOOST_INTRUSIVE_LIST_HOOK_HPP 15 #define BOOST_INTRUSIVE_LIST_HOOK_HPP 16 17 #include <boost/intrusive/detail/config_begin.hpp> 18 #include <boost/intrusive/intrusive_fwd.hpp> 19 20 #include <boost/intrusive/detail/list_node.hpp> 21 #include <boost/intrusive/circular_list_algorithms.hpp> 22 #include <boost/intrusive/options.hpp> 23 #include <boost/intrusive/detail/generic_hook.hpp> 24 25 #if defined(BOOST_HAS_PRAGMA_ONCE) 26 # pragma once 27 #endif 28 29 30 namespace boost { 31 namespace intrusive { 32 33 //! Helper metafunction to define a \c \c list_base_hook that yields to the same 34 //! type when the same options (either explicitly or implicitly) are used. 35 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 36 template<class ...Options> 37 #else 38 template<class O1 = void, class O2 = void, class O3 = void> 39 #endif 40 struct make_list_base_hook 41 { 42 /// @cond 43 typedef typename pack_options 44 < hook_defaults, 45 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 46 O1, O2, O3 47 #else 48 Options... 49 #endif 50 >::type packed_options; 51 52 typedef generic_hook 53 < CircularListAlgorithms 54 , list_node_traits<typename packed_options::void_pointer> 55 , typename packed_options::tag 56 , packed_options::link_mode 57 , ListBaseHookId 58 > implementation_defined; 59 /// @endcond 60 typedef implementation_defined type; 61 }; 62 63 //! Derive a class from this hook in order to store objects of that class 64 //! in an list. 65 //! 66 //! The hook admits the following options: \c tag<>, \c void_pointer<> and 67 //! \c link_mode<>. 68 //! 69 //! \c tag<> defines a tag to identify the node. 70 //! The same tag value can be used in different classes, but if a class is 71 //! derived from more than one \c list_base_hook, then each \c list_base_hook needs its 72 //! unique tag. 73 //! 74 //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, 75 //! \c auto_unlink or \c safe_link). 76 //! 77 //! \c void_pointer<> is the pointer type that will be used internally in the hook 78 //! and the container configured to use this hook. 79 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 80 template<class ...Options> 81 #else 82 template<class O1, class O2, class O3> 83 #endif 84 class list_base_hook 85 : public make_list_base_hook 86 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 87 <O1, O2, O3> 88 #else 89 <Options...> 90 #endif 91 ::type 92 { 93 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) 94 public: 95 //! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link 96 //! initializes the node to an unlinked state. 97 //! 98 //! <b>Throws</b>: Nothing. 99 list_base_hook(); 100 101 //! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link 102 //! initializes the node to an unlinked state. The argument is ignored. 103 //! 104 //! <b>Throws</b>: Nothing. 105 //! 106 //! <b>Rationale</b>: Providing a copy-constructor 107 //! makes classes using the hook STL-compliant without forcing the 108 //! user to do some additional work. \c swap can be used to emulate 109 //! move-semantics. 110 list_base_hook(const list_base_hook& ); 111 112 //! <b>Effects</b>: Empty function. The argument is ignored. 113 //! 114 //! <b>Throws</b>: Nothing. 115 //! 116 //! <b>Rationale</b>: Providing an assignment operator 117 //! makes classes using the hook STL-compliant without forcing the 118 //! user to do some additional work. \c swap can be used to emulate 119 //! move-semantics. 120 list_base_hook& operator=(const list_base_hook& ); 121 122 //! <b>Effects</b>: If link_mode is \c normal_link, the destructor does 123 //! nothing (ie. no code is generated). If link_mode is \c safe_link and the 124 //! object is stored in an list an assertion is raised. If link_mode is 125 //! \c auto_unlink and \c is_linked() is true, the node is unlinked. 126 //! 127 //! <b>Throws</b>: Nothing. 128 ~list_base_hook(); 129 130 //! <b>Effects</b>: Swapping two nodes swaps the position of the elements 131 //! related to those nodes in one or two containers. That is, if the node 132 //! this is part of the element e1, the node x is part of the element e2 133 //! and both elements are included in the containers s1 and s2, then after 134 //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 135 //! at the position of e1. If one element is not in a container, then 136 //! after the swap-operation the other element is not in a container. 137 //! Iterators to e1 and e2 related to those nodes are invalidated. 138 //! 139 //! <b>Complexity</b>: Constant 140 //! 141 //! <b>Throws</b>: Nothing. 142 void swap_nodes(list_base_hook &other); 143 144 //! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink. 145 //! 146 //! <b>Returns</b>: true, if the node belongs to a container, false 147 //! otherwise. This function can be used to test whether \c list::iterator_to 148 //! will return a valid iterator. 149 //! 150 //! <b>Complexity</b>: Constant 151 bool is_linked() const; 152 153 //! <b>Effects</b>: Removes the node if it's inserted in a container. 154 //! This function is only allowed if link_mode is \c auto_unlink. 155 //! 156 //! <b>Throws</b>: Nothing. 157 void unlink(); 158 #endif 159 }; 160 161 //! Helper metafunction to define a \c \c list_member_hook that yields to the same 162 //! type when the same options (either explicitly or implicitly) are used. 163 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 164 template<class ...Options> 165 #else 166 template<class O1 = void, class O2 = void, class O3 = void> 167 #endif 168 struct make_list_member_hook 169 { 170 /// @cond 171 typedef typename pack_options 172 < hook_defaults, 173 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 174 O1, O2, O3 175 #else 176 Options... 177 #endif 178 >::type packed_options; 179 180 typedef generic_hook 181 < CircularListAlgorithms 182 , list_node_traits<typename packed_options::void_pointer> 183 , member_tag 184 , packed_options::link_mode 185 , NoBaseHookId 186 > implementation_defined; 187 /// @endcond 188 typedef implementation_defined type; 189 }; 190 191 //! Store this hook in a class to be inserted 192 //! in an list. 193 //! 194 //! The hook admits the following options: \c void_pointer<> and 195 //! \c link_mode<>. 196 //! 197 //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, 198 //! \c auto_unlink or \c safe_link). 199 //! 200 //! \c void_pointer<> is the pointer type that will be used internally in the hook 201 //! and the container configured to use this hook. 202 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 203 template<class ...Options> 204 #else 205 template<class O1, class O2, class O3> 206 #endif 207 class list_member_hook 208 : public make_list_member_hook 209 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 210 <O1, O2, O3> 211 #else 212 <Options...> 213 #endif 214 ::type 215 { 216 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) 217 public: 218 //! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link 219 //! initializes the node to an unlinked state. 220 //! 221 //! <b>Throws</b>: Nothing. 222 list_member_hook(); 223 224 //! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link 225 //! initializes the node to an unlinked state. The argument is ignored. 226 //! 227 //! <b>Throws</b>: Nothing. 228 //! 229 //! <b>Rationale</b>: Providing a copy-constructor 230 //! makes classes using the hook STL-compliant without forcing the 231 //! user to do some additional work. \c swap can be used to emulate 232 //! move-semantics. 233 list_member_hook(const list_member_hook& ); 234 235 //! <b>Effects</b>: Empty function. The argument is ignored. 236 //! 237 //! <b>Throws</b>: Nothing. 238 //! 239 //! <b>Rationale</b>: Providing an assignment operator 240 //! makes classes using the hook STL-compliant without forcing the 241 //! user to do some additional work. \c swap can be used to emulate 242 //! move-semantics. 243 list_member_hook& operator=(const list_member_hook& ); 244 245 //! <b>Effects</b>: If link_mode is \c normal_link, the destructor does 246 //! nothing (ie. no code is generated). If link_mode is \c safe_link and the 247 //! object is stored in an list an assertion is raised. If link_mode is 248 //! \c auto_unlink and \c is_linked() is true, the node is unlinked. 249 //! 250 //! <b>Throws</b>: Nothing. 251 ~list_member_hook(); 252 253 //! <b>Effects</b>: Swapping two nodes swaps the position of the elements 254 //! related to those nodes in one or two containers. That is, if the node 255 //! this is part of the element e1, the node x is part of the element e2 256 //! and both elements are included in the containers s1 and s2, then after 257 //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 258 //! at the position of e1. If one element is not in a container, then 259 //! after the swap-operation the other element is not in a container. 260 //! Iterators to e1 and e2 related to those nodes are invalidated. 261 //! 262 //! <b>Complexity</b>: Constant 263 //! 264 //! <b>Throws</b>: Nothing. 265 void swap_nodes(list_member_hook &other); 266 267 //! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink. 268 //! 269 //! <b>Returns</b>: true, if the node belongs to a container, false 270 //! otherwise. This function can be used to test whether \c list::iterator_to 271 //! will return a valid iterator. 272 //! 273 //! <b>Complexity</b>: Constant 274 bool is_linked() const; 275 276 //! <b>Effects</b>: Removes the node if it's inserted in a container. 277 //! This function is only allowed if link_mode is \c auto_unlink. 278 //! 279 //! <b>Throws</b>: Nothing. 280 void unlink(); 281 #endif 282 }; 283 284 } //namespace intrusive 285 } //namespace boost 286 287 #include <boost/intrusive/detail/config_end.hpp> 288 289 #endif //BOOST_INTRUSIVE_LIST_HOOK_HPP 290