1 ///////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2006-2013 4 // 5 // Distributed under the Boost Software License, Version 1.0. 6 // (See accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // See http://www.boost.org/libs/intrusive for documentation. 10 // 11 ///////////////////////////////////////////////////////////////////////////// 12 13 #ifndef BOOST_INTRUSIVE_ANY_HOOK_HPP 14 #define BOOST_INTRUSIVE_ANY_HOOK_HPP 15 16 #include <boost/intrusive/detail/config_begin.hpp> 17 #include <boost/intrusive/intrusive_fwd.hpp> 18 #include <boost/intrusive/detail/any_node_and_algorithms.hpp> 19 #include <boost/intrusive/options.hpp> 20 #include <boost/intrusive/detail/generic_hook.hpp> 21 #include <boost/intrusive/detail/mpl.hpp> 22 #include <boost/intrusive/pointer_rebind.hpp> 23 24 #if defined(BOOST_HAS_PRAGMA_ONCE) 25 # pragma once 26 #endif 27 28 namespace boost { 29 namespace intrusive { 30 31 //! Helper metafunction to define a \c \c any_base_hook that yields to the same 32 //! type when the same options (either explicitly or implicitly) are used. 33 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 34 template<class ...Options> 35 #else 36 template<class O1 = void, class O2 = void, class O3 = void> 37 #endif 38 struct make_any_base_hook 39 { 40 /// @cond 41 typedef typename pack_options 42 < hook_defaults, 43 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 44 O1, O2, O3 45 #else 46 Options... 47 #endif 48 >::type packed_options; 49 50 typedef generic_hook 51 < any_algorithms<typename packed_options::void_pointer> 52 , typename packed_options::tag 53 , packed_options::link_mode 54 , AnyBaseHookId 55 > implementation_defined; 56 /// @endcond 57 typedef implementation_defined type; 58 }; 59 60 //! Derive a class from this hook in order to store objects of that class 61 //! in an intrusive container. 62 //! 63 //! The hook admits the following options: \c tag<>, \c void_pointer<> and 64 //! \c link_mode<>. 65 //! 66 //! \c tag<> defines a tag to identify the node. 67 //! The same tag value can be used in different classes, but if a class is 68 //! derived from more than one \c any_base_hook, then each \c any_base_hook needs its 69 //! unique tag. 70 //! 71 //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, \c safe_link). 72 //! 73 //! \c void_pointer<> is the pointer type that will be used internally in the hook 74 //! and the container configured to use this hook. 75 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 76 template<class ...Options> 77 #else 78 template<class O1, class O2, class O3> 79 #endif 80 class any_base_hook 81 : public make_any_base_hook 82 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 83 <O1, O2, O3> 84 #else 85 <Options...> 86 #endif 87 ::type 88 { 89 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) 90 public: 91 //! <b>Effects</b>: If link_mode is or \c safe_link 92 //! initializes the node to an unlinked state. 93 //! 94 //! <b>Throws</b>: Nothing. 95 any_base_hook(); 96 97 //! <b>Effects</b>: If link_mode is or \c safe_link 98 //! initializes the node to an unlinked state. The argument is ignored. 99 //! 100 //! <b>Throws</b>: Nothing. 101 //! 102 //! <b>Rationale</b>: Providing a copy-constructor 103 //! makes classes using the hook STL-compliant without forcing the 104 //! user to do some additional work. \c swap can be used to emulate 105 //! move-semantics. 106 any_base_hook(const any_base_hook& ); 107 108 //! <b>Effects</b>: Empty function. The argument is ignored. 109 //! 110 //! <b>Throws</b>: Nothing. 111 //! 112 //! <b>Rationale</b>: Providing an assignment operator 113 //! makes classes using the hook STL-compliant without forcing the 114 //! user to do some additional work. \c swap can be used to emulate 115 //! move-semantics. 116 any_base_hook& operator=(const any_base_hook& ); 117 118 //! <b>Effects</b>: If link_mode is \c normal_link, the destructor does 119 //! nothing (ie. no code is generated). If link_mode is \c safe_link and the 120 //! object is stored in a container an assertion is raised. 121 //! 122 //! <b>Throws</b>: Nothing. 123 ~any_base_hook(); 124 125 //! <b>Precondition</b>: link_mode must be \c safe_link. 126 //! 127 //! <b>Returns</b>: true, if the node belongs to a container, false 128 //! otherwise. This function can be used to test whether \c container::iterator_to 129 //! will return a valid iterator. 130 //! 131 //! <b>Complexity</b>: Constant 132 bool is_linked() const; 133 #endif 134 }; 135 136 //! Helper metafunction to define a \c \c any_member_hook that yields to the same 137 //! type when the same options (either explicitly or implicitly) are used. 138 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 139 template<class ...Options> 140 #else 141 template<class O1 = void, class O2 = void, class O3 = void> 142 #endif 143 struct make_any_member_hook 144 { 145 /// @cond 146 typedef typename pack_options 147 < hook_defaults, 148 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 149 O1, O2, O3 150 #else 151 Options... 152 #endif 153 >::type packed_options; 154 155 typedef generic_hook 156 < any_algorithms<typename packed_options::void_pointer> 157 , member_tag 158 , packed_options::link_mode 159 , NoBaseHookId 160 > implementation_defined; 161 /// @endcond 162 typedef implementation_defined type; 163 }; 164 165 //! Store this hook in a class to be inserted 166 //! in an intrusive container. 167 //! 168 //! The hook admits the following options: \c void_pointer<> and 169 //! \c link_mode<>. 170 //! 171 //! \c link_mode<> will specify the linking mode of the hook (\c normal_link or \c safe_link). 172 //! 173 //! \c void_pointer<> is the pointer type that will be used internally in the hook 174 //! and the container configured to use this hook. 175 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 176 template<class ...Options> 177 #else 178 template<class O1, class O2, class O3> 179 #endif 180 class any_member_hook 181 : public make_any_member_hook 182 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 183 <O1, O2, O3> 184 #else 185 <Options...> 186 #endif 187 ::type 188 { 189 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) 190 public: 191 //! <b>Effects</b>: If link_mode is or \c safe_link 192 //! initializes the node to an unlinked state. 193 //! 194 //! <b>Throws</b>: Nothing. 195 any_member_hook(); 196 197 //! <b>Effects</b>: If link_mode is or \c safe_link 198 //! initializes the node to an unlinked state. The argument is ignored. 199 //! 200 //! <b>Throws</b>: Nothing. 201 //! 202 //! <b>Rationale</b>: Providing a copy-constructor 203 //! makes classes using the hook STL-compliant without forcing the 204 //! user to do some additional work. \c swap can be used to emulate 205 //! move-semantics. 206 any_member_hook(const any_member_hook& ); 207 208 //! <b>Effects</b>: Empty function. The argument is ignored. 209 //! 210 //! <b>Throws</b>: Nothing. 211 //! 212 //! <b>Rationale</b>: Providing an assignment operator 213 //! makes classes using the hook STL-compliant without forcing the 214 //! user to do some additional work. \c swap can be used to emulate 215 //! move-semantics. 216 any_member_hook& operator=(const any_member_hook& ); 217 218 //! <b>Effects</b>: If link_mode is \c normal_link, the destructor does 219 //! nothing (ie. no code is generated). If link_mode is \c safe_link and the 220 //! object is stored in a container an assertion is raised. 221 //! 222 //! <b>Throws</b>: Nothing. 223 ~any_member_hook(); 224 225 //! <b>Precondition</b>: link_mode must be \c safe_link. 226 //! 227 //! <b>Returns</b>: true, if the node belongs to a container, false 228 //! otherwise. This function can be used to test whether \c container::iterator_to 229 //! will return a valid iterator. 230 //! 231 //! <b>Complexity</b>: Constant 232 bool is_linked() const; 233 #endif 234 }; 235 236 /// @cond 237 238 namespace detail{ 239 240 BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(old_proto_value_traits_base_hook, hooktags::is_base_hook) 241 242 //!This option setter specifies that the container 243 //!must use the specified base hook 244 template<class BasicHook, template <class> class NodeTraits> 245 struct any_to_some_hook 246 { 247 typedef typename BasicHook::template pack<empty>::proto_value_traits old_proto_value_traits; 248 249 template<class Base> 250 struct pack : public Base 251 { 252 struct proto_value_traits 253 { 254 //proto_value_traits::hooktags::is_base_hook is used by get_value_traits 255 //to detect base hooks, so mark it in case BasicHook has it. 256 struct hooktags 257 { 258 static const bool is_base_hook = old_proto_value_traits_base_hook_bool_is_true 259 <old_proto_value_traits>::value; 260 }; 261 262 typedef old_proto_value_traits basic_hook_t; 263 static const bool is_any_hook = true; 264 265 template<class VoidPtr> 266 struct node_traits_from_voidptr 267 { typedef NodeTraits<VoidPtr> type; }; 268 }; 269 }; 270 }; 271 272 } //namespace detail{ 273 274 /// @endcond 275 276 //!This option setter specifies that 277 //!any hook should behave as an slist hook 278 template<class BasicHook> 279 struct any_to_slist_hook 280 /// @cond 281 : public detail::any_to_some_hook<BasicHook, any_slist_node_traits> 282 /// @endcond 283 {}; 284 285 //!This option setter specifies that 286 //!any hook should behave as an list hook 287 template<class BasicHook> 288 struct any_to_list_hook 289 /// @cond 290 : public detail::any_to_some_hook<BasicHook, any_list_node_traits> 291 /// @endcond 292 {}; 293 294 //!This option setter specifies that 295 //!any hook should behave as a set hook 296 template<class BasicHook> 297 struct any_to_set_hook 298 /// @cond 299 : public detail::any_to_some_hook<BasicHook, any_rbtree_node_traits> 300 /// @endcond 301 {}; 302 303 //!This option setter specifies that 304 //!any hook should behave as an avl_set hook 305 template<class BasicHook> 306 struct any_to_avl_set_hook 307 /// @cond 308 : public detail::any_to_some_hook<BasicHook, any_avltree_node_traits> 309 /// @endcond 310 {}; 311 312 //!This option setter specifies that any 313 //!hook should behave as a bs_set hook 314 template<class BasicHook> 315 struct any_to_bs_set_hook 316 /// @cond 317 : public detail::any_to_some_hook<BasicHook, any_tree_node_traits> 318 /// @endcond 319 {}; 320 321 //!This option setter specifies that any hook 322 //!should behave as an unordered set hook 323 template<class BasicHook> 324 struct any_to_unordered_set_hook 325 /// @cond 326 : public detail::any_to_some_hook<BasicHook, any_unordered_node_traits> 327 /// @endcond 328 {}; 329 330 331 } //namespace intrusive 332 } //namespace boost 333 334 #include <boost/intrusive/detail/config_end.hpp> 335 336 #endif //BOOST_INTRUSIVE_ANY_HOOK_HPP 337