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