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