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