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 | |