Move include files in debian packge into 'senf' subdirectory
[senf.git] / boost / intrusive / islist_hook.hpp
1 /////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 // (C) Copyright Olaf Krzikalla 2004-2006.\r
4 // (C) Copyright Ion GaztaƱaga  2006-2007\r
5 //\r
6 // Distributed under the Boost Software License, Version 1.0.\r
7 //    (See accompanying file LICENSE_1_0.txt or copy at\r
8 //          http://www.boost.org/LICENSE_1_0.txt)\r
9 //\r
10 // See http://www.boost.org/libs/intrusive for documentation.\r
11 //\r
12 /////////////////////////////////////////////////////////////////////////////\r
13 \r
14 #ifndef BOOST_INTRUSIVE_ISLIST_HOOK_HPP\r
15 #define BOOST_INTRUSIVE_ISLIST_HOOK_HPP\r
16 \r
17 #include "detail/config_begin.hpp"\r
18 #include "detail/utilities.hpp"\r
19 #include "detail/pointer_type.hpp"\r
20 #include "detail/pointer_to_other.hpp"\r
21 #include "detail/slist_node.hpp"\r
22 #include "slist_algorithms.hpp"\r
23 #include "linking_policy.hpp"\r
24 #include <boost/get_pointer.hpp>\r
25 #include <stdexcept>\r
26 \r
27 namespace boost {\r
28 namespace intrusive {\r
29 \r
30 //! Derive a class from islist_base_hook in order to store objects in \r
31 //! in an islist. islist_base_hook holds the data necessary to maintain the \r
32 //! list and provides an appropriate value_traits class for islist.\r
33 //! \r
34 //! The first integer template argument defines a tag to identify the node. \r
35 //! The same tag value can be used in different classes, but if a class is \r
36 //! derived from more than one islist_base_hook, then each islist_base_hook needs its \r
37 //! unique tag.\r
38 //!\r
39 //! The second boolean template parameter will activate the safe-mode checks\r
40 //! if it's configured as "true".\r
41 //!\r
42 //! The third argument is the pointer type that will be used internally in the hook\r
43 //! and the islist configured from this hook.\r
44 template<typename Tag, bool SafeMode = true, class VoidPointer = void*>\r
45 class islist_base_hook\r
46    :  private detail::slist_node_traits<VoidPointer>::node\r
47 {\r
48    public:\r
49    typedef detail::slist_node_traits<VoidPointer>     node_traits;\r
50    enum { linking_policy = SafeMode? safe_mode_link : normal_link};\r
51 \r
52    private:\r
53    typedef slist_algorithms<node_traits> node_algorithms;\r
54 \r
55    public:\r
56    typedef typename node_traits::node                 node;\r
57    typedef islist_base_hook\r
58       <Tag, SafeMode, VoidPointer>                    this_type;\r
59    typedef typename boost::pointer_to_other\r
60       <VoidPointer, node>::type                       node_ptr;\r
61    typedef typename boost::pointer_to_other\r
62       <VoidPointer, const node>::type                 const_node_ptr;\r
63    typedef typename boost::pointer_to_other\r
64       <VoidPointer, this_type>::type                  this_type_ptr;\r
65    typedef typename boost::pointer_to_other\r
66       <VoidPointer, const this_type>::type            const_this_type_ptr;\r
67 \r
68    private:\r
69    node_ptr this_as_node()\r
70    {  return node_ptr(static_cast<node *const>(this)); }\r
71 \r
72    const_node_ptr this_as_node() const\r
73    {  return const_node_ptr(static_cast<const node *const>(this)); }\r
74 \r
75    public:\r
76 \r
77    //! <b>Effects</b>: If SafeMode is true initializes the node\r
78    //!   to an unlinked state.\r
79    //! \r
80    //! <b>Throws</b>: Nothing.\r
81    islist_base_hook()\r
82       : node_traits::node()\r
83    {\r
84       if(SafeMode){\r
85          node_algorithms::init(this_as_node());\r
86       }\r
87    }\r
88 \r
89    //! <b>Effects</b>: If SafeMode is true initializes the node\r
90    //!   to an unlinked state. The argument is ignored.\r
91    //! \r
92    //! <b>Throws</b>: Nothing.\r
93    //! \r
94    //! <b>Rationale</b>: Providing a copy-constructor\r
95    //!   makes classes using islist_base_hook STL-compliant without forcing the \r
96    //!   user to do some additional work. "swap" can be used to emulate\r
97    //!   move-semantics.\r
98    islist_base_hook(const islist_base_hook& )\r
99       :  node_traits::node()\r
100    {\r
101       if(SafeMode){\r
102          node_algorithms::init(this_as_node());\r
103       }\r
104    }\r
105 \r
106    //! <b>Effects</b>: If SafeMode is true, an assertion is raised\r
107    //!   if the node is still linked. After that, the node is initialized\r
108    //!   to an unlinked state. The argument is ignored.\r
109    //! \r
110    //! <b>Throws</b>: Nothing.\r
111    //! \r
112    //! <b>Rationale</b>: Providing an assignment operator \r
113    //!   makes classes using islist_base_hook STL-compliant without forcing the \r
114    //!   user to do some additional work. "swap" can be used to emulate\r
115    //!   move-semantics.\r
116    islist_base_hook& operator=(const islist_base_hook& )\r
117    { \r
118       if(SafeMode){\r
119          BOOST_ASSERT(!this->linked());\r
120       }\r
121       return *this; \r
122    }\r
123 \r
124    //! <b>Effects</b>: If SafeMode is set to false, the destructor does\r
125    //!   nothing (ie. no code is generated). If SafeMode is true and the\r
126    //!   object is stored in an islist an assertion is raised.\r
127    //! \r
128    //! <b>Throws</b>: Nothing.\r
129    ~islist_base_hook() \r
130    { \r
131       if(SafeMode){\r
132          BOOST_ASSERT(!this->linked());\r
133       }\r
134    }\r
135 \r
136    //! <b>Effects</b>: Swapping two nodes swaps the position of the elements \r
137    //!   related to those nodes in one or two containers. That is, if the node \r
138    //!   this is part of the element e1, the node x is part of the element e2 \r
139    //!   and both elements are included in the containers s1 and s2, then after \r
140    //!   the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 \r
141    //!   at the position of e1. If one element is not in a container, then \r
142    //!   after the swap-operation the other element is not in a container. \r
143    //!   Iterators to e1 and e2 related to those nodes are invalidated. \r
144    //!\r
145    //! <b>Complexity</b>: Linear\r
146    //!\r
147    //! <b>Throws</b>: Nothing. \r
148    void swap_nodes(islist_base_hook& other) \r
149    { node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }\r
150 \r
151    //! <b>Precondition</b>: The hook must be in safe-mode.\r
152    //!\r
153    //! <b>Returns</b>: true, if the node belongs to a container, false\r
154    //!   otherwise. This function can be used to test whether islist::current \r
155    //!   will return a valid iterator. \r
156    //!\r
157    //! <b>Complexity</b>: Constant\r
158    bool linked() const \r
159    {\r
160       //linked() can be only used in safe-mode\r
161       BOOST_ASSERT(SafeMode);\r
162       return !node_algorithms::unique(this_as_node());\r
163    }\r
164 \r
165    //! The value_traits class is used as the first template argument for islist. \r
166    //! The template argument T defines the class type stored in islist. Objects \r
167    //! of type T and of types derived from T can be stored. T doesn't need to be \r
168    //! copy-constructible or assignable.\r
169    template<class T>\r
170    struct value_traits\r
171       : detail::derivation_value_traits<T, this_type, Tag>\r
172    {};\r
173 \r
174    //! <b>Effects</b>: Converts a pointer to a node into\r
175    //!   a pointer to the hook that holds that node.\r
176    //! \r
177    //! <b>Throws</b>: Nothing.\r
178    static this_type_ptr to_hook_ptr(node_ptr p)\r
179    {\r
180       using boost::get_pointer;\r
181       return this_type_ptr(static_cast<islist_base_hook*> (get_pointer(p))); \r
182    }\r
183 \r
184    //! <b>Effects</b>: Converts a const pointer to a node stored in a container into\r
185    //!   a const pointer to the hook that holds that node.\r
186    //! \r
187    //! <b>Throws</b>: Nothing.\r
188    static const_this_type_ptr to_hook_ptr(const_node_ptr p)\r
189    {\r
190       using boost::get_pointer;\r
191       return this_type_ptr(static_cast<const islist_base_hook*> (get_pointer(p))); \r
192    }\r
193 \r
194    //! <b>Effects</b>: Returns a pointer to the node that this hook holds.\r
195    //! \r
196    //! <b>Throws</b>: Nothing.\r
197    node_ptr to_node_ptr()\r
198    { return this_as_node(); }\r
199 \r
200    //! <b>Effects</b>: Returns a const pointer to the node that this hook holds.\r
201    //! \r
202    //! <b>Throws</b>: Nothing.\r
203    const_node_ptr to_node_ptr() const\r
204    { return this_as_node(); }\r
205 };\r
206 \r
207 \r
208 //! Derive a class from islist_auto_base_hook in order to store objects in \r
209 //! in an islist. islist_auto_base_hook holds the data necessary to maintain the \r
210 //! list and provides an appropriate value_traits class for islist.\r
211 //!\r
212 //! The difference between islist_auto_base_hook and islist_base_hook is that\r
213 //! islist_auto_base_hook removes itself automatically from the container\r
214 //! in the assignment operator and the destructor. It also provides a new\r
215 //! "unlink" method so that the user can unlink its class without using\r
216 //! the container.\r
217 //!\r
218 //! islist_auto_base_hook can only be used with non constant-time islists.\r
219 //! \r
220 //! The first integer template argument defines a tag to identify the node. \r
221 //! The same tag value can be used in different classes, but if a class is \r
222 //! derived from more than one islist_auto_base_hook, then each islist_auto_base_hook needs its \r
223 //! unique tag.\r
224 //!\r
225 //! The second argument is the pointer type that will be used internally in the hook\r
226 //! and the islist configured from this hook.\r
227 template<typename Tag, class VoidPointer = void*>\r
228 class islist_auto_base_hook\r
229    :  private detail::slist_node_traits<VoidPointer>::node\r
230 {\r
231    public:\r
232    typedef detail::slist_node_traits<VoidPointer>     node_traits;\r
233    enum { linking_policy = auto_unlink  };\r
234 \r
235    private:\r
236    typedef slist_algorithms<node_traits> node_algorithms;\r
237 \r
238    public:\r
239    typedef islist_auto_base_hook\r
240       <Tag, VoidPointer>                              this_type;\r
241    typedef typename node_traits::node                 node;\r
242    typedef typename boost::pointer_to_other\r
243       <VoidPointer, node>::type                       node_ptr;\r
244    typedef typename boost::pointer_to_other\r
245       <VoidPointer, const node>::type                 const_node_ptr;\r
246    typedef typename boost::pointer_to_other\r
247       <VoidPointer, this_type>::type                  this_type_ptr;\r
248    typedef typename boost::pointer_to_other\r
249       <VoidPointer, const this_type>::type            const_this_type_ptr;\r
250 \r
251    private:\r
252    node_ptr this_as_node()\r
253    {  return node_ptr(static_cast<node *const>(this)); }\r
254 \r
255    const_node_ptr this_as_node() const\r
256    {  return const_node_ptr(static_cast<const node *const>(this)); }\r
257 \r
258    public:\r
259 \r
260    //! <b>Effects</b>: Initializes the node\r
261    //!   to an unlinked state.\r
262    //! \r
263    //! <b>Throws</b>: Nothing. \r
264    islist_auto_base_hook()\r
265       : node_traits::node()\r
266    {  node_algorithms::init(this_as_node());   }\r
267 \r
268    //! <b>Effects</b>: Initializes the node\r
269    //!   to an unlinked state. The argument is ignored.\r
270    //! \r
271    //! <b>Throws</b>: Nothing. \r
272    //! \r
273    //! <b>Rationale</b>: Providing a copy-constructor\r
274    //!   makes classes using islist_auto_base_hook STL-compliant without forcing the \r
275    //!   user to do some additional work.\r
276    islist_auto_base_hook(const islist_auto_base_hook& )\r
277       :  node_traits::node()\r
278    {  node_algorithms::init(this_as_node());   }\r
279 \r
280    //! <b>Effects</b>: Removes the node if it's inserted in a container.\r
281    //!   The argument is ignored.\r
282    //! \r
283    //! <b>Throws</b>: Nothing. \r
284    //! \r
285    //! <b>Rationale</b>: Providing an assignment operator \r
286    //!   makes classes using islist_auto_base_hook STL-compliant without forcing the \r
287    //!   user to do some additional work.\r
288    islist_auto_base_hook& operator=(const islist_auto_base_hook& )\r
289    {  this->unlink(); return *this;  }\r
290 \r
291    //! <b>Effects</b>: Removes the node if it's inserted in a container.\r
292    //! \r
293    //! <b>Throws</b>: Nothing. \r
294    ~islist_auto_base_hook() \r
295    {  this->unlink();  }\r
296 \r
297    //! <b>Effects</b>: Swapping two nodes swaps the position of the elements \r
298    //!   related to those nodes in one or two containers. That is, if the node \r
299    //!   this is part of the element e1, the node x is part of the element e2 \r
300    //!   and both elements are included in the containers s1 and s2, then after \r
301    //!   the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 \r
302    //!   at the position of e1. If one element is not in a container, then \r
303    //!   after the swap-operation the other element is not in a container. \r
304    //!   Iterators to e1 and e2 related to those nodes are invalidated. \r
305    //!\r
306    //! <b>Complexity</b>: Linear \r
307    //!\r
308    //! <b>Throws</b>: Nothing.\r
309    void swap_nodes(islist_auto_base_hook& other) \r
310    { node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }\r
311 \r
312    //! <b>Returns</b>: true, if the node belongs to a container, false\r
313    //!   otherwise. This function can be used to test whether islist::current \r
314    //!   will return a valid iterator. \r
315    //!\r
316    //! <b>Complexity</b>: Constant \r
317    bool linked() const \r
318    {  return !node_algorithms::unique(this_as_node());  }\r
319 \r
320    //! <b>Effects</b>: Removes the node if it's inserted in a container.\r
321    //! \r
322    //! <b>Throws</b>: Nothing. \r
323    void unlink()\r
324    {\r
325       node_algorithms::unlink(this_as_node());\r
326       node_algorithms::init(this_as_node());\r
327    }\r
328 \r
329    //! The value_traits class is used as the first template argument for islist. \r
330    //! The template argument T defines the class type stored in islist. Objects \r
331    //! of type T and of types derived from T can be stored. T doesn't need to be \r
332    //! copy-constructible or assignable.\r
333    template<class T>\r
334    struct value_traits\r
335       : detail::derivation_value_traits<T, this_type, Tag>\r
336    {};\r
337 \r
338    //! <b>Effects</b>: Converts a pointer to a node into\r
339    //!   a pointer to the hook that holds that node.\r
340    //! \r
341    //! <b>Throws</b>: Nothing. \r
342    static this_type_ptr to_hook_ptr(node_ptr p)\r
343    {\r
344       using boost::get_pointer;\r
345       return this_type_ptr(static_cast<islist_auto_base_hook*> (get_pointer(p))); \r
346    }\r
347 \r
348    //! <b>Effects</b>: Converts a const pointer to a node stored in a container into\r
349    //!   a const pointer to the hook that holds that node.\r
350    //! \r
351    //! <b>Throws</b>: Nothing. \r
352    static const_this_type_ptr to_hook_ptr(const_node_ptr p)\r
353    {\r
354       using boost::get_pointer;\r
355       return this_type_ptr(static_cast<const islist_auto_base_hook*> (get_pointer(p))); \r
356    }\r
357 \r
358    //! <b>Effects</b>: Returns a pointer to the node that this hook holds.\r
359    //! \r
360    //! <b>Throws</b>: Nothing.\r
361    node_ptr to_node_ptr()\r
362    { return this_as_node(); }\r
363 \r
364    //! <b>Effects</b>: Returns a const pointer to the node that this hook holds.\r
365    //! \r
366    //! <b>Throws</b>: Nothing.\r
367    const_node_ptr to_node_ptr() const\r
368    { return this_as_node(); }\r
369 };\r
370 \r
371 \r
372 //! Put a public data member islist_member_hook in order to store objects of this class in\r
373 //! an islist. islist_member_hook holds the data necessary for maintaining the list and \r
374 //! provides an appropriate value_traits class for islist.\r
375 //! \r
376 //! The template argument T defines the class type stored in islist. Objects of type \r
377 //! T and of types derived from T can be stored. T doesn't need to be \r
378 //! copy-constructible or assignable.\r
379 //! \r
380 //! The second boolean template parameter will activate the safe-mode checks\r
381 //! if it's configured as "true".\r
382 //!\r
383 //! The third argument is the pointer type that will be used internally in the hook\r
384 //! and the islist configured from this hook.\r
385 template<class T, bool SafeMode = true, class VoidPointer = void*>\r
386 class islist_member_hook \r
387    :  private detail::slist_node_traits<VoidPointer>::node\r
388 {\r
389    public:\r
390    typedef detail::slist_node_traits<VoidPointer>     node_traits;\r
391    enum { linking_policy = SafeMode? safe_mode_link : normal_link};\r
392 \r
393    private:\r
394    typedef slist_algorithms<node_traits>              node_algorithms;\r
395 \r
396    public:\r
397    typedef typename node_traits::node                 node;\r
398    typedef islist_member_hook<T, SafeMode, VoidPointer> this_type;\r
399    typedef typename boost::pointer_to_other\r
400       <VoidPointer, node>::type                       node_ptr;\r
401    typedef typename boost::pointer_to_other\r
402       <VoidPointer, const node>::type                 const_node_ptr;\r
403    typedef typename boost::pointer_to_other\r
404       <VoidPointer, this_type >::type                 this_type_ptr;\r
405    typedef typename boost::pointer_to_other\r
406       <VoidPointer, const this_type >::type           const_this_type_ptr;\r
407 \r
408    private:\r
409    node_ptr this_as_node()\r
410    {  return node_ptr(static_cast<node *const>(this)); }\r
411 \r
412    const_node_ptr this_as_node() const\r
413    {  return const_node_ptr(static_cast<const node *const>(this)); }\r
414 \r
415    public:\r
416    //! <b>Effects</b>: If SafeMode is true initializes the node\r
417    //!   to an unlinked state.\r
418    //! \r
419    //! <b>Throws</b>: Nothing. \r
420    islist_member_hook()\r
421       :  node_traits::node()\r
422    {\r
423       if(SafeMode){\r
424          node_algorithms::init(this_as_node());\r
425       }\r
426    }\r
427 \r
428    //! <b>Effects</b>: If SafeMode is true initializes the node\r
429    //!   to an unlinked state. The argument is ignored.\r
430    //! \r
431    //! <b>Throws</b>: Nothing. \r
432    //! \r
433    //! <b>Rationale</b>: Providing a copy-constructor\r
434    //!   makes classes using islist_member_hook STL-compliant without forcing the \r
435    //!   user to do some additional work. "swap" can be used to emulate\r
436    //!   move-semantics.\r
437    islist_member_hook(const islist_member_hook& )\r
438       :  node_traits::node()\r
439    {\r
440       if(SafeMode){\r
441          node_algorithms::init(this_as_node());\r
442       }\r
443    }\r
444 \r
445    //! <b>Effects</b>: If SafeMode is true, an assertion is raised\r
446    //!   if the node is still linked. After that, the node is initialized\r
447    //!   to an unlinked state. The argument is ignored.\r
448    //! \r
449    //! <b>Throws</b>: Nothing. \r
450    //! \r
451    //! <b>Rationale</b>: Providing an assignment operator \r
452    //!   makes classes using islist_member_hook STL-compliant without forcing the \r
453    //!   user to do some additional work. "swap" can be used to emulate\r
454    //!   move-semantics.\r
455    islist_member_hook& operator=(const islist_member_hook& ) \r
456    { \r
457       if(SafeMode){\r
458          BOOST_ASSERT(!this->linked());\r
459       }\r
460       return *this; \r
461    }\r
462 \r
463    //! <b>Effects</b>: If SafeMode is set to false, the destructor does\r
464    //!   nothing (ie. no code is generated). If SafeMode is true and the\r
465    //!   object is stored in an islist an assertion is raised.\r
466    //! \r
467    //! <b>Throws</b>: Nothing. \r
468    ~islist_member_hook() \r
469    { \r
470       if(SafeMode){\r
471          BOOST_ASSERT(!this->linked());\r
472       }\r
473    }\r
474 \r
475    //! <b>Effects</b>: Swapping two nodes swaps the position of the elements \r
476    //!   related to those nodes in one or two containers. That is, if the node \r
477    //!   this is part of the element e1, the node x is part of the element e2 \r
478    //!   and both elements are included in the containers s1 and s2, then after \r
479    //!   the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 \r
480    //!   at the position of e1. If one element is not in a container, then \r
481    //!   after the swap-operation the other element is not in a container. \r
482    //!   Iterators to e1 and e2 related to those nodes are invalidated. \r
483    //!\r
484    //! <b>Complexity</b>: Linear \r
485    //!\r
486    //! <b>Throws</b>: Nothing.\r
487    void swap_nodes(islist_member_hook& other) \r
488    { node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }\r
489 \r
490    //! <b>Precondition</b>: The hook must be in safe-mode.\r
491    //!\r
492    //! <b>Returns</b>: true, if the node belongs to a container, false\r
493    //!   otherwise. This function can be used to test whether islist::current \r
494    //!   will return a valid iterator. \r
495    //!\r
496    //! <b>Complexity</b>: Constant\r
497    bool linked() const \r
498    {\r
499       //We must be in safe-mode to know if we are really linked\r
500       //Otherwise, this would lead to an unknown state\r
501       BOOST_ASSERT(SafeMode);\r
502       return !node_algorithms::unique(this_as_node()); \r
503    }\r
504 \r
505    //! The value_traits class is used as the first template argument for islist. \r
506    //! The template argument is a pointer to member pointing to the node in \r
507    //! the class. Objects of type T and of types derived from T can be stored. \r
508    //! T doesn't need to be copy-constructible or assignable.\r
509    template<this_type T::* M>\r
510    struct value_traits\r
511       : detail::member_value_traits<T, this_type, M>\r
512    {};\r
513 \r
514    //! <b>Effects</b>: Converts a pointer to a node into\r
515    //!   a pointer to the hook that holds that node.\r
516    //! \r
517    //! <b>Throws</b>: Nothing. \r
518    static this_type_ptr to_hook_ptr(node_ptr p)\r
519    {\r
520       using boost::get_pointer;\r
521       return this_type_ptr(static_cast<this_type*> (get_pointer(p))); \r
522    }\r
523 \r
524    //! <b>Effects</b>: Converts a const pointer to a node stored in a container into\r
525    //!   a const pointer to the hook that holds that node.\r
526    //! \r
527    //! <b>Throws</b>: Nothing. \r
528    static const_this_type_ptr to_hook_ptr(const_node_ptr p)\r
529    {\r
530       using boost::get_pointer;\r
531       return this_type_ptr(static_cast<this_type*> (get_pointer(p))); \r
532    }\r
533 \r
534    //! <b>Effects</b>: Returns a pointer to the node that this hook holds.\r
535    //! \r
536    //! <b>Throws</b>: Nothing. \r
537    node_ptr to_node_ptr()\r
538    { return this_as_node(); }\r
539 \r
540    //! <b>Effects</b>: Returns a const pointer to the node that this hook holds.\r
541    //! \r
542    //! <b>Throws</b>: Nothing. \r
543    const_node_ptr to_node_ptr() const\r
544    { return this_as_node(); }\r
545 };\r
546 \r
547 \r
548 //! Put a public data member islist_auto_member_hook in order to store objects of this class in\r
549 //! an islist. islist_auto_member_hook holds the data necessary for maintaining the list and \r
550 //! provides an appropriate value_traits class for islist.\r
551 //!\r
552 //! The difference between islist_auto_member_hook and islist_member_hook is that\r
553 //! islist_auto_member_hook removes itself automatically from the container\r
554 //! in the assignment operator and the destructor. It also provides a new\r
555 //! "unlink" method so that the user can unlink its class without using\r
556 //! the container.\r
557 //!\r
558 //! islist_auto_member_hook can only be used with non constant-time islists.\r
559 //! \r
560 //! The first template argument T defines the class type stored in islist. Objects of\r
561 //! type T and of types derived from T can be stored. T doesn't need to be \r
562 //! copy-constructible or assignable.\r
563 //!\r
564 //! The second argument is the pointer type that will be used internally in the hook\r
565 //! and the islist configured from this hook.\r
566 template<class T, class VoidPointer = void*>\r
567 class islist_auto_member_hook \r
568    :  private detail::slist_node_traits<VoidPointer>::node\r
569 {\r
570    public:\r
571    typedef detail::slist_node_traits<VoidPointer>     node_traits;\r
572    enum { linking_policy = auto_unlink  };\r
573 \r
574    private:\r
575    typedef slist_algorithms<node_traits>              node_algorithms;\r
576 \r
577    public:\r
578    typedef typename node_traits::node                 node;\r
579    typedef islist_auto_member_hook<T, VoidPointer>    this_type;\r
580    typedef typename boost::pointer_to_other\r
581       <VoidPointer, node>::type                       node_ptr;\r
582    typedef typename boost::pointer_to_other\r
583       <VoidPointer, const node>::type                 const_node_ptr;\r
584    typedef typename boost::pointer_to_other\r
585       <VoidPointer, this_type >::type                 this_type_ptr;\r
586    typedef typename boost::pointer_to_other\r
587       <VoidPointer, const this_type >::type           const_this_type_ptr;\r
588 \r
589    private:\r
590    node_ptr this_as_node()\r
591    {  return node_ptr(static_cast<node *const>(this)); }\r
592 \r
593    const_node_ptr this_as_node() const\r
594    {  return const_node_ptr(static_cast<const node *const>(this)); }\r
595 \r
596    public:\r
597    //! <b>Effects</b>: Initializes the node\r
598    //!   to an unlinked state.\r
599    //! \r
600    //! <b>Throws</b>: Nothing. \r
601    islist_auto_member_hook()\r
602       :  node_traits::node()\r
603    {  node_algorithms::init(this_as_node());   }\r
604 \r
605    //! <b>Effects</b>: Initializes the node\r
606    //!   to an unlinked state. The argument is ignored.\r
607    //! \r
608    //! <b>Throws</b>: Nothing. \r
609    //! \r
610    //! <b>Rationale</b>: Providing a copy-constructor\r
611    //!   makes classes using islist_auto_base_hook STL-compliant without forcing the \r
612    //!   user to do some additional work.\r
613    islist_auto_member_hook(const islist_auto_member_hook& )\r
614       :  node_traits::node()\r
615    {  node_algorithms::init(this_as_node());   }\r
616 \r
617    //! <b>Effects</b>: Removes the node if it's inserted in a container.\r
618    //!   The argument is ignored.\r
619    //! \r
620    //! <b>Throws</b>: Nothing. \r
621    //! \r
622    //! <b>Rationale</b>: Providing an assignment operator \r
623    //!   makes classes using islist_auto_base_hook STL-compliant without forcing the \r
624    //!   user to do some additional work.\r
625    islist_auto_member_hook& operator=(const islist_auto_member_hook& ) \r
626    {  this->unlink(); return *this;  }\r
627 \r
628    //! <b>Effects</b>: If SafeMode is set to false, the destructor does\r
629    //!   nothing (ie. no code is generated). If SafeMode is true and the\r
630    //!   object is stored in an islist an assertion is raised.\r
631    //! \r
632    //! <b>Throws</b>: Nothing. \r
633    ~islist_auto_member_hook() \r
634    {  this->unlink();  }\r
635 \r
636    //! <b>Effects</b>: Swapping two nodes swaps the position of the elements \r
637    //!   related to those nodes in one or two containers. That is, if the node \r
638    //!   this is part of the element e1, the node x is part of the element e2 \r
639    //!   and both elements are included in the containers s1 and s2, then after \r
640    //!   the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 \r
641    //!   at the position of e1. If one element is not in a container, then \r
642    //!   after the swap-operation the other element is not in a container. \r
643    //!   Iterators to e1 and e2 related to those nodes are invalidated. \r
644    //!\r
645    //! <b>Complexity</b>: Constant \r
646    //!\r
647    //! <b>Throws</b>: Nothing.\r
648    void swap_nodes(islist_auto_member_hook& other) \r
649    { node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }\r
650 \r
651    //! <b>Returns</b>: true, if the node belongs to a container, false\r
652    //!   otherwise. This function can be used to test whether islist::current \r
653    //!   will return a valid iterator. \r
654    //!\r
655    //! <b>Complexity</b>: Constant \r
656    bool linked() const \r
657    {  return !node_algorithms::unique(this_as_node());  }\r
658 \r
659    //! The value_traits class is used as the first template argument for islist. \r
660    //! The template argument is a pointer to member pointing to the node in \r
661    //! the class. Objects of type T and of types derived from T can be stored. \r
662    //! T doesn't need to be copy-constructible or assignable.\r
663    template<this_type T::* M>\r
664    struct value_traits\r
665       : detail::member_value_traits<T, this_type, M>\r
666    {};\r
667 \r
668    //! <b>Effects</b>: Removes the node if it's inserted in a container.\r
669    //! \r
670    //! <b>Throws</b>: Nothing. \r
671    void unlink()\r
672    {\r
673       node_algorithms::unlink(this_as_node());\r
674       node_algorithms::init(this_as_node());\r
675    }\r
676 \r
677    //! <b>Effects</b>: Converts a pointer to a node into\r
678    //!   a pointer to the hook that holds that node.\r
679    //! \r
680    //! <b>Throws</b>: Nothing. \r
681    static this_type_ptr to_hook_ptr(node_ptr p)\r
682    {\r
683       using boost::get_pointer;\r
684       return this_type_ptr(static_cast<this_type*> (get_pointer(p))); \r
685    }\r
686 \r
687    //! <b>Effects</b>: Converts a const pointer to a node stored in a container into\r
688    //!   a const pointer to the hook that holds that node.\r
689    //! \r
690    //! <b>Throws</b>: Nothing. \r
691    static const_this_type_ptr to_hook_ptr(const_node_ptr p)\r
692    {\r
693       using boost::get_pointer;\r
694       return const_this_type_ptr(static_cast<const this_type*> (get_pointer(p))); \r
695    }\r
696 \r
697    //! <b>Effects</b>: Returns a pointer to the node that this hook holds.\r
698    //! \r
699    //! <b>Throws</b>: Nothing. \r
700    node_ptr to_node_ptr()\r
701    { return this_as_node(); }\r
702 \r
703    //! <b>Effects</b>: Returns a const pointer to the node that this hook holds.\r
704    //! \r
705    //! <b>Throws</b>: Nothing. \r
706    const_node_ptr to_node_ptr() const\r
707    { return this_as_node(); }\r
708 };\r
709 \r
710 } //namespace intrusive \r
711 } //namespace boost \r
712 \r
713 #include<boost/intrusive/detail/config_end.hpp>\r
714 \r
715 #endif //BOOST_INTRUSIVE_ISLIST_HOOK_HPP\r