• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2 / Copyright (c) 2006-2013 Ion Gaztanaga
3 /
4 / Distributed under the Boost Software License, Version 1.0. (See accompanying
5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 /]
7
8[library Boost.Intrusive
9    [quickbook 1.6]
10    [authors [Krzikalla, Olaf], [Gaztanaga, Ion]]
11    [copyright 2005 Olaf Krzikalla, 2006-2015 Ion Gaztanaga]
12    [id intrusive]
13    [dirname intrusive]
14    [purpose Intrusive containers]
15    [license
16        Distributed under the Boost Software License, Version 1.0.
17        (See accompanying file LICENSE_1_0.txt or copy at
18        [@http://www.boost.org/LICENSE_1_0.txt])
19    ]
20]
21
22[section:introduction Introduction]
23
24[section:introduction_presenting Presenting Boost.Intrusive]
25
26[*Boost.Intrusive] is a library presenting some intrusive containers to
27the world of C++. Intrusive containers are special containers
28that offer [link intrusive.performance better performance]
29and exception safety guarantees than non-intrusive containers (like STL containers).
30
31The performance benefits of intrusive containers makes them ideal as a building
32block to efficiently construct complex containers like multi-index containers or
33to design high performance code like memory allocation algorithms.
34
35While intrusive containers were and are widely used in C, they
36became more and more forgotten in C++ due to the presence of the standard
37containers which don't support intrusive techniques.[*Boost.Intrusive] wants to
38push intrusive containers usage encapsulating the implementation in
39STL-like interfaces. Hence anyone familiar with standard containers can easily use
40[*Boost.Intrusive].
41
42[endsect]
43
44[section:introduction_building_intrusive Building Boost.Intrusive]
45
46There is no need to compile anything to use [*Boost.Intrusive], since it's
47a header only library. Just include your Boost header directory in your
48compiler include path.
49
50[endsect]
51
52[section:tested_compilers Tested compilers]
53
54[*Boost.Intrusive] has been tested on the following compilers/platforms:
55
56*  Visual C++ >= 7.1.
57*  GCC >= 4.1.
58
59[warning GCC < 4.3 and MSVC < 9.0 are deprecated and will be removed in the next version.]
60
61[endsect]
62
63[endsect]
64
65[section:intrusive_vs_nontrusive Intrusive and non-intrusive containers]
66
67[section:differences_intrusive_vs_nontrusive Differences between intrusive and non-intrusive containers]
68
69The main difference between intrusive containers and non-intrusive containers is
70that in C++ non-intrusive containers store [*copies] of values passed by the user.
71Containers use the `Allocator` template parameter to allocate the stored values:
72
73[c++]
74
75   #include <list>
76   #include <assert.h>
77
78   int main()
79   {
80      std::list<MyClass> myclass_list;
81
82      MyClass myclass(...);
83      myclass_list.push_back(myclass);
84
85      //The stored object is different from the original object
86      assert(&myclass != &myclass_list.front());
87      return 0;
88   }
89
90
91To store the newly allocated copy of `myclass`, the container needs additional
92data: `std::list` usually allocates nodes that contain pointers to the
93next and previous node and the value itself. Something similar to:
94
95[c++]
96
97   //A possible implementation of a std::list<MyClass> node
98   class list_node
99   {
100      list_node *next;
101      list_node *previous;
102      MyClass    value;
103   };
104
105
106On the other hand, an intrusive container does not store copies of passed objects,
107but it stores the objects themselves. The additional data needed to insert the object
108in the container must be provided by the object itself. For example, to insert `MyClass`
109in an intrusive container that implements a linked list, `MyClass` must contain the
110needed ['next] and ['previous] pointers:
111
112[c++]
113
114   class MyClass
115   {
116      MyClass *next;
117      MyClass *previous;
118      //Other members...
119   };
120
121   int main()
122   {
123      acme_intrusive_list<MyClass> list;
124
125      MyClass myclass;
126      list.push_back(myclass);
127
128      //"myclass" object is stored in the list
129      assert(&myclass == &list.front());
130      return 0;
131   }
132
133As we can see, knowing which additional data the class should contain is not
134an easy task. [*Boost.Intrusive] offers several intrusive containers and an easy
135way to make user classes compatible with those containers.
136
137[endsect]
138
139[section:properties_of_intrusive Properties of Boost.Intrusive containers]
140
141Semantically, a [*Boost.Intrusive] container is similar to a STL container
142holding pointers to objects. That is, if you have an intrusive list holding
143objects of type `T`, then `std::list<T*>` would allow you to do quite the
144same operations (maintaining and navigating a set of objects of type T and
145types derived from it).
146
147A non-intrusive container has some limitations:
148
149*  An object can only belong to one container: If you want to share an object
150   between two containers, you either have to store multiple copies of those
151   objects or you need to use containers of pointers: `std::list<Object*>`.
152
153*  The use of dynamic allocation to create copies of passed values can be a performance
154   and size bottleneck in some applications. Normally, dynamic allocation imposes
155   a size overhead for each allocation to store bookkeeping information and a
156   synchronization to protected concurrent allocation from different threads.
157
158*  Before C++11, only copies of objects could be stored in non-intrusive containers. Still
159   copy or move constructors and copy or move assignment operators are required
160   and non-copyable and non-movable objects can't be stored in some containers. In any case,
161   [*new] objects have to be created inside the container using constructors and the same
162   object can't be shared between two containers.
163
164*  It's not possible to store a derived object in a STL-container while
165   retaining its original type.
166
167Intrusive containers have some important advantages:
168
169*  Operating with intrusive containers doesn't invoke any memory management at all.
170   The time and size overhead associated with dynamic memory can be minimized.
171
172*  The same object can be inserted in more than one container at the same time with
173   a tiny overhead in the object size.
174
175*  Iterating an Intrusive container needs less memory accesses than the semantically
176   equivalent container of pointers: iteration is faster.
177
178*  Intrusive containers offer better exception guarantees than non-intrusive containers.
179   In some situations intrusive containers offer a no-throw guarantee that can't be
180   achieved with non-intrusive containers.
181
182*  The computation of an iterator to an element from a pointer or reference to that element
183   is a constant time operation (computing the position of `T*` in a `std::list<T*>` has
184   linear complexity).
185
186*  Intrusive containers offer predictability when inserting and erasing objects since no
187   memory management is done with intrusive containers. Memory management usually is not a predictable
188   operation so complexity guarantees from non-intrusive containers are looser than the guarantees
189   offered by intrusive containers.
190
191Intrusive containers have also downsides:
192
193*  Each type stored in an intrusive container needs additional memory holding the
194   maintenance information needed by the container. Hence, whenever a certain type will
195   be stored in an intrusive container [*you have to change the definition of that type]
196   appropriately. Although this task is easy with [*Boost.Intrusive], touching the
197   definition of a type is sometimes a crucial issue.
198
199*  In intrusive containers you don't store a copy of an object, [*but rather the original object
200   is linked with other objects in the container]. Objects don't need copy-constructors or assignment
201   operators to be stored in intrusive containers. But you have to take care of possible side effects,
202   whenever you change the contents of an object (this is especially important for
203   associative containers).
204
205*  The user [*has to manage the lifetime of inserted objects] independently from the
206   containers.
207
208*  Again you have to be [*careful]: in contrast to STL containers [*it's easy to render an
209   iterator invalid] without touching the intrusive container directly, because the object
210   can be disposed before is erased from the container.
211
212*  [*Boost.Intrusive] containers are [*non-copyable and non-assignable]. Since intrusive
213   containers don't have allocation capabilities, these operations make no sense. However,
214   swapping can be used to implement move capabilities. To ease the implementation of
215   copy constructors and assignment operators of classes storing [*Boost.Intrusive]
216   containers, [*Boost.Intrusive] offers special cloning functions. See
217   [link intrusive.clone_from Cloning Boost.Intrusive containers] section for more information.
218
219*  Analyzing the thread safety of a program that uses containers is harder with intrusive containers, because
220   the container might be modified indirectly without an explicit call to a container member.
221
222[table Summary of intrusive containers advantages and disadvantages
223    [[Issue]                                                                     [Intrusive]                         [Non-intrusive]]
224    [[Memory management]                                                         [External]                          [Internal through allocator]]
225    [[Insertion/Erasure time]                                                    [Faster]                            [Slower]]
226    [[Memory locality]                                                           [Better]                            [Worse]]
227    [[Can insert the same object in more than one container]                     [Yes]                               [No]]
228    [[Exception guarantees]                                                      [Better]                            [Worse]]
229    [[Computation of iterator from value]                                        [Constant]                          [Non-constant]]
230    [[Insertion/erasure predictability]                                          [High]                              [Low]]
231    [[Memory use]                                                                [Minimal]                           [More than minimal]]
232    [[Insert objects by value retaining polymorphic behavior]                    [Yes]                               [No (slicing)]]
233    [[User must modify the definition of the values to insert]                   [Yes]                               [No]]
234    [[Containers are copyable]                                                   [No]                                [Yes]]
235    [[Inserted object's lifetime managed by]                                     [User (more complex)]               [Container (less complex)]]
236    [[Container invariants can be broken without using the container]            [Easier]                            [Harder (only with containers of pointers)]]
237    [[Thread-safety analysis]                                                    [Harder]                            [Easier]]
238]
239
240For a performance comparison between Intrusive and Non-intrusive containers see
241[link intrusive.performance Performance] section.
242
243[endsect]
244
245[endsect]
246
247[section:usage How to use Boost.Intrusive]
248
249If you plan to insert a class in an intrusive container, you have to make some decisions
250influencing the class definition itself. Each class that will be used in an intrusive
251container needs some appropriate data members storing the information needed by the
252container. We will take a simple intrusive container, the intrusive list
253([classref boost::intrusive::list boost::intrusive::list]), for the following
254examples, but all [*Boost.Intrusive] containers are very similar. To compile
255the example using [classref boost::intrusive::list boost::intrusive::list],
256just include:
257
258[c++]
259
260   #include <boost/intrusive/list.hpp>
261
262Every class to be inserted in an intrusive container, needs to contain a hook that
263will offer the necessary data and resources to be insertable in the container.
264With [*Boost.Intrusive] you just choose the hook to be a public base class or
265a public member of the class to be inserted. [*Boost.Intrusive] also offers
266more flexible hooks for advanced users, as explained in the chapter
267[link intrusive.function_hooks Using function hooks], but usually base or member
268hooks are good enough for most users.
269
270[section:usage_base_hook Using base hooks]
271
272For [classref boost::intrusive::list list], you can publicly derive from
273[classref boost::intrusive::list_base_hook list_base_hook].
274
275[c++]
276
277   template <class ...Options>
278   class list_base_hook;
279
280The class can take several options. [*Boost.Intrusive] classes receive arguments in the
281form `option_name<option_value>`. You can specify the following options:
282
283*  [*`tag<class Tag>`]: this argument serves as a tag, so you can derive from more than one
284   [classref boost::intrusive::list_base_hook list_base_hook] and hence put an object in
285   multiple intrusive lists at the same time. An incomplete type can serve as a tag.
286   If you specify two base hooks, you [*must] specify a different
287   tag for each one. Example: `list_base_hook< tag<tag1> >`. If no tag is specified
288   a default one will be used (more on default tags later).
289
290*  [*`link_mode<link_mode_type LinkMode>`]: The second template argument controls the
291   linking policy. [*Boost.Intrusive] currently supports
292   3 modes: `normal_link`, `safe_link` and `auto_unlink`. By default, `safe_link`
293   mode is used. More about these in sections
294   [link intrusive.safe_hook Safe hooks] and [link intrusive.auto_unlink_hooks Auto-unlink hooks].
295   Example: `list_base_hook< link_mode<auto_unlink> >`
296
297*  [*`void_pointer<class VoidPointer>`]: this option is the pointer type to be used
298   internally in the hook. The default value is `void *`, which means that raw pointers
299   will be used in the hook. More about this in the section titled
300   [link intrusive.using_smart_pointers Using smart pointers with Boost.Intrusive containers].
301   Example: `list_base_hook< void_pointer< my_smart_ptr<void> >`
302
303For the following examples, let's forget the options and use the default values:
304
305[c++]
306
307   #include <boost/intrusive/list.hpp>
308
309   using namespace boost::intrusive;
310
311   class Foo
312      //Base hook with default tag, raw pointers and safe_link mode
313      :  public list_base_hook<>
314   { /**/ };
315
316After that, we can define the intrusive list:
317
318[c++]
319
320   template <class T, class ...Options>
321   class list;
322
323`list` receives the type to be inserted in the container (`T`) as the first parameter
324and optionally, the user can specify options. We have 3 option types:
325
326*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
327   [*`value_traits<class ValueTraits>`]: All these options specify the relationship
328   between the type `T` to be inserted in the list and the hook (since we can
329   have several hooks in the same `T` type). `member_hook` will be explained
330   a bit later and `value_traits` will be explained in the
331   [link intrusive.value_traits Containers with custom ValueTraits] section.
332   [*If no option is specified, the container will be configured to use the base
333   hook with the default tag].
334   Some options configured for the hook (the type of the pointers, link mode, etc.)
335   will be propagated to the container.
336
337*  [*`constant_time_size<bool Enabled>`]: Specifies if a constant time `size()`
338   function is demanded for the container. This will instruct the intrusive
339   container to store an additional member to keep track of the current size of the
340   container. By default, constant-time size is activated.
341
342*  [*`size_type<class SizeType>`]: Specifies an unsigned type that can hold
343   the size of the container. This type will be the type returned by `list.size()`
344   and the type stored in the intrusive container if `constant_time_size<true>`
345   is requested.
346   The user normally will not need to change this type, but some
347   containers can have a `size_type` that might be different from `std::size_t`
348   (for example, STL-like containers use the `size_type` defined by their allocator).
349   [*Boost.Intrusive] can be used to implement such containers specifying the
350   type of the size. By default the type is `std::size_t`.
351
352Example of a constant-time size intrusive list that will store Foo objects, using
353the base hook with the default tag:
354
355[c++]
356
357   typedef list<Foo> FooList;
358
359Example of an intrusive list with non constant-time size that will store Foo objects:
360
361[c++]
362
363   typedef list<Foo, constant_time_size<false> > FooList;
364
365Remember that the user must specify the base hook in the container declaration
366if the base hook has no default tag, because that usually means that the type
367has more than one base hook, and a container shall know which hook will be
368using:
369
370[c++]
371
372   #include <boost/intrusive/list.hpp>
373
374   using namespace boost::intrusive;
375
376   struct my_tag1;
377   struct my_tag2;
378
379   typedef list_base_hook< tag<my_tag>  > BaseHook;
380   typedef list_base_hook< tag<my_tag2> > BaseHook2;
381   class Foo   :  public BaseHook, public BaseHook2
382   { /**/ };
383
384   typedef list< Foo, base_hook<BaseHook>  > FooList;
385   typedef list< Foo, base_hook<BaseHook2> > FooList2;
386
387Once the list is defined, we can use it:
388
389[c++]
390
391   //An object to be inserted in the list
392   Foo foo_object;
393   FooList list;
394
395   list.push_back(object);
396
397   assert(&list.front() == &foo_object);
398
399[endsect]
400
401[section:usage_member_hook Using member hooks]
402
403Sometimes an 'is-a' relationship between list hooks and the list value types
404is not desirable. In this case, using a member hook as a data member instead of
405'disturbing' the hierarchy might be the right way: you can add a public data
406member `list_member_hook<...>` to your class.
407This class can be configured with the same options as `list_base_hook`
408except the option `tag`:
409
410[c++]
411
412   template <class ...Options>
413   class list_member_hook;
414
415Example:
416
417[c++]
418
419   #include <boost/intrusive/list.hpp>
420
421   class Foo
422   {
423      public:
424      list_member_hook<> hook_;
425      //...
426   };
427
428When member hooks are used, the `member_hook` option is used to configure the
429list:
430
431[c++]
432
433   //This option will configure "list" to use the member hook
434   typedef member_hook<Foo, list_member_hook<>, &Foo::hook_> MemberHookOption;
435
436   //This list will use the member hook
437   typedef list<Foo, MemberHookOption> FooList;
438
439Now we can use the container:
440
441[c++]
442
443   //An object to be inserted in the list
444   Foo foo_object;
445   FooList list;
446
447   list.push_back(object);
448
449   assert(&list.front() == &foo_object);
450
451[endsect]
452
453However, member hooks have some implementation limitations: If there is a virtual inheritance
454relationship between the parent and the member hook, then the distance between the parent
455and the hook is not a compile-time fixed value so obtaining the address of
456the parent from the member hook is not possible without reverse engineering compiler
457produced RTTI. Apart from this, the non-standard pointer to member implementation for classes
458with complex inheritance relationships in MSVC ABI compatible-compilers is not supported
459by member hooks since it also depends on compiler-produced RTTI information.
460
461[section:usage_both_hooks Using both hooks]
462
463You can insert the same object in several intrusive containers at the same time,
464using one hook per container. This is a full example using base and member hooks:
465
466[import ../example/doc_how_to_use.cpp]
467[doc_how_to_use_code]
468
469[endsect]
470
471[section:usage_lifetime Object lifetime]
472
473Even if the interface of [classref boost::intrusive::list list] is similar to
474`std::list`, its usage is a bit different: You always have to keep in mind that
475you directly store objects in intrusive containers, not copies. The lifetime of a
476stored object is not bound to or managed by the container:
477
478*  When the container gets destroyed before the object, the object is not destroyed,
479   so you have to be careful to avoid resource leaks.
480
481*  When the object is destroyed before the container, your program is likely to crash,
482   because the container contains a pointer to an non-existing object.
483
484[endsect]
485
486
487[endsect]
488
489[section:usage_when When to use?]
490
491Intrusive containers can be used for highly optimized algorithms, where speed is a crucial
492issue and:
493
494*  additional memory management should be avoided.
495*  the programmer needs to efficiently track the construction and destruction of objects.
496*  exception safety, especially the no-throw guarantee, is needed.
497*  the computation of an iterator to an element from a pointer or reference
498   to that element should be a constant time operation.
499*  it's important to achieve a well-known worst-time system response.
500*  localization of data (e.g. for cache hit optimization) leads to measurable effects.
501
502The last point is important if you have a lot of containers over a set of elements. E.g. if
503you have a vector of objects (say, `std::vector<Object>`), and you also have a list
504storing a subset of those objects (`std::list<Object*>`), then operating on an Object
505from the list iterator (`std::list<Object*>::iterator`) requires two steps:
506
507*  Access from the iterator (usually on the stack) to the list node storing a pointer to `Object`.
508*  Access from the pointer to `Object` to the Object stored in the vector.
509
510While the objects themselves are tightly packed in the memory of the vector
511(a vector's memory is guaranteed to be contiguous), and form something
512like a data block, list nodes may be dispersed in the heap memory.
513Hence depending on your system you might get a lot of cache misses. The same doesn't hold
514for an intrusive list. Indeed, dereferencing an iterator from an intrusive list is performed in
515the same two steps as described above. But the list node is already embedded in the Object, so
516the memory is directly tracked from the iterator to the Object.
517
518It's also possible to use intrusive containers when the objects to be stored can
519have different or unknown size. This allows storing base and derived objects
520in the same container, as shown in the following example:
521
522[import ../example/doc_window.cpp]
523[doc_window_code]
524
525Due to certain properties of intrusive containers
526they are often more difficult to use than their STL-counterparts. That's why you
527should avoid them in public interfaces of libraries. Classes to be stored in intrusive
528containers must change their implementation to store the hook and this is not always
529possible or desirable.
530
531[endsect]
532
533[section:concepts_summary Concept summary]
534
535Here is a small summary of the basic concepts that will be used in the following
536chapters:
537
538[variablelist Brief Concepts Summary
539[[Node Algorithms][A class containing typedefs and static functions that define
540   basic operations that can be applied to a group of `node`s. It's independent
541   from the node definition and configured using a NodeTraits template
542   parameter that describes the node.]]
543[[Node Traits][A class that stores basic information and operations to insert a node into a group of nodes.]]
544[[Hook][A class that a user must add as a base class or as a member to make the user class compatible with intrusive containers. A Hook encapsulates a `node`]]
545[[Intrusive Container][A class that stores user classes that have the needed hooks. It takes a ValueTraits template parameter as configuration information.]]
546[[Semi-Intrusive Container][Similar to an intrusive container but a semi-intrusive container needs additional memory (e.g. an auxiliary array) to work.]]
547[[Value Traits][A class containing typedefs and operations to obtain the node to be used by Node Algorithms from the user class and the inverse.]]
548]
549
550[endsect]
551
552[section:presenting_containers Presenting Boost.Intrusive containers]
553
554[*Boost.Intrusive] offers a wide range of intrusive containers:
555
556*  [*slist]: An intrusive singly linked list. The size overhead is very small
557   for user classes (usually the size of one pointer) but many operations have linear
558   time complexity, so the user must be careful if he wants to avoid performance problems.
559
560*  [*list]: A `std::list` like intrusive linked list. The size overhead is quite
561   small for user classes (usually the size of two pointers). Many operations have
562   constant time complexity.
563
564*  [*set/multiset/rbtree]: `std::set/std::multiset` like intrusive associative containers
565   based on red-black trees.
566   The size overhead is moderate for user classes (usually the size of three pointers).
567   Many operations have logarithmic time complexity.
568
569*  [*avl_set/avl_multiset/avltree]: A `std::set/std::multiset` like intrusive associative
570   containers based on AVL trees.
571   The size overhead is moderate for user classes (usually the size of three pointers).
572   Many operations have logarithmic time complexity.
573
574*  [*splay_set/splay_multiset/splaytree]: `std::set/std::multiset` like intrusive associative
575   containers based on splay trees. Splay trees have no constant operations, but they
576   have some interesting caching properties.
577   The size overhead is moderate for user classes (usually the size of three pointers).
578   Many operations have logarithmic time complexity.
579
580*  [*sg_set/sg_multiset/sgtree]: A `std::set/std::multiset` like intrusive associative
581   containers based on scapegoat trees. Scapegoat can be configured with the desired
582   balance factor to achieve the desired rebalancing frequency/search time compromise.
583   The size overhead is moderate for user classes (usually the size of three pointers).
584   Many operations have logarithmic time complexity.
585
586[*Boost.Intrusive] also offers semi-intrusive containers:
587
588*  [*unordered_set/unordered_multiset]: `std::tr1::unordered_set/std::tr1::unordered_multiset`
589   like intrusive unordered associative containers.
590   The size overhead is moderate for user classes (an average of two pointers per element).
591   Many operations have amortized constant time complexity.
592
593Most of these intrusive containers can be configured with constant or linear time
594size:
595
596*  [*Linear time size]: The intrusive container doesn't hold a size member that is
597updated with every insertion/erasure. This implies that the `size()` function doesn't have constant
598time complexity. On the other hand, the container is smaller, and some operations, like
599`splice()` taking a range of iterators in linked lists, have constant time complexity
600instead of linear complexity.
601
602*  [*Constant time size]: The intrusive container holds a size member that is updated
603with every insertion/erasure. This implies that the `size()` function has constant time
604complexity. On the other hand, increases the size of the container, and some operations,
605like `splice()` taking a range of iterators, have linear time complexity in linked lists.
606
607To make user classes compatible with these intrusive containers [*Boost.Intrusive]
608offers two types of hooks for each container type:
609
610*  [*Base hook]: The hook is stored as a public base class of the user class.
611
612*  [*Member hook]: The hook is stored as a public member of the user class.
613
614Apart from that, [*Boost.Intrusive] offers additional features:
615
616*  [*Safe mode hooks]: Hook constructor initializes the internal `node` to a well-known
617   safe state and intrusive containers check that state before inserting a value in the
618   container using that hook. When erasing an element from the container, the container
619   puts the `node` of the hook in the safe state again. This allows a safer use mode and it can
620   be used to detect programming errors. It implies a slight performance overhead in some
621   operations and can convert some constant time operations to linear time operations.
622
623*  [*Auto-unlink hooks]: The hook destructor removes the object from the container
624   automatically and the user can safely unlink the object from the container without
625   referring to the container.
626
627*  [*Non-raw pointers]: If the user wants to use smart pointers instead of raw pointers,
628   [*Boost.Intrusive] hooks can
629   be configured to use any type of pointer. This configuration information is also
630   transmitted to the containers, so all the internal pointers used by intrusive containers
631   configured with these hooks will be smart pointers. As an example,
632   [*Boost.Interprocess] defines a smart pointer compatible with shared memory,
633   called `offset_ptr`. [*Boost.Intrusive] can be configured to use this smart pointer
634   to allow shared memory intrusive containers.
635
636[endsect]
637
638[section:safe_hook Safe hooks]
639
640[section:features Features of the safe mode]
641
642[*Boost.Intrusive] hooks can be configured to operate in safe-link mode.
643The safe mode is activated by default, but it can be also explicitly activated:
644
645[c++]
646
647   //Configuring the safe mode explicitly
648   class Foo : public list_base_hook< link_mode<safe_link> >
649   {};
650
651With the safe mode the user can detect if the object
652is actually inserted in a container without any external reference. Let's review the basic features of the safe mode:
653
654*  Hook's constructor puts the hook in a well-known default state.
655
656*  Hook's destructor checks if the hook is in the well-known default state. If not,
657   an assertion is raised.
658
659*  Every time an object is inserted in the intrusive container, the container
660   checks if the hook is in the well-known default state. If not,
661   an assertion is raised.
662
663*  Every time an object is being erased from the intrusive container, the container
664   puts the erased object in the well-known default state.
665
666With these features, without any external reference the user can know if the object
667has been inserted in a container by calling the `is_linked()` member function.
668If the object is not actually inserted
669in a container, the hook is in the default state, and if it is inserted in a container, the
670hook is not in the default state.
671
672[endsect]
673
674[section:configuring Configuring safe-mode assertions]
675
676By default, all safe-mode assertions raised by [*Boost-Intrusive] hooks
677and containers in are implemented using `BOOST_ASSERT`, which can be configured by
678the user. See [@http://www.boost.org/libs/utility/assert.html] for more
679information about `BOOST_ASSERT`.
680
681`BOOST_ASSERT` is globally configured, so the user might
682want to redefine intrusive safe-mode assertions without modifying the global
683`BOOST_ASSERT`. This can be achieved redefining the following macros:
684
685*  `BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT`: This assertion will be
686   used in insertion functions of the intrusive containers to check that
687   the hook of the value to be inserted is default constructed.
688*  `BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT`: This assertion will be
689   used in hooks' destructors to check that the hook is in a default state.
690
691If any of these macros is not redefined, the assertion will default to `BOOST_ASSERT`.
692If `BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT` or `BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT`
693is defined and the programmer needs to include a file to configure that assertion, it can define
694`BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE` or `BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE`
695with the name of the file to include:
696
697[c++]
698
699   #define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT          MYASSERT
700   #define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE <myassert.h>
701
702[endsect]
703
704[endsect]
705
706[section:auto_unlink_hooks Auto-unlink hooks]
707
708[section:auto_unlink_hooks_what What's an auto-unlink hook?]
709
710[*Boost.Intrusive] offers additional hooks with unique features:
711
712*  When the destructor of the hook is called, the hook checks if the node is inserted
713   in a container. If so, the hook removes the node from the container.
714*  The hook has a member function called `unlink()` that can be used to unlink the
715   node from the container at any time, without having any reference to the container,
716   if the user wants to do so.
717
718These hooks have exactly the same size overhead as their analog non auto-unlinking
719hooks, but they have a restriction: they can only be used with
720[link intrusive.presenting_containers non-constant time size containers].
721There is a reason for this:
722
723* Auto-unlink hooks don't store any reference to the container where they are inserted.
724* Only containers with non constant-time `size()` allow removing an object from the container
725  without referring to the container.
726
727This auto-unlink feature is useful in certain applications
728but it must be used [*very carefully]:
729
730*  If several threads are using the same container the destructor of the auto-unlink
731   hook will be called without any thread synchronization so removing the object is
732   thread-unsafe.
733
734*  Container contents change silently without modifying the container directly.
735   This can lead to surprising effects.
736
737These auto-unlink hooks have also safe-mode properties:
738
739*  Hooks' constructors put the hook in a well-known default state.
740
741*  Every time an object is inserted in the intrusive container, the container
742   checks if the hook is in the well-known default state. If not,
743   an assertion is raised.
744
745*  Every time an object is erased from an intrusive container, the container
746   puts the erased object in the well-known default state.
747
748[endsect]
749
750[section:auto_unlink_hooks_example Auto-unlink hook example]
751
752Let's see an example of an auto-unlink hook:
753
754[import ../example/doc_auto_unlink.cpp]
755[doc_auto_unlink_code]
756
757[endsect]
758
759[section:auto_unlink_and_constant_time Auto-unlink hooks and containers with constant-time `size()`]
760
761As explained, [*Boost.Intrusive] auto-unlink hooks are incompatible with containers
762that have constant-time `size()`, so if you try to define such container with an
763auto-unlink hook's value_traits, you will get a static assertion:
764
765[c++]
766
767   #include <boost/intrusive/list.hpp>
768
769   using boost::intrusive;
770
771   struct MyTag;
772
773   class MyClass : public list_base_hook< link_mode<auto_unlink> >
774   {/**/};
775
776   list <MyClass, constant_time_size<true> > bad_list;
777
778   int main()
779   {
780      bad_list list;
781      return 0;
782   }
783
784leads to an error similar to:
785
786[pre
787  error : use of undefined type 'boost::STATIC_ASSERTION_FAILURE<false>'
788]
789
790Pointing to code like this:
791
792[c++]
793
794   //Constant-time size is incompatible with auto-unlink hooks!
795   BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink)));
796
797This way, there is no way to compile a program if you try to use auto-unlink hooks
798in constant-time size containers.
799
800[endsect]
801
802[endsect]
803
804[section:slist Intrusive singly linked list: slist]
805
806[classref boost::intrusive::slist slist] is the simplest intrusive container of
807[*Boost.Intrusive]: a singly linked list. The memory overhead
808it imposes is 1 pointer per node. The size of an empty, non constant-time size
809[classref boost::intrusive::slist slist] is the size of 1 pointer. This
810lightweight memory overhead comes with drawbacks, though: many operations have
811linear time complexity, even some that usually are constant time, like
812[classref boost::intrusive::slist::swap swap]. [classref boost::intrusive::slist slist]
813only provides forward iterators.
814
815For most cases, a doubly linked list is preferable because it offers more
816constant-time functions with a slightly bigger size overhead.
817However, for some applications like
818constructing more elaborate containers, singly linked lists are essential
819because of their low size overhead.
820
821[section:slist_hooks slist hooks]
822
823Like the rest of [*Boost.Intrusive] containers,
824[classref boost::intrusive::slist slist] has two hook types:
825
826[c++]
827
828   template <class ...Options>
829   class slist_base_hook;
830
831*  [classref boost::intrusive::slist_base_hook slist_base_hook]:
832   the user class derives publicly from
833   [classref boost::intrusive::slist_base_hook slist_base_hook] to make
834   it [classref boost::intrusive::slist slist]-compatible.
835
836[c++]
837
838   template <class ...Options>
839   class slist_member_hook;
840
841*  [classref boost::intrusive::slist_member_hook slist_member_hook]:
842   the user class contains a public
843   [classref boost::intrusive::slist_member_hook slist_member_hook] to make
844   it [classref boost::intrusive::slist slist]-compatible.
845
846[classref boost::intrusive::slist_base_hook slist_base_hook] and
847[classref boost::intrusive::slist_member_hook slist_member_hook]
848receive the same options explained in
849the section [link intrusive.usage How to use Boost.Intrusive]:
850
851*  [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
852   so you can derive from more than one slist hook.
853   Default: `tag<default_tag>`.
854
855*  [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
856   Default: `link_mode<safe_link>`.
857
858*  [*`void_pointer<class VoidPointer>`]: The pointer type to be used
859   internally in the hook and propagated to the container.
860   Default: `void_pointer<void*>`.
861
862[endsect]
863
864[section:slist_container slist container]
865
866[c++]
867
868   template <class T, class ...Options>
869   class slist;
870
871[classref boost::intrusive::slist slist] receives the options explained in
872the section [link intrusive.usage How to use Boost.Intrusive]:
873
874*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
875   [*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
876   to configure the container. (To learn about value traits go to the section
877   [link intrusive.value_traits Containers with custom ValueTraits].)
878
879*  [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
880   Default: `constant_time_size<true>`
881
882*  [*`size_type<typename SizeType>`]: To specify the type that will be used to store the size
883   of the container. Default: `size_type<std::size_t>`.
884
885[classref boost::intrusive::slist slist] can receive additional options:
886
887*  [*`linear<bool Enable>`]: the singly linked list is implemented as a
888   null-terminated list instead of a circular list. This allows `O(1)` swap,
889   but losses some operations like `container_from_end_iterator`.
890*  [*`cache_last<bool Enable>`]: `slist` also stores a pointer to the
891   last element of the singly linked list. This allows `O(1)` swap,
892   `splice_after(iterator, slist &)` and makes the list offer new functions
893   like `push_back(reference)` and `back()`. Logically, the size an empty list is
894   increased in `sizeof(void_pointer)` and the cached last node pointer must
895   be updated in every operation, and that might incur in a slight performance impact.
896
897`auto_unlink` hooks are not usable if `linear<true>` and/or `cache_last<true>` options are
898used. If `auto_unlink` hooks are used and those options are specified, a static
899assertion will be raised.
900
901[endsect]
902
903[section:slist_example Example]
904
905Now let's see a small example using both hooks:
906
907[import ../example/doc_slist.cpp]
908[doc_slist_code]
909
910[endsect]
911
912[endsect]
913
914[section:list Intrusive doubly linked list: list]
915
916[classref boost::intrusive::list list] is a doubly linked list. The memory overhead
917it imposes is 2 pointers per node. An empty, non constant-time size [classref boost::intrusive::list list]
918also has the size of 2 pointers. [classref boost::intrusive::list list]
919has many more constant-time operations than [classref boost::intrusive::slist slist]
920and provides a bidirectional iterator. It is recommended to use
921[classref boost::intrusive::list list] instead of
922[classref boost::intrusive::slist slist] if the size overhead is acceptable:
923
924[section:list_hooks list hooks]
925
926Like the rest of [*Boost.Intrusive] containers,
927[classref boost::intrusive::list list] has two hook types:
928
929[c++]
930
931   template <class ...Options>
932   class list_base_hook;
933
934*  [classref boost::intrusive::list_base_hook list_base_hook]: the user class
935   derives publicly from [classref boost::intrusive::list_base_hook list_base_hook]
936   to make it [classref boost::intrusive::list list]-compatible.
937
938[c++]
939
940   template <class ...Options>
941   class list_member_hook;
942
943*  [classref boost::intrusive::list_member_hook list_member_hook]:
944   the user class contains a public
945   [classref boost::intrusive::list_member_hook list_member_hook] to make
946   it [classref boost::intrusive::list list]-compatible.
947
948[classref boost::intrusive::list_base_hook list_base_hook] and
949[classref boost::intrusive::list_member_hook list_member_hook] receive
950the same options explained in the section
951[link intrusive.usage How to use Boost.Intrusive]:
952
953*  [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
954   so you can derive from more than one list hook.
955   Default: `tag<default_tag>`.
956
957*  [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
958   Default: `link_mode<safe_link>`.
959
960*  [*`void_pointer<class VoidPointer>`]: The pointer type to be used
961   internally in the hook and propagated to the container.
962   Default: `void_pointer<void*>`.
963
964[endsect]
965
966[section:list_container list container]
967
968[c++]
969
970   template <class T, class ...Options>
971   class list;
972
973[classref boost::intrusive::list list] receives the same options explained in
974the section [link intrusive.usage How to use Boost.Intrusive]:
975
976*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
977   [*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
978   to configure the container. (To learn about value traits go to the section
979   [link intrusive.value_traits Containers with custom ValueTraits].)
980
981*  [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
982   Default: `constant_time_size<true>`
983
984*  [*`size_type<typename SizeType>`]: To specify the type that will be used to store the size
985   of the container. Default: `size_type<std::size_t>`
986
987[endsect]
988
989[section:list_example Example]
990
991Now let's see a small example using both hooks:
992
993[import ../example/doc_list.cpp]
994[doc_list_code]
995
996[endsect]
997
998[endsect]
999
1000[section:set_multiset Intrusive associative containers: set, multiset, rbtree]
1001
1002[*Boost.Intrusive] also offers associative containers that can be very useful
1003when creating more complex associative containers, like containers maintaining
1004one or more indices with different sorting semantics. Boost.Intrusive associative
1005containers, like most STL associative container implementations are based on
1006red-black trees.
1007
1008The memory overhead of these containers is usually 3 pointers and a bit (with
1009alignment issues, this means 3 pointers and an integer).
1010This size can be reduced to 3 pointers if pointers have even alignment
1011(which is usually true in most systems).
1012
1013An empty, non constant-time size [classref boost::intrusive::set set],
1014[classref boost::intrusive::multiset multiset] or
1015[classref boost::intrusive::rbtree rbtree]
1016has also the size of 3 pointers and an integer (3 pointers when optimized for size).
1017These containers have logarithmic complexity in many
1018operations like
1019searches, insertions, erasures, etc. [classref boost::intrusive::set set] and
1020[classref boost::intrusive::multiset multiset] are the
1021intrusive equivalents of standard `std::set` and `std::multiset` containers.
1022
1023[classref boost::intrusive::rbtree rbtree] is a superset of
1024[classref boost::intrusive::set set] and
1025[classref boost::intrusive::multiset multiset] containers that offers
1026functions to insert unique and multiple keys.
1027
1028[section:set_multiset_hooks set, multiset and rbtree hooks]
1029
1030[classref boost::intrusive::set set],
1031[classref boost::intrusive::multiset multiset] and
1032[classref boost::intrusive::rbtree rbtree] share the same hooks.
1033This is an advantage, because the same
1034user type can be inserted first in a [classref boost::intrusive::multiset multiset]
1035and after that in [classref boost::intrusive::set set] without
1036changing the definition of the user class.
1037
1038[c++]
1039
1040   template <class ...Options>
1041   class set_base_hook;
1042
1043*  [classref boost::intrusive::set_base_hook set_base_hook]:
1044   the user class derives publicly from
1045   [classref boost::intrusive::set_base_hook set_base_hook] to make
1046   it [classref boost::intrusive::set set]/[classref boost::intrusive::multiset multiset]-compatible.
1047
1048[c++]
1049
1050   template <class ...Options>
1051   class set_member_hook;
1052
1053*  [classref boost::intrusive::set_member_hook set_member_hook]:
1054   the user class contains a public
1055   [classref boost::intrusive::set_member_hook set_member_hook] to make
1056   it [classref boost::intrusive::set set]/[classref boost::intrusive::multiset multiset]-compatible.
1057
1058[classref boost::intrusive::set_base_hook set_base_hook] and
1059[classref boost::intrusive::set_member_hook set_member_hook] receive
1060the same options explained in the section
1061[link intrusive.usage How to use Boost.Intrusive] plus a size optimization option:
1062
1063*  [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
1064   so you can derive from more than one base hook.
1065   Default: `tag<default_tag>`.
1066
1067*  [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
1068   Default: `link_mode<safe_link>`.
1069
1070*  [*`void_pointer<class VoidPointer>`]: The pointer type to be used
1071   internally in the hook and propagated to the container.
1072   Default: `void_pointer<void*>`.
1073
1074*  [*`optimize_size<bool Enable>`]: The hook will be optimized for size
1075   instead of speed. The hook will embed the color bit of the red-black
1076   tree node in the parent pointer if pointer alignment is even.
1077   In some platforms, optimizing the size might reduce speed performance a bit
1078   since masking operations will be needed to access parent pointer and color attributes,
1079   in other platforms this option improves performance due to improved memory locality.
1080   Default: `optimize_size<false>`.
1081
1082[endsect]
1083
1084[section:set_multiset_containers set, multiset and rbtree containers]
1085
1086[c++]
1087
1088   template <class T, class ...Options>
1089   class set;
1090
1091   template <class T, class ...Options>
1092   class multiset;
1093
1094   template <class T, class ...Options>
1095   class rbtree;
1096
1097These containers receive the same options explained in the section
1098[link intrusive.usage How to use Boost.Intrusive]:
1099
1100*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
1101   [*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
1102   to configure the container. (To learn about value traits go to the section
1103   [link intrusive.value_traits Containers with custom ValueTraits].)
1104
1105*  [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
1106   Default: `constant_time_size<true>`
1107
1108*  [*`size_type<typename SizeType>`]: To specify the type that will be used to store the size
1109   of the container. Default: `size_type<std::size_t>`
1110
1111And they also can receive an additional option:
1112
1113*  [*`compare<class Compare>`]: Comparison function for the objects to be inserted
1114   in containers. The comparison functor must induce a strict weak ordering.
1115   Default: `compare< std::less<key_type> >`
1116
1117*  [*`key_of_value<class KeyOfValueFunctionObject>`]: A function object that will
1118   define the `key_type` of the value type to be stored. This type will allow a map-like interface. See
1119   [link intrusive.map_multimap Map and multimap-like interface with set and multiset]
1120   for details. Default: `key_type` is equal to `value_type` (set-like interface).
1121
1122[endsect]
1123
1124[section:set_multiset_example Example]
1125
1126Now let's see a small example using both hooks and both containers:
1127
1128[import ../example/doc_set.cpp]
1129[doc_set_code]
1130
1131[endsect]
1132
1133[endsect]
1134
1135[section:unordered_set_unordered_multiset Semi-Intrusive unordered associative containers: unordered_set, unordered_multiset]
1136
1137[*Boost.Intrusive] also offers hashed containers that can be very useful to implement
1138fast-lookup containers.  These containers
1139([classref boost::intrusive::unordered_set unordered_set] and [classref boost::intrusive::unordered_multiset unordered_multiset])
1140are semi-intrusive containers: they need additional memory apart from the hook
1141stored in the `value_type`. This additional
1142memory must be passed in the constructor of the container.
1143
1144Unlike C++ TR1 unordered associative containers (which are also hashed containers),
1145the contents of these semi-intrusive containers are not rehashed to maintain a
1146load factor: that would require memory management and intrusive containers don't
1147implement any memory management at all. However, the user can request an explicit
1148rehashing passing a new bucket array.
1149This also offers an additional guarantee over TR1 unordered associative containers:
1150[*iterators are not invalidated when inserting an element] in the container.
1151
1152As with TR1 unordered associative containers, rehashing invalidates iterators,
1153changes ordering between elements and changes which buckets elements appear in,
1154but does not invalidate pointers or references to elements.
1155
1156Apart from expected hash and equality function objects, [*Boost.Intrusive] unordered
1157associative containers' constructors take an argument specifying an auxiliary
1158bucket vector to be used by the container.
1159
1160[section:unordered_set_unordered_multiset_performance unordered_set and unordered_multiset performance notes]
1161
1162The size overhead for a hashed container is moderate: 1 pointer per value plus
1163a bucket array per container. The size of an element of the bucket array
1164is usually one pointer. To obtain a good performance hashed container,
1165the bucket length is usually the same as the number of elements that the
1166container contains, so a well-balanced hashed container (`bucket_count()` is
1167equal to `size()` ) will have an equivalent overhead of two pointers per element.
1168
1169An empty, non constant-time size [classref boost::intrusive::unordered_set unordered_set] or
1170[classref boost::intrusive::unordered_multiset unordered_multiset]
1171has also the size of `bucket_count()` pointers.
1172
1173Insertions, erasures, and searches, have amortized constant-time complexity in
1174hashed containers. However, some worst-case guarantees are linear. See
1175[classref boost::intrusive::unordered_set unordered_set] or
1176[classref boost::intrusive::unordered_multiset unordered_multiset] for complexity guarantees
1177of each operation.
1178
1179[*Be careful with non constant-time size hashed containers]: some operations, like
1180`empty()`, have linear complexity, unlike other [*Boost.Intrusive] containers.
1181
1182[endsect]
1183
1184[section:unordered_set_unordered_multiset_hooks unordered_set and unordered_multiset hooks]
1185
1186[classref boost::intrusive::unordered_set unordered_set] and [classref boost::intrusive::unordered_multiset unordered_multiset] share the same hooks. This is an advantage, because the same
1187user type can be inserted first in a [classref boost::intrusive::unordered_multiset unordered_multiset] and after that in [classref boost::intrusive::unordered_set unordered_set] without
1188changing the definition of the user class.
1189
1190[c++]
1191
1192   template <class ...Options>
1193   class unordered_set_base_hook;
1194
1195*  [classref boost::intrusive::unordered_set_base_hook unordered_set_base_hook]:
1196   the user class derives publicly from
1197   [classref boost::intrusive::unordered_set_base_hook unordered_set_base_hook] to make
1198   it [classref boost::intrusive::unordered_set unordered_set]/[classref boost::intrusive::unordered_multiset unordered_multiset]-compatible.
1199
1200[c++]
1201
1202   template <class ...Options>
1203   class unordered_set_member_hook;
1204
1205*  [classref boost::intrusive::unordered_set_member_hook unordered_set_member_hook]:
1206   the user class contains a public
1207   [classref boost::intrusive::unordered_set_member_hook unordered_set_member_hook] to make
1208   it [classref boost::intrusive::unordered_set unordered_set]/[classref boost::intrusive::unordered_multiset unordered_multiset]-compatible.
1209
1210[classref boost::intrusive::unordered_set_base_hook unordered_set_base_hook] and
1211[classref boost::intrusive::unordered_set_member_hook unordered_set_member_hook] receive
1212the same options explained in the section
1213[link intrusive.usage How to use Boost.Intrusive]:
1214
1215*  [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
1216   so you can derive from more than one base hook.
1217   Default: `tag<default_tag>`.
1218
1219*  [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
1220   Default: `link_mode<safe_link>`.
1221
1222*  [*`void_pointer<class VoidPointer>`]: The pointer type to be used
1223   internally in the hook and propagated to the container.
1224   Default: `void_pointer<void*>`.
1225
1226Apart from them, these hooks offer additional options:
1227
1228*  [*`store_hash<bool Enabled>`]: This option reserves additional space in
1229   the hook to store the hash value of the object once it's introduced in the
1230   container. When this option is used, the unordered container will store
1231   the calculated hash value in the hook and rehashing operations won't need
1232   to recalculate the hash of the value.
1233   This option will improve the performance of unordered containers when
1234   rehashing is frequent or hashing the value is a slow operation.
1235   Default: `store_hash<false>`.
1236
1237*  [*`optimize_multikey<bool Enabled>`]: This option reserves additional space in
1238   the hook that will be used to group equal elements in unordered multisets,
1239   improving significantly the performance when many equal values are inserted
1240   in these containers. Default: `optimize_multikey<false>`.
1241
1242[endsect]
1243
1244[section:unordered_set_unordered_multiset_containers unordered_set and unordered_multiset containers]
1245
1246[c++]
1247
1248   template<class T, class ...Options>
1249   class unordered_set;
1250
1251   template<class T, class ...Options>
1252   class unordered_multiset;
1253
1254As mentioned, unordered containers need an auxiliary array to work. [*Boost.Intrusive]
1255unordered containers receive this auxiliary array packed in a type called `bucket_traits`
1256(which can be also customized by a container option). All unordered containers receive
1257a `bucket_traits` object in their constructors. The default `bucket_traits` class
1258is initialized with a pointer to an array of buckets and its size:
1259
1260[c++]
1261
1262   #include <boost/intrusive/unordered_set.hpp>
1263
1264   using namespace boost::intrusive;
1265
1266   struct MyClass : public unordered_set_base_hook<>
1267   {};
1268
1269   typedef unordered_set<MyClass>::bucket_type     bucket_type;
1270   typedef unordered_set<MyClass>::bucket_traits   bucket_traits;
1271
1272   int main()
1273   {
1274      bucket_type buckets[100];
1275      unordered_set<MyClass> uset(bucket_traits(buckets, 100));
1276      return 0;
1277   }
1278
1279Each hashed container needs [*its own bucket traits], that is, [*its own
1280bucket vector]. Two hashed containers
1281[*can't] share the same `bucket_type` elements. The bucket array [*must] be
1282destroyed [*after] the container using it is destroyed, otherwise, the result
1283is undefined.
1284
1285[classref boost::intrusive::unordered_set unordered_set] and
1286[classref boost::intrusive::unordered_multiset unordered_multiset]
1287receive the same options explained in the section
1288[link intrusive.usage How to use Boost.Intrusive]:
1289
1290*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
1291   [*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
1292   to configure the container. (To learn about value traits go to the section
1293   [link intrusive.value_traits Containers with custom ValueTraits].)
1294
1295*  [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
1296   Default: `constant_time_size<true>`
1297
1298*  [*`size_type<typename SizeType>`]: To specify the type that will be used to store the size
1299   of the container. Default: `size_type<std::size_t>`
1300
1301And they also can receive additional options:
1302
1303*  [*`equal<class Equal>`]: Equality function for the objects to be inserted
1304   in containers. Default: `equal< std::equal_to<T> >`
1305
1306*  [*`hash<class Hash>`]: Hash function to be used in the container.
1307   Default: `hash< boost::hash<T> >`
1308
1309*  [*`bucket_traits<class BucketTraits>`]: A type that wraps the bucket vector to
1310   be used by the unordered container. Default: a type initialized by the address
1311   and size of a bucket array and stores both variables internally.
1312
1313*  [*`power_2_buckets<bool Enabled>`]: The user guarantees that only bucket arrays
1314   with power of two length will be used. The container will then use masks instead of modulo
1315   operations to obtain the bucket number from the hash value. Masks are faster than
1316   modulo operations and for some applications modulo operations can impose
1317   a considerable overhead. In debug mode an assertion will be raised if the user
1318   provides a bucket length that is not power of two.
1319   Default: `power_2_buckets<false>`.
1320
1321*  [*`cache_begin<bool Enabled>`]:
1322   [*Note: this option is not compatible with `auto_unlink` hooks].
1323   Due to its internal structure, finding the first
1324   element of an unordered container (`begin()` operation) is
1325   amortized constant-time. It's possible to speed up `begin()` and other operations
1326   related to it (like `clear()`) if the container caches internally the position
1327   of the first element. This imposes the overhead of one pointer to the size
1328   of the container. Default: `cache_begin<false>`.
1329
1330*  [*`compare_hash<bool Enabled>`]:
1331   [*Note: this option requires `store_hash<true>` option in the hook].
1332   When the comparison function is expensive,
1333   (e.g. strings with a long common predicate) sometimes (specially when the
1334   load factor is high or we have many equivalent elements in an
1335   [classref boost::intrusive::unordered_multiset unordered_multiset] and
1336   no `optimize_multikey<>` is activated in the hook)
1337   the equality function is a performance problem. Two equal values must have
1338   equal hashes, so comparing the hash values of two elements before using the
1339   comparison functor can speed up some implementations.
1340
1341*  [*`incremental<bool Enabled>`]: Activates incremental hashing (also known as Linear Hashing).
1342   This option implies `power_2_buckets<true>` and the container will require power of two buckets.
1343   For more information on incremental hashing, see
1344   [@http://en.wikipedia.org/wiki/Linear_hashing `Linear hash` on Wikipedia]
1345   Default: `incremental<false>`
1346
1347*  [*`key_of_value<class KeyOfValueFunctionObject>`]: A function object that will
1348   define the `key_type` of the value type to be stored. This type will allow a map-like interface. See
1349   [link intrusive.map_multimap Map and multimap-like interface with set and multiset]
1350   for details. Default: `key_type` is equal to `value_type` (set-like interface).
1351
1352[endsect]
1353
1354[section:unordered_set_unordered_multiset_example Example]
1355
1356Now let's see a small example using both hooks and both containers:
1357
1358[import ../example/doc_unordered_set.cpp]
1359[doc_unordered_set_code]
1360
1361[endsect]
1362
1363[section:custom_bucket_traits Custom bucket traits]
1364
1365Instead of using the default `bucket_traits` class to store the bucket array, a user
1366can define his own class to store the bucket array using the [*['bucket_traits<>]]
1367option. A user-defined bucket-traits must fulfill the following interface:
1368
1369[c++]
1370
1371   class my_bucket_traits
1372   {
1373      bucket_ptr        bucket_begin();
1374      const_bucket_ptr  bucket_begin() const;
1375      std::size_t bucket_count() const;
1376   };
1377
1378
1379The following bucket traits just stores a pointer to the bucket
1380array but the size is a compile-time constant. Note the use of the auxiliary
1381[classref boost::intrusive::unordered_bucket unordered_bucket] and
1382[classref boost::intrusive::unordered_bucket_ptr unordered_bucket_ptr]
1383utilities to obtain the type of the bucket and its pointer before defining
1384the unordered container:
1385
1386[import ../example/doc_bucket_traits.cpp]
1387[doc_bucket_traits]
1388
1389[endsect]
1390
1391[endsect]
1392
1393[section:map_multimap Map and multimap-like interface for associative containers]
1394
1395Implementing map-like intrusive containers is not a trivial task as
1396STL's `std::map` and `std::multimap` containers store copies of a `value_type` which is defined
1397as `std::pair<const key_type, mapped_type>`. In order to reproduce this interface in [*Boost.Intrusive]
1398it shall require that objects stored in the intrusive containers contain that `std::pair` member with
1399`pair.first` hardcoded as the key part and `pair.second` hardcoded as the `mapped_type`, which
1400is limiting and also not very useful in practice. Any intrusive associative container can be used like
1401a map using [link intrusive.advanced_lookups_insertions advanced lookup and insertions] and the user
1402can change the key type in each lookup/insertion check call.
1403
1404On the other hand, in many cases containers are indexed by a well-known key type, and the user is forced
1405to write some repetitive code using advanced lookup and insertions. [*Boost.Intrusive]
1406associative containers offer an alternative to build a useful map-like lookup interfaces
1407without forcing users to define `value_type`s containing `std::pair`-like classes.
1408The option is called [classref boost::intrusive::key_of_value].
1409
1410If a user specifies that option when defining a `set/multiset` intrusive container, it specifies a function object
1411that will tell the container which is the type of the ['key] that `value_type` holds and how to obtain it. This
1412function object must be:
1413
1414* Lightweight to copy.
1415* Default constructible (when the container constructor overload requires it).
1416* It shall define:
1417   * A `type` member that defines the type of the key
1418   * A member function that returns the key derived a `value_type`, either by value or by const-reference.
1419
1420Let's see an example of how a set can be configured as a map indexed by an integer stored in the `value_type`:
1421
1422[import ../example/doc_map.cpp]
1423[doc_map_code]
1424
1425[endsect]
1426
1427[section:avl_set_multiset Intrusive avl tree based associative containers: avl_set, avl_multiset and avltree]
1428
1429Similar to red-black trees, AVL trees are balanced binary trees.
1430AVL trees are often compared with red-black trees because they support the same set of operations
1431and because both take O(log n) time for basic operations.
1432AVL trees are more rigidly balanced than Red-Black trees, leading to slower insertion and
1433removal but faster retrieval, so AVL trees perform better
1434than red-black trees for lookup-intensive applications.
1435
1436[*Boost.Intrusive] offers 3 containers based on avl trees:
1437[classref boost::intrusive::avl_set avl_set],
1438[classref boost::intrusive::avl_multiset avl_multiset] and
1439[classref boost::intrusive::avltree avltree]. The first two are similar to
1440[classref boost::intrusive::set set] or
1441[classref boost::intrusive::multiset multiset] and the latter is a generalization
1442that offers functions both to insert unique and multiple keys.
1443
1444The memory overhead of these containers with Boost.Intrusive hooks is usually 3
1445pointers and 2 bits (due to alignment, this usually means 3 pointers plus an integer).
1446This size can be reduced to 3 pointers if pointers have 4 byte alignment
1447(which is usually true in 32 bit systems).
1448
1449An empty, non constant-time size [classref boost::intrusive::avl_set avl_set],
1450[classref boost::intrusive::avl_multiset avl_multiset] or
1451[classref boost::intrusive::avltree avltree]
1452also has a size of 3 pointers and an integer (3 pointers when optimized for size).
1453
1454[section:avl_set_multiset_hooks avl_set, avl_multiset and avltree hooks]
1455
1456[classref boost::intrusive::avl_set avl_set],
1457[classref boost::intrusive::avl_multiset avl_multiset] and
1458[classref boost::intrusive::avltree avltree]
1459share the same hooks.
1460
1461[c++]
1462
1463   template <class ...Options>
1464   class avl_set_base_hook;
1465
1466*  [classref boost::intrusive::avl_set_base_hook avl_set_base_hook]:
1467   the user class derives publicly from this class to make
1468   it compatible with avl tree based containers.
1469
1470[c++]
1471
1472   template <class ...Options>
1473   class avl_set_member_hook;
1474
1475*  [classref boost::intrusive::set_member_hook set_member_hook]:
1476   the user class contains a public member of this class to make
1477   it compatible with avl tree based containers.
1478
1479[classref boost::intrusive::avl_set_base_hook avl_set_base_hook] and
1480[classref boost::intrusive::avl_set_member_hook avl_set_member_hook] receive
1481the same options explained in the section
1482[link intrusive.usage How to use Boost.Intrusive] plus an option to optimize
1483the size of the node:
1484
1485*  [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
1486   so you can derive from more than one base hook.
1487   Default: `tag<default_tag>`.
1488
1489*  [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
1490   Default: `link_mode<safe_link>`.
1491
1492*  [*`void_pointer<class VoidPointer>`]: The pointer type to be used
1493   internally in the hook and propagated to the container.
1494   Default: `void_pointer<void*>`.
1495
1496*  [*`optimize_size<bool Enable>`]: The hook will be optimized for size
1497   instead of speed. The hook will embed the balance bits of the AVL
1498   tree node in the parent pointer if pointer alignment is multiple of 4.
1499   In some platforms, optimizing the size might reduce speed performance a bit
1500   since masking operations will be needed to access parent pointer and balance factor attributes,
1501   in other platforms this option improves performance due to improved memory locality.
1502   Default: `optimize_size<false>`.
1503
1504[endsect]
1505
1506[section:set_multiset_containers avl_set, avl_multiset and avltree containers]
1507
1508[c++]
1509
1510   template <class T, class ...Options>
1511   class avl_set;
1512
1513   template <class T, class ...Options>
1514   class avl_multiset;
1515
1516   template <class T, class ...Options>
1517   class avltree;
1518
1519These containers receive the same options explained in the section
1520[link intrusive.usage How to use Boost.Intrusive]:
1521
1522*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
1523   [*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
1524   to configure the container. (To learn about value traits go to the section
1525   [link intrusive.value_traits Containers with custom ValueTraits].)
1526
1527*  [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
1528   Default: `constant_time_size<true>`
1529
1530*  [*`size_type<typename SizeType>`]: To specify the type that will be used to store the size
1531   of the container. Default: `size_type<std::size_t>`
1532
1533And they also can receive an additional option:
1534
1535*  [*`compare<class Compare>`]: Comparison function for the objects to be inserted
1536   in containers. The comparison functor must induce a strict weak ordering.
1537   Default: `compare< std::less<key_type> >`
1538
1539*  [*`key_of_value<class KeyOfValueFunctionObject>`]: A function object that will
1540   define the `key_type` of the value type to be stored. This type will allow a map-like interface. See
1541   [link intrusive.map_multimap Map and multimap-like interface with set and multiset]
1542   for details. Default: `key_type` is equal to `value_type` (set-like interface).
1543
1544[endsect]
1545
1546[section:avl_set_multiset_example Example]
1547
1548Now let's see a small example using both hooks and
1549[classref boost::intrusive::avl_set avl_set]/
1550[classref boost::intrusive::avl_multiset avl_multiset]
1551containers:
1552
1553[import ../example/doc_avl_set.cpp]
1554[doc_avl_set_code]
1555
1556[endsect]
1557
1558[endsect]
1559
1560[section:splay_set_multiset Intrusive splay tree based associative containers: splay_set, splay_multiset and , splay_tree]
1561
1562C++ associative containers are usually based on red-black tree implementations (e.g.: STL,
1563Boost.Intrusive associative containers). However, there are other interesting data
1564structures that offer some advantages (and also disadvantages).
1565
1566Splay trees are self-adjusting binary search trees used typically in caches, memory
1567allocators and other applications, because splay trees have a "caching effect": recently
1568accessed elements have better access times than elements accessed less frequently.
1569For more information on splay trees see [@http://en.wikipedia.org/wiki/Splay_tree the corresponding Wikipedia entry].
1570
1571[*Boost.Intrusive] offers 3 containers based on splay trees:
1572[classref boost::intrusive::splay_set splay_set],
1573[classref boost::intrusive::splay_multiset splay_multiset] and
1574[classref boost::intrusive::splaytree splaytree]. The first two are similar to
1575[classref boost::intrusive::set set] or
1576[classref boost::intrusive::multiset multiset] and the latter is a generalization
1577that offers functions both to insert unique and multiple keys.
1578
1579The memory overhead of these containers with Boost.Intrusive hooks is usually 3 pointers.
1580An empty, non constant-time size splay container has also a size of 3 pointers.
1581
1582[section:splay_set_multiset_disadvantages Advantages and disadvantages of splay tree based containers]
1583
1584Splay tree based intrusive containers have logarithmic complexity in many
1585operations like searches, insertions, erasures, etc., but if some elements are
1586more frequently accessed than others, splay trees perform faster searches than equivalent
1587balanced binary trees (such as red-black trees).
1588
1589The caching effect offered by splay trees comes with a cost: the tree must be
1590rebalanced when an element is searched. To maintain const-correctness and thread-safety
1591guarantees, this caching effect is not updated when const versions of
1592search functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`,
1593`count()`... are called. This means that using splay-tree based associative containers as drop-in
1594replacements of [classref boost::intrusive::set set]/
1595[classref boost::intrusive::multiset multiset], specially for const search functions,
1596might not result in desired performance improvements.
1597
1598If element searches are randomized, the tree will be continuously srebalanced
1599without taking advantage of the cache effect, so splay trees can offer worse
1600performance than other balanced trees for several search patterns.
1601
1602[*Boost.Intrusive] splay associative containers don't use their own hook types but plain Binary search tree hooks.
1603See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more
1604information about these hooks.
1605
1606[endsect]
1607
1608[section:set_multiset_containers splay_set, splay_multiset and splaytree containers]
1609
1610[c++]
1611
1612   template <class T, class ...Options>
1613   class splay_set;
1614
1615   template <class T, class ...Options>
1616   class splay_multiset;
1617
1618   template <class T, class ...Options>
1619   class splaytree;
1620
1621These containers receive the same options explained in the section
1622[link intrusive.usage How to use Boost.Intrusive]:
1623
1624*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
1625   [*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
1626   to configure the container.  (To learn about value traits go to the section
1627   [link intrusive.value_traits Containers with custom ValueTraits].)
1628
1629*  [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
1630   Default: `constant_time_size<true>`
1631
1632*  [*`size_type<typename SizeType>`]: To specify the type that will be used to store the size
1633   of the container. Default: `size_type<std::size_t>`
1634
1635And they also can receive an additional option:
1636
1637*  [*`compare<class Compare>`]: Comparison function for the objects to be inserted
1638   in containers. The comparison functor must induce a strict weak ordering.
1639   Default: `compare< std::less<key_type> >`
1640
1641*  [*`key_of_value<class KeyOfValueFunctionObject>`]: A function object that will
1642   define the `key_type` of the value type to be stored. This type will allow a map-like interface. See
1643   [link intrusive.map_multimap Map and multimap-like interface with set and multiset]
1644   for details. Default: `key_type` is equal to `value_type` (set-like interface).
1645
1646[endsect]
1647
1648[section:splay_set_multiset_example Example]
1649
1650Now let's see a small example using
1651[classref boost::intrusive::splay_set splay_set]/
1652[classref boost::intrusive::splay_multiset splay_multiset]
1653containers:
1654
1655[import ../example/doc_splay_set.cpp]
1656[doc_splay_set_code]
1657
1658[endsect]
1659
1660[endsect]
1661
1662
1663[section:sg_set_multiset Intrusive scapegoat tree based associative containers: sg_set, sg_multiset and sgtree]
1664
1665A scapegoat tree is a self-balancing binary search tree, that provides worst-case O(log n)
1666lookup time, and O(log n) amortized insertion and deletion time.
1667Unlike other self-balancing binary search trees that provide worst case O(log n) lookup
1668time, scapegoat trees have no additional per-node overhead compared to a regular binary
1669search tree.
1670
1671A binary search tree is said to be weight balanced if half the nodes are on the left
1672of the root, and half on the right. An a-height-balanced tree is defined with defined
1673with the following equation:
1674
1675[*['height(tree) <= log1/a(tree.size())]]
1676
1677*  [*['a == 1]]: A tree forming a linked list is considered balanced.
1678*  [*['a == 0.5]]: Only a perfectly balanced binary is considered balanced.
1679
1680Scapegoat trees are loosely ['a-height-balanced] so:
1681
1682[*['height(tree) <= log1/a(tree.size()) + 1]]
1683
1684Scapegoat trees support any a between 0.5 and 1. If a is higher, the tree is rebalanced
1685less often, obtaining quicker insertions but slower searches. Lower
1686a values improve search times. Scapegoat-trees implemented in [*Boost.Intrusive] offer the possibility of
1687[*changing a at run-time] taking advantage of the flexibility of scapegoat trees.
1688For more information on scapegoat trees see [@http://en.wikipedia.org/wiki/Scapegoat_tree Wikipedia entry].
1689
1690Scapegoat trees also have downsides:
1691
1692*  They need additional storage of data on the
1693   root (the size of the tree, for example) to achieve logarithmic complexity operations
1694   so it's not possible to offer `auto_unlink` hooks. The size of an empty scapegoat
1695   tree is also considerably increased.
1696
1697*  The operations needed to determine if the tree is unbalanced require floating-point
1698   operations like ['log1/a]. If the system has no floating point operations (like some
1699   embedded systems), scapegoat tree operations might become slow.
1700
1701[*Boost.Intrusive] offers 3 containers based on scapegoat trees:
1702[classref boost::intrusive::sg_set sg_set],
1703[classref boost::intrusive::sg_multiset sg_multiset] and
1704[classref boost::intrusive::sgtree sgtree]. The first two are similar to
1705[classref boost::intrusive::set set] or
1706[classref boost::intrusive::multiset multiset] and the latter is a generalization
1707that offers functions both to insert unique and multiple keys.
1708
1709The memory overhead of these containers with Boost.Intrusive hooks is 3
1710pointers.
1711
1712An empty, [classref boost::intrusive::sg_set sg_set],
1713[classref boost::intrusive::sg_multiset sg_multiset] or
1714[classref boost::intrusive::sgtree sgtree]
1715has also the size of 3 pointers, two integers and two floating point values
1716(equivalent to the size of 7 pointers on most systems).
1717
1718[*Boost.Intrusive] scapegoat associative containers don't use their own hook types but plain Binary search tree hooks.
1719See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more
1720information about these hooks.
1721
1722[section:sg_set_multiset_containers sg_set, sg_multiset and sgtree containers]
1723
1724[c++]
1725
1726   template <class T, class ...Options>
1727   class sg_set;
1728
1729   template <class T, class ...Options>
1730   class sg_multiset;
1731
1732   template <class T, class ...Options>
1733   class sgtree;
1734
1735These containers receive the same options explained in the section
1736[link intrusive.usage How to use Boost.Intrusive]:
1737
1738*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
1739   [*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
1740   to configure the container. (To learn about value traits go to the section
1741   [link intrusive.value_traits Containers with custom ValueTraits].)
1742
1743*  [*`size_type<typename SizeType>`]: To specify the type that will be used to store the size
1744   of the container. Default: `size_type<std::size_t>`
1745
1746And they also can receive additional options:
1747
1748*  [*`compare<class Compare>`]: Comparison function for the objects to be inserted
1749   in containers. The comparison functor must induce a strict weak ordering.
1750   Default: `compare< std::less<key_type> >`
1751
1752*  [*`floating_point<bool Enable>`]:
1753   When this option is deactivated, the scapegoat tree loses the ability to change
1754   the balance factor a at run-time, but the size of an empty container is reduced
1755   and no floating point operations are performed, normally increasing container
1756   performance. The fixed a factor that is used when this option is activated
1757   is ['1/sqrt(2) ~ 0,70711]. Default: `floating_point<true>`
1758
1759*  [*`key_of_value<class KeyOfValueFunctionObject>`]: A function object that will
1760   define the `key_type` of the value type to be stored. This type will allow a map-like interface. See
1761   [link intrusive.map_multimap Map and multimap-like interface with set and multiset]
1762   for details. Default: `key_type` is equal to `value_type` (set-like interface).
1763
1764[endsect]
1765
1766[section:sg_set_multiset_example Example]
1767
1768Now let's see a small example using binary search tree hooks and
1769[classref boost::intrusive::sg_set sg_set]/
1770[classref boost::intrusive::sg_multiset sg_multiset]
1771containers:
1772
1773[import ../example/doc_sg_set.cpp]
1774[doc_sg_set_code]
1775
1776[endsect]
1777
1778[endsect]
1779
1780
1781[section:treap_set_multiset Intrusive treap based associative containers: treap_set, treap_multiset and treap]
1782
1783The name ['treap] is a mixture of ['tree] and ['heap] indicating that Treaps exhibit the properties of both
1784binary search trees and heaps. A treap is a binary search tree that orders the nodes
1785by a key but also by a priority attribute. The nodes are ordered so that the keys form a binary search tree and
1786the priorities obey the max heap order property.
1787
1788* If v is a left descendant of u, then key[v] < key[u];
1789* If v is a right descendant of u, then key[v] > key[u];
1790* If v is a child of u, then priority[v] <= priority[u];
1791
1792If priorities are non-random, the tree will usually be unbalanced; this worse theoretical average-case
1793behavior may be outweighed by better expected-case behavior, as the most important items will be near the root.
1794This means most important objects will be retrieved faster than less important items and for items keys with equal keys
1795most important objects will be found first. These properties are important for some applications.
1796
1797The priority comparison will be provided just like the key comparison, via a function object that will be
1798stored in the intrusive container. This means that the priority can be stored in the value to be introduced
1799in the treap or computed on flight (via hashing or similar).
1800
1801[*Boost.Intrusive] offers 3 containers based on treaps:
1802[classref boost::intrusive::treap_set treap_set],
1803[classref boost::intrusive::treap_multiset treap_multiset] and
1804[classref boost::intrusive::treap treap]. The first two are similar to
1805[classref boost::intrusive::set set] or
1806[classref boost::intrusive::multiset multiset] and the latter is a generalization
1807that offers functions both to insert unique and multiple keys.
1808
1809The memory overhead of these containers with Boost.Intrusive hooks is 3
1810pointers.
1811
1812An empty, [classref boost::intrusive::treap_set treap_set],
1813[classref boost::intrusive::treap_multiset treap_multiset] or
1814[classref boost::intrusive::treap treap]
1815has also the size of 3 pointers and an integer (supposing empty function objects for key and priority
1816comparison and constant-time size).
1817
1818[*Boost.Intrusive] treap associative containers don't use their own hook types but plain Binary search tree hooks.
1819See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more
1820information about these hooks.
1821
1822[section:treap_set_multiset_containers treap_set, treap_multiset and treap containers]
1823
1824[c++]
1825
1826   template <class T, class ...Options>
1827   class treap_set;
1828
1829   template <class T, class ...Options>
1830   class treap_multiset;
1831
1832   template <class T, class ...Options>
1833   class treap;
1834
1835These containers receive the same options explained in the section
1836[link intrusive.usage How to use Boost.Intrusive]:
1837
1838*  [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
1839   [*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
1840   to configure the container. (To learn about value traits go to the section
1841   [link intrusive.value_traits Containers with custom ValueTraits].)
1842
1843*  [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
1844   Default: `constant_time_size<true>`
1845
1846*  [*`size_type<typename SizeType>`]: To specify the type that will be used to store the size
1847   of the container. Default: `size_type<std::size_t>`
1848
1849And they also can receive additional options:
1850
1851*  [*`compare<class Compare>`]: Comparison function for the objects to be inserted
1852   in containers. The comparison functor must induce a strict weak ordering.
1853   Default: `compare< std::less<key_type> >`
1854
1855*  [*`priority_of_value<class PriorityOfValue>`]: A function object
1856   that specifies the type of the priority (`priority_type`) of a treap
1857   container and an operator to obtain it from a value type.
1858   Default: `priority_type` is equal to `value_type` (set-like interface).
1859
1860*  [*`priority<class PriorityCompare>`]: Priority Comparison function for the objects to be inserted
1861   in containers. The comparison functor must induce a strict weak ordering.
1862   Default: `priority< priority_compare<priority_type> >`
1863
1864*  [*`key_of_value<class KeyOfValueFunctionObject>`]: A function object that will
1865   define the `key_type` of the value type to be stored. This type will allow a map-like interface. See
1866   [link intrusive.map_multimap Map and multimap-like interface with set and multiset]
1867   for details. Default: `key_type` is equal to `value_type` (set-like interface).
1868
1869The default `priority_compare<T>` object function will call an unqualified function `priority_order`
1870passing two constant `T` references as arguments and should return true if the first argument has
1871higher priority (it will be searched faster), inducing strict weak ordering.
1872The function will be found using ADL lookup so that
1873the user just needs to define a `priority_order` function in the same namespace as the class:
1874
1875[c++]
1876
1877   struct MyType
1878   {
1879      friend bool priority_order(const MyType &a, const MyType &b)
1880      {...}
1881   };
1882
1883or
1884
1885   namespace mytype {
1886
1887   struct MyType{ ... };
1888
1889   bool priority_order(const MyType &a, const MyType &b)
1890   {...}
1891
1892   }  //namespace mytype {
1893
1894[endsect]
1895
1896[section:treap_set_exceptions Exception safety of treap-based intrusive containers]
1897
1898In general, intrusive containers offer strong safety guarantees, but treap containers must deal
1899with two possibly throwing functors (one for value ordering, another for priority ordering).
1900Moreover, treap erasure operations require rotations based on the priority order function and
1901this issue degrades usual `erase(const_iterator)` no-throw guarantee. However, intrusive offers
1902the strongest possible behaviour in these situations. In summary:
1903
1904*  If the priority order functor does not throw, treap-based containers, offer exactly the same
1905   guarantees as other tree-based containers.
1906
1907*  If the priority order functor throws, treap-based containers offer strong guarantee.
1908
1909[endsect]
1910
1911[section:treap_set_multiset_example Example]
1912
1913Now let's see a small example using binary search tree hooks and
1914[classref boost::intrusive::treap_set treap_set]/
1915[classref boost::intrusive::treap_multiset treap_multiset]
1916containers:
1917
1918[import ../example/doc_treap_set.cpp]
1919[doc_treap_set_code]
1920
1921[endsect]
1922
1923[endsect]
1924
1925[section:bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook]
1926
1927Binary search tree hooks can be used with several tree-like containers that don't
1928need any additional metadata for rebalancing operations. This has many advantages
1929since binary search tree hooks can also be used to insert values in
1930plain binary search tree, splay tree, scapegoat tree, and treap containers.
1931
1932[c++]
1933
1934   template <class ...Options>
1935   class bs_set_base_hook;
1936
1937*  [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]:
1938   the user class derives publicly from this class to make
1939   it compatible with the mentioned tree based containers.
1940
1941[c++]
1942
1943   template <class ...Options>
1944   class bs_set_member_hook;
1945
1946*  [classref boost::intrusive::bs_set_member_hook bs_set_member_hook]:
1947   the user class contains a public member of this class to make
1948   it compatible with the mentioned tree based containers.
1949
1950[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and
1951[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive
1952the same options explained in the section
1953[link intrusive.usage How to use Boost.Intrusive]:
1954
1955*  [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
1956   so you can derive from more than one base hook.
1957   Default: `tag<default_tag>`.
1958
1959*  [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
1960   Default: `link_mode<safe_link>`.
1961
1962*  [*`void_pointer<class VoidPointer>`]: The pointer type to be used
1963   internally in the hook and propagated to the container.
1964   Default: `void_pointer<void*>`.
1965
1966[endsect]
1967
1968[section:advanced_lookups_insertions Advanced lookup and insertion functions for associative containers]
1969
1970[section:advanced_lookups Advanced lookups]
1971
1972[*Boost.Intrusive] associative containers offer an interface similar to STL associative
1973containers. However, STL's ordered and unordered simple associative containers
1974(`std::set`, `std::multiset`, `std::unordered_set` and `std::unordered_multiset`)
1975have some inefficiencies caused by the interface in several search, insertion or erasure functions
1976(`equal_range`, `lower_bound`, `upper_bound`, `find`, `insert`, `erase`...): the user can only operate
1977with `value_type` objects or (starting from C++11),
1978[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3657.htm heterogeneous comparison lookups]
1979which are not flexible enough as `key_compare` shall support the comparison between the provided
1980key and `value_type`, which precludes the use of user-defined comparison objects that can partition the
1981search in a compatible but advanced way.
1982
1983To solve these problems, [*Boost.Intrusive] containers offers functions where a key type different
1984from `key_type` and a comparison object are provided by the user. This applies to:
1985   *  equal_range
1986   *  lower_bound
1987   *  upper_bound
1988   *  count
1989   *  find
1990   *  erase
1991
1992Requirements for such functions are:
1993
1994* For unordered container the provided comparison and hashing
1995  function with the given key shall induce the same hash and equivalence as `key_compare` and `hasher`.
1996
1997* For ordered associative containers, lookup and erasure functions, the container to be searched shall
1998  be partitioned in regards to the supplied comparison object and key.
1999
2000For more details, see  [*Requires] clauses of such functions in the reference.
2001
2002[section:advanced_lookups_example Example]
2003
2004Imagine that the object to be searched is quite expensive to construct (called `Expensive` in the example):
2005
2006[import ../example/doc_assoc_optimized_code.cpp]
2007[doc_assoc_optimized_code_normal_find]
2008
2009If "key" c-string is quite long
2010`Expensive` has to construct a `std::string` using heap memory. Like
2011`Expensive`, many times the only member taking part in ordering issues is just
2012a small part of the class. E.g.: with `Expensive`, only the internal
2013`std::string` is needed to compare the object.
2014
2015In both containers, if we call `get_from_set/get_from_unordered_set` in a loop, we might get a performance penalty,
2016because we are forced to create a whole `Expensive` object to be able to find an
2017equivalent one.
2018
2019Sometimes the problem is not only performance-related, as
2020we [*might not have enough information to construct the object] but we might
2021[*have enough information to find the object]. In this case, a name is enough
2022to search `Expensive` objects in the container but constructing an `Expensive`
2023object might require more information that the searcher might not have.
2024
2025To solve this, we can use the functions that take any type comparable with the value and a
2026the 'compatible' comparison object (and hash, when the associative container is unordered)
2027Let's see optimized search function:
2028
2029[doc_assoc_optimized_code_optimized_find]
2030
2031[endsect]
2032
2033[endsect]
2034
2035[section:advanced_insertions Advanced insertions]
2036
2037A similar issue happens with insertions in simple ordered and unordered associative
2038containers with unique keys (`std::set` and `std::unordered_set`). In these containers,
2039if a value is already present, the value to be inserted is discarded. With expensive
2040values, if the value is already present, we can suffer efficiency problems.
2041
2042[classref boost::intrusive::set set] and [classref boost::intrusive::unordered_set unordered_set]-like
2043containers have insertion functions (`insert_check`, `insert_unique_check`,...) to check efficiently, without
2044constructing the value, if a value is present or not and if it's not present, a
2045function to insert it immediately (`insert_commit`) without any further lookup. Requirements for functions
2046that check the existence of such value are:
2047
2048* For unordered container the provided comparison and hashing
2049  function with the given key shall induce the same hash and equivalence as `key_compare` and `hasher`.
2050
2051* For ordered associative containers, the provided comparison function with the given key, shall induce the same
2052strict weak order as `key_compare`.
2053
2054To sum up, `insert_check` is similar to a normal `insert` but:
2055
2056*  `insert_check` can be used with arbitrary keys
2057*  if the insertion is possible (there is no equivalent value) `insert_check` collects all the needed information
2058in an `insert_commit_data` structure, so that `insert_commit`:
2059   *   [*does not execute] further comparisons
2060   *   can be executed with [*constant-time complexity]
2061   *   has [*no-throw guarantee].
2062
2063These functions must be used with care,
2064no other insertion or erasure must be executed between an `insert_check` and an `insert_commit`
2065pair. Otherwise, the behaviour is undefined.
2066
2067See [classref boost::intrusive::set set]
2068and [classref boost::intrusive::unordered_set unordered_set]-like containers' reference
2069for more information about `insert_check` and `insert_commit`.
2070
2071With multiple ordered and unordered associative containers
2072([classref boost::intrusive::multiset multiset] and
2073[classref boost::intrusive::unordered_multiset unordered_multiset]) there  is
2074no need for these advanced insertion functions, since insertions are always successful.
2075
2076[section:advanced_insertions_example Example]
2077
2078For example, using the same `Expensive` class,
2079this function can be inefficient:
2080
2081[doc_assoc_optimized_code_normal_insert]
2082
2083If the object is already present, we are constructing an `Expensive` that
2084will be discarded, and this is a waste of resources. Instead of that, let's use
2085`insert_check` and `insert_commit` functions:
2086
2087[doc_assoc_optimized_code_optimized_insert]
2088
2089[endsect]
2090
2091[endsect]
2092
2093[section:positional_insertions Positional insertions]
2094
2095Some ordered associative containers offer low-level functions to bypass ordering
2096checks and insert nodes directly in desired tree positions. These functions are
2097provided for performance reasons when values to be inserted in the container are
2098known to fulfill order (sets and multisets) and uniqueness (sets) invariants. A
2099typical usage of these functions is when intrusive associative containers are used
2100to build non-intrusive containers and the programmer wants to speed up assignments
2101from other associative containers: if the ordering and uniqueness properties are the same,
2102there is no need to waste time checking the position of each source value, because values
2103are already ordered: back insertions will be much more efficient.
2104
2105[*Note:] These functions [*don't check preconditions] so they must used with care. They
2106are low-level operations that [*will break container invariants if
2107ordering and uniqueness preconditions are not assured by the caller.]
2108
2109Let's see an example:
2110
2111[import ../example/doc_positional_insertion.cpp]
2112[doc_positional_insertion]
2113
2114[endsect]
2115
2116For more information about advanced lookup and insertion functions see
2117associative containers' documentation (e.g.
2118[classref boost::intrusive::set set],
2119[classref boost::intrusive::multiset multiset],
2120[classref boost::intrusive::unordered_set unordered_set] and
2121[classref boost::intrusive::unordered_multiset unordered_multiset] references).
2122
2123[endsect]
2124
2125[section:erasing_and_disposing Erasing and disposing values from Boost.Intrusive containers]
2126
2127One of the most tedious tasks when using intrusive containers is the management of the erased elements.
2128When using STL containers, the container itself unlinks and destroys the contained elements, but with
2129intrusive containers, the user must explicitly destroy the object after erasing an element from the container.
2130This makes STL-like functions erasing multiple objects unhelpful: the user can't destroy every erased element.
2131For example, let's take the function `remove_if` from [classref boost::intrusive::list list]:
2132
2133[c++]
2134
2135   template<class Pred>
2136   void remove_if(Pred pred);
2137
2138How can the user destroy the elements (say, using `operator delete`) that will be erased according
2139to the predicate? [*Boost.Intrusive] containers offer additional functions that take a function
2140object that will be called after the element has been erased from the container. For example,
2141[classref boost::intrusive::list list] offers:
2142
2143[c++]
2144
2145   template<class Pred, class Disposer>
2146   void remove_and_dispose_if(Pred pred, Disposer disposer)
2147
2148With this function the user can efficiently remove and destroy elements if the disposer
2149function destroys an object: `remove_and_dispose_if`
2150will call the "disposer" function object for every removed element. [classref boost::intrusive::list list] offers
2151more functions taking a disposer function object as argument, like `erase_and_dispose`, `clear_and_dispose`,
2152`remove_and_dispose`, etc.
2153
2154Note that the disposing function does not need to just destroy the object. It can
2155implement any other operation like inserting the remove object in another container.
2156Let's see a small example:
2157
2158[import ../example/doc_erasing_and_disposing.cpp]
2159[doc_erasing_and_disposing]
2160
2161All [*Boost.Intrusive] containers offer these "erase + dispose" additional members for all functions
2162that erase an element from the container.
2163
2164
2165
2166[endsect]
2167
2168[section:clone_from Cloning Boost.Intrusive containers]
2169
2170As previously mentioned, [*Boost.Intrusive] containers are [*non-copyable and non-assignable], because
2171intrusive containers don't allocate memory at all. To implement a copy-constructor or assignment operator,
2172the user must clone one by one all the elements of the container and insert them in another intrusive container.
2173However, cloning by hand is usually more inefficient than a member cloning function and a specialized cloning
2174function can offer more guarantees than the manual cloning (better exception safety guarantees, for example).
2175
2176To ease the implementation of copy constructors and assignment operators of classes containing [*Boost.Intrusive]
2177containers, all [*Boost.Intrusive] containers offer a special cloning function called `clone_from`.
2178
2179Apart from the container to be cloned, `clone_from` takes two function objects as arguments. For example, consider the
2180`clone_from` member function of [classref boost::intrusive::list list]:
2181
2182[c++]
2183
2184   template <class Cloner, class Disposer>
2185   void clone_from(const list &src, Cloner cloner, Disposer disposer);
2186
2187This function will make `*this` a clone of `src`. Let's explain the arguments:
2188
2189*   The first parameter is the list to be cloned.
2190*   The second parameter is a function object that will clone `value_type` objects and
2191   return a pointer to the clone. It must implement the following function:
2192   `pointer operator()(const value_type &)`.
2193*   The second parameter is a function object that will dispose `value_type` objects. It's used first
2194   to empty the container before cloning and to dispose the elements if an exception is thrown.
2195
2196The cloning function works as follows:
2197
2198*   First it clears and disposes all the elements from *this using the disposer function object.
2199*   After that it starts cloning all the elements of the source container using the cloner function object.
2200*   If any operation in the cloning function (for example, the cloner function object) throws,
2201   all the constructed elements are disposed using the disposer function object.
2202
2203
2204Here is an example of `clone_from`:
2205
2206[import ../example/doc_clone_from.cpp]
2207[doc_clone_from]
2208
2209[endsect]
2210
2211[section:function_hooks Using function hooks]
2212
2213A programmer might find that base or member hooks are not flexible enough in some situations.
2214In some applications it would be optimal to put a hook deep inside a member of a class or just outside the class.
2215[*Boost.Intrusive] has an easy option to allow such cases: [classref boost::intrusive::function_hook function_hook].
2216
2217This option is similar to [classref boost::intrusive::member_hook member_hook] or
2218[classref boost::intrusive::base_hook base_hook], but the programmer can specify a function
2219object that tells the container how to obtain a hook from a value and vice versa.
2220The programmer just needs to define the following function object:
2221
2222[c++]
2223
2224   //This functor converts between value_type and a hook_type
2225   struct Functor
2226   {
2227      //Required types
2228      typedef /*impl-defined*/      hook_type;
2229      typedef /*impl-defined*/      hook_ptr;
2230      typedef /*impl-defined*/      const_hook_ptr;
2231      typedef /*impl-defined*/      value_type;
2232      typedef /*impl-defined*/      pointer;
2233      typedef /*impl-defined*/      const_pointer;
2234      //Required static functions
2235      static hook_ptr to_hook_ptr (value_type &value);
2236      static const_hook_ptr to_hook_ptr(const value_type &value);
2237      static pointer to_value_ptr(hook_ptr n);
2238      static const_pointer to_value_ptr(const_hook_ptr n);
2239   };
2240
2241Converting from values to hooks is generally easy, since most hooks are
2242in practice members or base classes of class data members. The inverse operation
2243is a bit more complicated, but [*Boost.Intrusive] offers a bit of help with the function
2244[funcref boost::intrusive::get_parent_from_member get_parent_from_member],
2245which allows easy conversions from the address of a data member to the address of
2246the parent holding that member. Let's see a little example of
2247[classref boost::intrusive::function_hook function_hook]:
2248
2249[import ../example/doc_function_hooks.cpp]
2250[doc_function_hooks]
2251
2252[endsect]
2253
2254
2255[section:recursive Recursive Boost.Intrusive containers]
2256
2257[*Boost.Intrusive] containers can be used to define recursive structures very easily,
2258allowing complex data structures with very low overhead. Let's see an example:
2259
2260[import ../example/doc_recursive.cpp]
2261[doc_recursive]
2262
2263Recursive data structures using [*Boost.Intrusive] containers must avoid using hook deduction to avoid early type
2264instantiation:
2265
2266[c++]
2267
2268  //This leads to compilation error (Recursive is instantiated by
2269  //'list' to deduce hook properties (pointer type, tag, safe-mode...)
2270  class Recursive
2271  {  //...
2272
2273     list< Recursive > l;
2274     //...
2275  };
2276
2277  //Ok, programmer must specify the hook type to avoid early Recursive instantiation
2278  class Recursive
2279  {  //...
2280     list< Recursive, base_hook<BaseHook> > l;
2281     //...
2282  };
2283
2284
2285Member hooks are not suitable for recursive structures:
2286
2287[c++]
2288
2289   class Recursive
2290   {
2291      private:
2292      Recursive(const Recursive&);
2293      Recursive & operator=(const Recursive&);
2294
2295      public:
2296      list_member_hook<> memhook;
2297      list< Recursive, member_hook<Recursive, list_member_hook<>, &Recursive::memhook> > children;
2298   };
2299
2300Specifying `&Recursive::memhook` (that is, the offset between memhook and Recursive) provokes an early
2301instantiation of `Recursive`. To define recursive structures using member hooks, a programmer should use
2302[classref ::boost::interprocess::function_hook function_hook]:
2303
2304[import ../example/doc_recursive_member.cpp]
2305[doc_recursive_member]
2306
2307[endsect]
2308
2309
2310[section:using_smart_pointers Using smart pointers with Boost.Intrusive containers]
2311
2312[*Boost.Intrusive] hooks can be configured to use other pointers than raw pointers.
2313When a [*Boost.Intrusive] hook is configured with a smart pointer as an argument,
2314this pointer configuration is passed to the containers. For example, if the following
2315hook is configured with a smart pointer (for example, an offset pointer from
2316[*Boost.Interprocess]):
2317
2318[import ../example/doc_offset_ptr.cpp]
2319[doc_offset_ptr_0]
2320
2321Any intrusive list constructed using this hook will be ready for shared memory,
2322because the intrusive list will also use offset pointers internally. For example,
2323we can create an intrusive list in shared memory combining [*Boost.Interprocess]
2324and [*Boost.Intrusive]:
2325
2326[doc_offset_ptr_1]
2327
2328[section:smart_pointers_requirements Requirements for smart pointers compatible with Boost.Intrusive]
2329
2330Not every smart pointer is compatible with [*Boost.Intrusive]:
2331
2332* It must be compatible with C++11 [@http://en.cppreference.com/w/cpp/memory/pointer_traits `std::pointer_traits`]
2333   requirements. [*Boost.Intrusive] uses its own [classref boost::intrusive::pointer_traits pointer_traits]
2334   class to implement those features in both C++11 and C++03 compilers.
2335* It must  have the same ownership semantics as a raw pointer. This means that
2336   resource management smart pointers (like `boost::shared_ptr`) can't be used.
2337
2338The conversion from the smart pointer to a raw pointer will be implemented as a recursive call to
2339`operator->()` until the function returns a raw pointer.
2340
2341[endsect]
2342
2343[endsect]
2344
2345[section:obtaining_iterators_from_values Obtaining iterators from values]
2346
2347[*Boost.Intrusive] offers another useful feature that's not present in STL
2348containers: it's possible to obtain an iterator to a value from the value itself.
2349This feature is implemented in [*Boost.Intrusive] containers by a
2350function called `iterator_to`:
2351
2352[c++]
2353
2354   iterator iterator_to(reference value);
2355   const_iterator iterator_to(const_reference value);
2356
2357For [*Boost.Intrusive] containers that have local iterators, like unordered
2358associative containers, we can also obtain local iterators:
2359
2360[c++]
2361
2362   local_iterator local_iterator_to(reference value);
2363   const_local_iterator local_iterator_to(const_reference value) const;
2364
2365For most [*Boost.Intrusive] containers
2366([classref boost::intrusive::list list],
2367[classref boost::intrusive::slist slist],
2368[classref boost::intrusive::set set],
2369[classref boost::intrusive::multiset multiset]) we have an alternative
2370static `s_iterator_to` function.
2371
2372For unordered associative containers
2373([classref boost::intrusive::unordered_set unordered_set],
2374[classref boost::intrusive::multiset multiset]),
2375`iterator_to` has no static alternative function.
2376On the other hand, `local_iterator_to` functions
2377have their `s_local_iterator_to` static alternatives.
2378
2379Alternative static functions are available under certain circumstances
2380explained in the [link intrusive.value_traits.stateful_value_traits Stateful value traits] section;
2381if the programmer uses hooks provided by [*Boost.Intrusive], those functions
2382will be available.
2383
2384Let's see a small function that shows the use of `iterator_to` and
2385`local_iterator_to`:
2386
2387[import ../example/doc_iterator_from_value.cpp]
2388[doc_iterator_from_value]
2389
2390[endsect]
2391
2392[section:any_hooks Any Hooks: A single hook for any Intrusive container]
2393
2394Sometimes, a class programmer wants to place a class in several intrusive
2395containers but no at the same time. In this case, the programmer might
2396decide to insert two hooks in the same class.
2397
2398[c++]
2399
2400   class MyClass
2401      : public list_base_hook<>, public slist_base_hook<> //...
2402   {};
2403
2404However, there is a more size-efficient alternative in [*Boost.Intrusive]: "any" hooks
2405([classref boost::intrusive::any_base_hook any_base_hook] and
2406[classref boost::intrusive::any_member_hook any_member_hook]).
2407These hooks can be used to store a type in several containers
2408offered by [*Boost.Intrusive] minimizing the size of the class.
2409
2410These hooks support these options:
2411
2412*  [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
2413   so you can derive from more than one slist hook.
2414   Default: `tag<default_tag>`.
2415
2416*  [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
2417   `link_mode<auto_unlink>` is [*not] supported and `link_mode<safe_mode>`
2418   might offer weaker error detection in any hooks than in other hooks.
2419   Default: `link_mode<safe_link>`.
2420
2421*  [*`void_pointer<class VoidPointer>`]: The pointer type to be used
2422   internally in the hook and propagated to the container.
2423   Default: `void_pointer<void*>`.
2424
2425`auto_unlink` can't be supported because the hook does not know in which type of
2426container might be currently inserted. Additionally, these hooks don't support `unlink()` and
2427`swap_nodes()` operations for the same reason.
2428
2429Here is an example that creates a class with two any hooks, and uses one to insert the
2430class in a [classref slist] and the other one in a [classref list].
2431
2432[import ../example/doc_any_hook.cpp]
2433[doc_any_hook]
2434
2435[endsect]
2436
2437[section:concepts Concepts explained]
2438
2439This section will expand the explanation of previously presented basic concepts
2440before explaining the customization options of [*Boost.Intrusive].
2441
2442*  [*Node Algorithms]: A set of static functions that implement basic operations
2443   on a group of nodes: initialize a node, link a node to a group of nodes,
2444   unlink a node from another group of nodes, etc. For example, a circular
2445   singly linked list is a group of nodes, where each node has a pointer to the
2446   next node. [*Node Algorithms] just require a [*NodeTraits]
2447   template parameter and they can work with any [*NodeTraits] class that fulfills
2448   the needed interface. As an example, here is a class that implements operations
2449   to manage a group of nodes forming a circular singly linked list:
2450
2451[c++]
2452
2453   template<class NodeTraits>
2454   struct my_slist_algorithms
2455   {
2456      typedef typename NodeTraits::node_ptr       node_ptr;
2457      typedef typename NodeTraits::const_node_ptr const_node_ptr;
2458
2459      //Get the previous node of "this_node"
2460      static node_ptr get_prev_node(node_ptr this_node)
2461      {
2462         node_ptr p = this_node;
2463         while (this_node != NodeTraits::get_next(p))
2464            p = NodeTraits::get_next(p);
2465         return p;
2466      }
2467
2468      // number of elements in the group of nodes containing "this_node"
2469      static std::size_t count(const_node_ptr this_node)
2470      {
2471         std::size_t result = 0;
2472         const_node_ptr p = this_node;
2473         do{
2474            p = NodeTraits::get_next(p);
2475            ++result;
2476         } while (p != this_node);
2477         return result;
2478      }
2479
2480      // More operations
2481      // ...
2482   };
2483
2484*  [*Node Traits]: A class that encapsulates the basic information and
2485   operations on a node within a group of nodes:
2486   the type of the node, a function to obtain the pointer to the next node, etc.
2487   [*Node Traits] specify the configuration information [*Node Algorithms]
2488   need. Each type of [*Node Algorithm] expects an interface that compatible
2489   [*Node Traits] classes must implement.
2490   As an example, this is the definition of a [*Node Traits] class that
2491   is compatible with the previously presented `my_slist_algorithms`:
2492
2493[c++]
2494
2495   struct my_slist_node_traits
2496   {
2497      //The type of the node
2498      struct node
2499      {
2500         node *next_;
2501      };
2502
2503      typedef node *       node_ptr;
2504      typedef const node * const_node_ptr;
2505
2506      //A function to obtain a pointer to the next node
2507      static node_ptr get_next(const_node_ptr n)
2508      {  return n->next_;  }
2509
2510      //A function to set the pointer to the next node
2511      static void set_next(node_ptr n, node_ptr next)
2512      {  n->next_ = next;  }
2513   };
2514
2515
2516*  [*Hook]: A class that the user must add as a base class or as a member to his own
2517   class to make that class insertable in an intrusive container. Usually the hook
2518   contains a node object that will be used to form the group of nodes:
2519   For example, the following class is a [*Hook] that the user can add as a base class,
2520   to make the user class compatible with a singly linked list container:
2521
2522[c++]
2523
2524   class my_slist_base_hook
2525         //This hook contains a node, that will be used
2526         //to link the user object in the group of nodes
2527      : private my_slist_node_traits::node
2528   {
2529      typedef my_slist_node_traits::node_ptr       node_ptr;
2530      typedef my_slist_node_traits::const_node_ptr const_node_ptr;
2531
2532      //Converts the generic node to the hook
2533      static my_slist_base_hook *to_hook_ptr(node_ptr p)
2534      {  return static_cast<my_slist_base_hook*>(p); }
2535
2536      //Returns the generic node stored by this hook
2537      node_ptr to_node_ptr()
2538      { return static_cast<node *const>(this); }
2539
2540      // More operations
2541      // ...
2542   };
2543
2544   //To make MyClass compatible with an intrusive singly linked list
2545   //derive our class from the hook.
2546   class MyClass
2547      :  public my_slist_base_hook
2548   {
2549      void set(int value);
2550      int get() const;
2551
2552      private:
2553      int value_;
2554   };
2555
2556*  [*Intrusive Container]: A container that offers a STL-like interface to store
2557   user objects. An intrusive container can be templatized to store different
2558   value types that use different hooks. An intrusive container is also more elaborate
2559   than a group of nodes: it can store the number of elements to achieve constant-time
2560   size information, it can offer debugging facilities, etc.
2561   For example, an [classref boost::intrusive::slist slist] container
2562   (intrusive singly linked list) should
2563   be able to hold `MyClass` objects that might have decided to store the hook
2564   as a base class or as a member. Internally, the container will use [*Node Algorithms]
2565   to implement its operations, and an intrusive container is configured using
2566   a template parameter called [*ValueTraits]. [*ValueTraits] will contain
2567   the information to convert user classes in nodes compatible with [*Node Algorithms].
2568   For example, this a possible [classref boost::intrusive::slist slist] implementation:
2569
2570[c++]
2571
2572   template<class ValueTraits, ...>
2573   class slist
2574   {
2575      public:
2576      typedef typename ValueTraits::value_type value_type;
2577
2578      //More typedefs and functions
2579      // ...
2580
2581      //Insert the value as the first element of the list
2582      void push_front (reference value)
2583      {
2584         node_ptr to_insert(ValueTraits::to_node_ptr(value));
2585         circular_list_algorithms::link_after(to_insert, get_root_node());
2586      }
2587
2588      // More operations
2589      // ...
2590   };
2591
2592*  [*Semi-Intrusive Container]: A semi-intrusive container is similar to an
2593   intrusive container, but apart from the values to be inserted in the container,
2594   it needs additional memory (for example, auxiliary arrays or indexes).
2595
2596*  [*Value Traits]: As we can see, to make our classes intrusive-friendly we add
2597   a simple hook as a member or base class. The hook contains a generic node
2598   that will be inserted in a group of nodes. [*Node Algorithms] just work
2599   with nodes and don't know anything about user classes. On the other
2600   hand, an intrusive container needs to know how to obtain a node from a user class,
2601   and also the inverse operation.
2602   So we can define [*ValueTraits] as the glue between user classes and nodes
2603   required by [*Node Algorithms].
2604   Let's see a possible implementation of a value traits class that glues MyClass
2605   and the node stored in the hook:
2606
2607[c++]
2608
2609   struct my_slist_derivation_value_traits
2610   {
2611      public:
2612      typedef slist_node_traits           node_traits;
2613      typedef MyClass                     value_type;
2614      typedef node_traits::node_ptr       node_ptr;
2615      typedef value_type*                 pointer;
2616      //...
2617
2618      //Converts user's value to a generic node
2619      static node_ptr to_node_ptr(reference value)
2620      { return static_cast<slist_base_hook &>(value).to_node_ptr(); }
2621
2622      //Converts a generic node into user's value
2623      static value_type *to_value_ptr(node_traits::node *n)
2624      { static_cast<value_type*>(slist_base_hook::to_hook_ptr(n)); }
2625
2626      // More operations
2627      // ...
2628   };
2629
2630[endsect]
2631
2632[section:node_algorithms Node algorithms with custom NodeTraits]
2633
2634As explained in the [link intrusive.concepts Concepts] section, [*Boost.Intrusive]
2635containers are implemented using node algorithms that work on generic nodes.
2636
2637Sometimes, the use of intrusive containers is expensive for some environments
2638and the programmer might want to avoid all the template instantiations
2639related to [*Boost.Intrusive] containers. However, the user can still benefit
2640from [*Boost.Intrusive] using the node algorithms, because some of those algorithms,
2641like red-black tree algorithms, are not trivial to write.
2642
2643All node algorithm classes are
2644templatized by a `NodeTraits` class. This class encapsulates the needed internal
2645type declarations and operations to make a node compatible with node algorithms.
2646Each type of node algorithms has its own requirements:
2647
2648[section:circular_slist_algorithms Intrusive singly linked list algorithms]
2649
2650These algorithms are static
2651members of the [classref boost::intrusive::circular_slist_algorithms circular_slist_algorithms] class:
2652
2653[c++]
2654
2655   template<class NodeTraits>
2656   struct circular_slist_algorithms;
2657
2658An empty list is formed by a node whose pointer to the next node points
2659to itself. [classref boost::intrusive::circular_slist_algorithms circular_slist_algorithms]
2660is configured with a NodeTraits class, which encapsulates
2661the information about the node to be manipulated. NodeTraits must support the
2662following interface:
2663
2664[*Typedefs]:
2665
2666*  `node`: The type of the node that forms the circular list
2667
2668*  `node_ptr`: The type of a pointer to a node (usually node*)
2669
2670*  `const_node_ptr`: The type of a pointer to a const node (usually const node*)
2671
2672[*Static functions]:
2673
2674*  `static node_ptr get_next(const_node_ptr n);`:
2675   Returns a pointer to the next node stored in "n".
2676
2677*  `static void set_next(node_ptr n, node_ptr next);`:
2678   Sets the pointer to the next node stored in "n" to "next".
2679
2680Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
2681with our nodes:
2682
2683[import ../example/doc_slist_algorithms.cpp]
2684[doc_slist_algorithms_code]
2685
2686For a complete list of functions see
2687[classref boost::intrusive::circular_slist_algorithms circular_slist_algorithms reference].
2688
2689[endsect]
2690
2691[section:circular_list_algorithms Intrusive doubly linked list algorithms]
2692
2693These algorithms are static
2694members of the [classref boost::intrusive::circular_list_algorithms circular_list_algorithms] class:
2695
2696[c++]
2697
2698   template<class NodeTraits>
2699   struct circular_list_algorithms;
2700
2701An empty list is formed by a node whose pointer to the next node points
2702to itself. [classref boost::intrusive::circular_list_algorithms circular_list_algorithms]
2703is configured with a NodeTraits class, which encapsulates
2704the information about the node to be manipulated. NodeTraits must support the
2705following interface:
2706
2707[*Typedefs]:
2708
2709*  `node`: The type of the node that forms the circular list
2710
2711*  `node_ptr`: The type of a pointer to a node (usually node*)
2712
2713*  `const_node_ptr`: The type of a pointer to a const node (usually const node*)
2714
2715[*Static functions]:
2716
2717*  `static node_ptr get_next(const_node_ptr n);`:
2718   Returns a pointer to the next node stored in "n".
2719
2720*  `static void set_next(node_ptr n, node_ptr next);`:
2721   Sets the pointer to the next node stored in "n" to "next".
2722
2723*  `static node_ptr get_previous(const_node_ptr n);`:
2724   Returns a pointer to the previous node stored in "n".
2725
2726*  `static void set_previous(node_ptr n, node_ptr prev);`:
2727   Sets the pointer to the previous node stored in "n" to "prev".
2728
2729Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
2730with our nodes:
2731
2732[import ../example/doc_list_algorithms.cpp]
2733[doc_list_algorithms_code]
2734
2735For a complete list of functions see
2736[classref boost::intrusive::circular_list_algorithms circular_list_algorithms reference].
2737
2738[endsect]
2739
2740[section:rbtree_algorithms Intrusive red-black tree algorithms]
2741
2742These algorithms are static
2743members of the [classref boost::intrusive::rbtree_algorithms rbtree_algorithms] class:
2744
2745[c++]
2746
2747   template<class NodeTraits>
2748   struct rbtree_algorithms;
2749
2750
2751An empty tree is formed by a node whose pointer to the parent node is null,
2752the left and right node pointers point to itself, and whose color is red.
2753[classref boost::intrusive::rbtree_algorithms rbtree_algorithms]
2754is configured with a NodeTraits class, which encapsulates
2755the information about the node to be manipulated. NodeTraits must support the
2756following interface:
2757
2758[*Typedefs]:
2759
2760*  `node`: The type of the node that forms the circular rbtree
2761
2762*  `node_ptr`: The type of a pointer to a node (usually node*)
2763
2764*  `const_node_ptr`: The type of a pointer to a const node (usually const node*)
2765
2766*  `color`: The type that can store the color of a node
2767
2768[*Static functions]:
2769
2770*  `static node_ptr get_parent(const_node_ptr n);`:
2771   Returns a pointer to the parent node stored in "n".
2772
2773*  `static void set_parent(node_ptr n, node_ptr p);`:
2774   Sets the pointer to the parent node stored in "n" to "p".
2775
2776*  `static node_ptr get_left(const_node_ptr n);`:
2777   Returns a pointer to the left node stored in "n".
2778
2779*  `static void set_left(node_ptr n, node_ptr l);`:
2780   Sets the pointer to the left node stored in "n" to "l".
2781
2782*  `static node_ptr get_right(const_node_ptr n);`:
2783   Returns a pointer to the right node stored in "n".
2784
2785*  `static void set_right(node_ptr n, node_ptr r);`:
2786   Sets the pointer to the right node stored in "n" to "r".
2787
2788*  `static color get_color(const_node_ptr n);`:
2789   Returns the color stored in "n".
2790
2791*  `static void set_color(node_ptr n, color c);`:
2792   Sets the color stored in "n" to "c".
2793
2794*  `static color black();`:
2795   Returns a value representing the black color.
2796
2797*  `static color red();`:
2798   Returns a value representing the red color.
2799
2800Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
2801with our nodes:
2802
2803[import ../example/doc_rbtree_algorithms.cpp]
2804[doc_rbtree_algorithms_code]
2805
2806For a complete list of functions see
2807[classref boost::intrusive::rbtree_algorithms rbtree_algorithms reference].
2808
2809[endsect]
2810
2811[section:splaytree_algorithms Intrusive splay tree algorithms]
2812
2813These algorithms are static
2814members of the [classref boost::intrusive::splaytree_algorithms splaytree_algorithms] class:
2815
2816[c++]
2817
2818   template<class NodeTraits>
2819   struct splaytree_algorithms;
2820
2821
2822An empty tree is formed by a node whose pointer to the parent node is null,
2823and whose left and right nodes pointers point to itself.
2824[classref boost::intrusive::splaytree_algorithms splaytree_algorithms]
2825is configured with a NodeTraits class, which encapsulates
2826the information about the node to be manipulated. NodeTraits must support the
2827following interface:
2828
2829[*Typedefs]:
2830
2831*  `node`: The type of the node that forms the circular splaytree
2832
2833*  `node_ptr`: The type of a pointer to a node (usually node*)
2834
2835*  `const_node_ptr`: The type of a pointer to a const node (usually const node*)
2836
2837[*Static functions]:
2838
2839*  `static node_ptr get_parent(const_node_ptr n);`:
2840   Returns a pointer to the parent node stored in "n".
2841
2842*  `static void set_parent(node_ptr n, node_ptr p);`:
2843   Sets the pointer to the parent node stored in "n" to "p".
2844
2845*  `static node_ptr get_left(const_node_ptr n);`:
2846   Returns a pointer to the left node stored in "n".
2847
2848*  `static void set_left(node_ptr n, node_ptr l);`:
2849   Sets the pointer to the left node stored in "n" to "l".
2850
2851*  `static node_ptr get_right(const_node_ptr n);`:
2852   Returns a pointer to the right node stored in "n".
2853
2854*  `static void set_right(node_ptr n, node_ptr r);`:
2855   Sets the pointer to the right node stored in "n" to "r".
2856
2857Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
2858with our nodes:
2859
2860[import ../example/doc_splaytree_algorithms.cpp]
2861[doc_splaytree_algorithms_code]
2862
2863For a complete list of functions see
2864[classref boost::intrusive::splaytree_algorithms splaytree_algorithms reference].
2865
2866[endsect]
2867
2868[section:avltree_algorithms Intrusive avl tree algorithms]
2869
2870[classref boost::intrusive::avltree_algorithms avltree_algorithms] have the same
2871interface as [classref boost::intrusive::rbtree_algorithms rbtree_algorithms].
2872
2873[c++]
2874
2875   template<class NodeTraits>
2876   struct avltree_algorithms;
2877
2878[classref boost::intrusive::avltree_algorithms avltree_algorithms]
2879is configured with a NodeTraits class, which encapsulates
2880the information about the node to be manipulated. NodeTraits must support the
2881following interface:
2882
2883[*Typedefs]:
2884
2885*  `node`: The type of the node that forms the circular avltree
2886
2887*  `node_ptr`: The type of a pointer to a node (usually node*)
2888
2889*  `const_node_ptr`: The type of a pointer to a const node (usually const node*)
2890
2891*  `balance`: A type that can represent 3 balance types (usually an integer)
2892
2893[*Static functions]:
2894
2895*  `static node_ptr get_parent(const_node_ptr n);`:
2896   Returns a pointer to the parent node stored in "n".
2897
2898*  `static void set_parent(node_ptr n, node_ptr p);`:
2899   Sets the pointer to the parent node stored in "n" to "p".
2900
2901*  `static node_ptr get_left(const_node_ptr n);`:
2902   Returns a pointer to the left node stored in "n".
2903
2904*  `static void set_left(node_ptr n, node_ptr l);`:
2905   Sets the pointer to the left node stored in "n" to "l".
2906
2907*  `static node_ptr get_right(const_node_ptr n);`:
2908   Returns a pointer to the right node stored in "n".
2909
2910*  `static void set_right(node_ptr n, node_ptr r);`:
2911   Sets the pointer to the right node stored in "n" to "r".
2912
2913*  `static balance get_balance(const_node_ptr n);`:
2914   Returns the balance factor stored in "n".
2915
2916*  `static void set_balance(node_ptr n, balance b);`:
2917   Sets the balance factor stored in "n" to "b".
2918
2919*  `static balance negative();`:
2920   Returns a value representing a negative balance factor.
2921
2922*  `static balance zero();`:
2923   Returns a value representing a zero balance factor.
2924
2925*  `static balance positive();`:
2926   Returns a value representing a positive balance factor.
2927
2928Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
2929with our nodes:
2930
2931[import ../example/doc_avltree_algorithms.cpp]
2932[doc_avltree_algorithms_code]
2933
2934For a complete list of functions see
2935[classref boost::intrusive::avltree_algorithms avltree_algorithms reference].
2936
2937[endsect]
2938
2939
2940[section:treap_algorithms Intrusive treap algorithms]
2941
2942[classref boost::intrusive::treap_algorithms treap_algorithms] have the same
2943interface as [classref boost::intrusive::rbtree_algorithms rbtree_algorithms].
2944
2945[c++]
2946
2947   template<class NodeTraits>
2948   struct treap_algorithms;
2949
2950[classref boost::intrusive::treap_algorithms treap_algorithms]
2951is configured with a NodeTraits class, which encapsulates
2952the information about the node to be manipulated. NodeTraits must support the
2953following interface:
2954
2955[*Typedefs]:
2956
2957*  `node`: The type of the node that forms the circular treap
2958
2959*  `node_ptr`: The type of a pointer to a node (usually node*)
2960
2961*  `const_node_ptr`: The type of a pointer to a const node (usually const node*)
2962
2963[*Static functions]:
2964
2965*  `static node_ptr get_parent(const_node_ptr n);`:
2966   Returns a pointer to the parent node stored in "n".
2967
2968*  `static void set_parent(node_ptr n, node_ptr p);`:
2969   Sets the pointer to the parent node stored in "n" to "p".
2970
2971*  `static node_ptr get_left(const_node_ptr n);`:
2972   Returns a pointer to the left node stored in "n".
2973
2974*  `static void set_left(node_ptr n, node_ptr l);`:
2975   Sets the pointer to the left node stored in "n" to "l".
2976
2977*  `static node_ptr get_right(const_node_ptr n);`:
2978   Returns a pointer to the right node stored in "n".
2979
2980*  `static void set_right(node_ptr n, node_ptr r);`:
2981   Sets the pointer to the right node stored in "n" to "r".
2982
2983Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
2984with our nodes:
2985
2986[import ../example/doc_treap_algorithms.cpp]
2987[doc_treap_algorithms_code]
2988
2989For a complete list of functions see
2990[classref boost::intrusive::treap_algorithms treap_algorithms reference].
2991
2992[endsect]
2993
2994
2995[/
2996/
2997/[section:sgtree_algorithms Intrusive sg tree algorithms]
2998/
2999/
3000/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms] have the same
3001/interface as [classref boost::intrusive::rbtree_algorithms rbtree_algorithms].
3002/
3003/[c++]
3004/
3005/   template<class NodeTraits>
3006/   struct sgtree_algorithms;
3007/
3008/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms]
3009/is configured with a NodeTraits class, which encapsulates
3010/the information about the node to be manipulated. NodeTraits must support the
3011/following interface:
3012/
3013/[*Typedefs]:
3014/
3015/*  `node`: The type of the node that forms the circular sgtree
3016/
3017/*  `node_ptr`: The type of a pointer to a node (usually node*)
3018/
3019/*  `const_node_ptr`: The type of a pointer to a const node (usually const node*)
3020/
3021/[*Static functions]:
3022/
3023/*  `static node_ptr get_parent(const_node_ptr n);`:
3024/   Returns a pointer to the parent node stored in "n".
3025/
3026/*  `static void set_parent(node_ptr n, node_ptr p);`:
3027/   Sets the pointer to the parent node stored in "n" to "p".
3028/
3029/*  `static node_ptr get_left(const_node_ptr n);`:
3030/   Returns a pointer to the left node stored in "n".
3031/
3032/*  `static void set_left(node_ptr n, node_ptr l);`:
3033/   Sets the pointer to the left node stored in "n" to "l".
3034/
3035/*  `static node_ptr get_right(const_node_ptr n);`:
3036/   Returns a pointer to the right node stored in "n".
3037/
3038/*  `static void set_right(node_ptr n, node_ptr r);`:
3039/   Sets the pointer to the right node stored in "n" to "r".
3040/
3041/Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
3042/with our nodes:
3043/
3044/[import ../example/doc_sgtree_algorithms.cpp]
3045/[doc_sgtree_algorithms_code]
3046/
3047/For a complete list of functions see
3048/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms reference].
3049/
3050/[endsect]
3051/]
3052
3053[endsect]
3054
3055[section:value_traits Containers with custom ValueTraits]
3056
3057As explained in the [link intrusive.concepts Concepts] section, [*Boost.Intrusive]
3058containers need a `ValueTraits` class to perform transformations between nodes and
3059user values. `ValueTraits` can be explicitly configured (using the `value_traits<>` option)
3060or implicitly configured (using hooks and their `base_hook<>`/`member_hook<>` options).
3061`ValueTraits` contains
3062all the information to glue the `value_type` of the containers and the node to be
3063used in node algorithms, since these types can be different. Apart from this,
3064`ValueTraits` also stores information about the link policy of the values to be inserted.
3065
3066Instead of using [*Boost.Intrusive] predefined hooks
3067a user might want to develop customized containers, for example, using nodes that are
3068optimized for a specific
3069application or that are compatible with a legacy ABI. A user might want
3070to have only two additional pointers in his class and insert the class in a doubly
3071linked list sometimes and in a singly linked list in other situations. You can't
3072achieve this using [*Boost.Intrusive] predefined hooks. Now, instead of using
3073`base_hook<...>` or `member_hook<...>` options the user will specify the
3074`value_traits<...>` options. Let's see how we can do this:
3075
3076[section:value_traits_interface ValueTraits interface]
3077
3078`ValueTraits` has the following interface:
3079
3080[c++]
3081
3082   #include <boost/intrusive/pointer_traits.hpp>
3083   #include <boost/intrusive/link_mode.hpp>
3084
3085   struct my_value_traits
3086   {
3087      typedef implementation_defined                                    node_traits;
3088      typedef implementation_defined                                    value_type;
3089      typedef node_traits::node_ptr                                     node_ptr;
3090      typedef node_traits::const_node_ptr                               const_node_ptr;
3091      typedef boost::intrusive::pointer_traits<node_ptr>::rebind_traits
3092         <value_type>::type::pointer                                    pointer;
3093      typedef boost::intrusive::pointer_traits<node_ptr>::rebind_traits
3094         <const value_type>::type::pointer                              const_pointer;
3095
3096      static const link_mode_type link_mode = some_linking_policy;
3097
3098      static node_ptr       to_node_ptr    (value_type &value);
3099      static const_node_ptr to_node_ptr    (const value_type &value);
3100      static pointer        to_value_ptr   (node_ptr n);
3101      static const_pointer  to_value_ptr   (const_node_ptr n);
3102   };
3103
3104Let's explain each type and function:
3105
3106*  [*['node_traits]]: The node configuration that is needed by node algorithms.
3107   These node traits and algorithms are
3108   described in the previous chapter: [link intrusive.node_algorithms Node Algorithms].
3109
3110   *  If my_value_traits is meant to be used with [classref boost::intrusive::slist slist],
3111      `node_traits` should follow
3112      the interface needed by [classref boost::intrusive::circular_slist_algorithms circular_slist_algorithms].
3113
3114   *  If my_value_traits is meant to be used with [classref boost::intrusive::list list],
3115      `node_traits` should follow
3116      the interface needed by [classref boost::intrusive::circular_list_algorithms circular_list_algorithms].
3117
3118   *  If my_value_traits is meant to be used with [classref boost::intrusive::set set]/[classref boost::intrusive::multiset multiset],
3119      `node_traits` should follow
3120      the interface needed by [classref boost::intrusive::rbtree_algorithms rbtree_algorithms].
3121
3122   *  If my_value_traits is meant to be used with [classref boost::intrusive::unordered_set unordered_set]/
3123      [classref boost::intrusive::unordered_multiset unordered_multiset], `node_traits`
3124      should follow the interface needed by [classref boost::intrusive::circular_slist_algorithms circular_slist_algorithms].
3125
3126*  [*['node_ptr]]: A typedef for `node_traits::node_ptr`.
3127
3128*  [*['const_node_ptr]]: A typedef for `node_traits::const_node_ptr`.
3129
3130*  [*['value_type]]: The type that the user wants to insert in the container. This type can be
3131   the same as `node_traits::node` but it can be different (for example, `node_traits::node`
3132   can be a member type of `value_type`). If `value_type` and `node_traits::node` are the
3133   same type, the `to_node_ptr` and `to_value_ptr` functions are trivial.
3134
3135*  [*['pointer]]: The type of a pointer to a `value_type`. It must be the same pointer type
3136   as `node_ptr`: If `node_ptr` is `node*`, `pointer` must be `value_type*`. If
3137   `node_ptr` is `smart_ptr<node_traits::node>`, `pointer` must be `smart_ptr<value_type>`.
3138   This can be generically achieved using `boost::intrusive::pointer_traits` (portable implementation of C++11
3139   `std::pointer_traits`).
3140
3141*  [*['const_pointer]]: The type of a pointer to a `const value_type`. It must be the same pointer type
3142   as `node_ptr`: If `node_ptr` is `node*`, `const_pointer` must be `const value_type*`. If
3143   `node_ptr` is `smart_ptr<node_traits::node>`, `const_pointer` must be `smart_ptr<const value_type>`.
3144
3145*  [*['link_mode]]: Indicates that `value_traits` needs some additional work or checks from the
3146   container. The types are enumerations defined in the `link_mode.hpp` header.
3147   These are the possible types:
3148
3149   *  [*`normal_link`]: If this linking policy is specified in a `ValueTraits` class
3150      as the link mode, containers
3151      configured with such `ValueTraits` won't set the hooks
3152      of the erased values to a default state. Containers also won't
3153      check that the hooks of the new values are default initialized.
3154
3155   *  [*`safe_link`]: If this linking policy is specified as the link mode
3156      in a `ValueTraits` class, containers
3157      configured with this `ValueTraits` will set the hooks
3158      of the erased values to a default state. Containers also will
3159      check that the hooks of the new values are default initialized.
3160
3161   *  [*`auto_unlink`]: Same as "safe_link" but containers with
3162      constant-time size features won't be
3163      compatible with `ValueTraits` configured with this policy.
3164      Containers also know that a value can be silently erased from
3165      the container without using any function provided by the containers.
3166
3167*  [*['static node_ptr to_node_ptr (value_type &value)]] and
3168   [*['static const_node_ptr to_node_ptr (const value_type &value)]]:
3169   These functions take a reference to a value_type and return a pointer to the node
3170   to be used with node algorithms.
3171
3172*  [*['static pointer to_value_ptr (node_ptr n)]] and
3173   [*['static const_pointer to_value_ptr (const_node_ptr n)]]:
3174   These functions take a pointer to a node and return a pointer to the value
3175   that contains the node.
3176
3177[endsect]
3178
3179[section:value_traits_example Custom ValueTraits example]
3180
3181Let's define our own `value_traits` class to be able to use [*Boost.Intrusive]
3182containers with an old C structure whose definition can't be changed.
3183That legacy type has two pointers that can be used to build singly and doubly linked
3184lists: in singly linked lists we only need a pointer, whereas in doubly
3185linked lists, we need two pointers. Since we only have two pointers, we can't insert
3186the object in both a singly and a doubly linked list at the same time.
3187This is the definition of the old node:
3188
3189[import ../example/doc_value_traits.cpp]
3190[doc_value_traits_code_legacy]
3191
3192Now we have to define a NodeTraits class that will implement the functions/typedefs
3193that will make the legacy node compatible with [*Boost.Intrusive] algorithms. After that,
3194we'll define a ValueTraits class that will configure [*Boost.Intrusive] containers:
3195
3196[doc_value_traits_value_traits]
3197
3198Defining a value traits class that simply defines `value_type` as
3199`legacy_node_traits::node` is a common approach when defining customized
3200intrusive containers, so [*Boost.Intrusive] offers a templatized
3201[classref boost::intrusive::trivial_value_traits trivial_value_traits] class
3202that does exactly what we want:
3203
3204[doc_value_traits_trivial]
3205
3206Now we can just define the containers that will store the legacy abi objects and write
3207a little test:
3208
3209[doc_value_traits_test]
3210
3211As seen, several key elements of [*Boost.Intrusive] can be reused with custom user types,
3212if the user does not want to use the provided [*Boost.Intrusive] facilities.
3213
3214[endsect]
3215
3216[section:reusing_node_algorithms Reusing node algorithms for different values]
3217
3218In the previous example, `legacy_node_traits::node` type and
3219`legacy_value_traits::value_type` are the same type, but this is not necessary. It's possible
3220to have several `ValueTraits` defining the same `node_traits` type (and thus, the same `node_traits::node`).
3221This reduces the number of node algorithm instantiations, but
3222now `ValueTraits::to_node_ptr` and `ValueTraits::to_value_ptr` functions need to offer
3223conversions between both types. Let's see a small example:
3224
3225First, we'll define the node to be used in the algorithms. For a linked list,
3226we just need a node that stores two pointers:
3227
3228[import ../example/doc_advanced_value_traits.cpp]
3229[doc_advanced_value_traits_code]
3230
3231Now we'll define two different types that will be inserted in intrusive lists and
3232a templatized `ValueTraits` that will work for both types:
3233
3234[doc_advanced_value_traits_value_traits]
3235
3236Now define two containers. Both containers will instantiate the same list algorithms
3237(`circular_list_algorithms<simple_node_traits>`),
3238due to the fact that the value traits used to define the containers provide the same `node_traits` type:
3239
3240[doc_advanced_value_traits_containers]
3241
3242All [*Boost.Intrusive] containers using predefined hooks use this technique to minimize code size:
3243all possible [classref boost::intrusive::list list] containers
3244created with predefined hooks that define the same `VoidPointer` type
3245share the same list algorithms.
3246
3247[endsect]
3248
3249[section:simplifying_value_traits Simplifying value traits definition]
3250
3251The previous example can be further simplified using the
3252[classref boost::intrusive::derivation_value_traits derivation_value_traits]
3253class to define a value traits class with a value that stores the
3254`simple_node` as a base class:
3255
3256[import ../example/doc_derivation_value_traits.cpp]
3257[doc_derivation_value_traits_value_traits]
3258
3259We can even choose to store `simple_node` as a member of `value_1` and `value_2`
3260classes and use [classref boost::intrusive::member_value_traits member_value_traits]
3261to define the needed value traits classes:
3262
3263[import ../example/doc_member_value_traits.cpp]
3264[doc_member_value_traits_value_traits]
3265
3266[endsect]
3267
3268[section:stateful_value_traits Stateful value traits]
3269
3270Until now all shown custom value traits are stateless, that is, [*the transformation between nodes
3271and values is implemented in terms of static functions]. It's possible to use [*stateful] value traits
3272so that we can separate nodes and values and [*avoid modifying types to insert nodes].
3273[*Boost.Intrusive] differentiates between stateful and stateless value traits by checking if all
3274Node <-> Value transformation functions are static or not (except for Visual 7.1, since overloaded
3275static function detection is not possible, in this case the implementation checks if the class is empty):
3276
3277*  If all Node <-> Value transformation functions are static , a [*stateless]
3278   value traits is assumed.  transformations must be static functions.
3279*  Otherwise a [*stateful] value traits is assumed.
3280
3281Using stateful value traits it's possible to create containers of non-copyable/movable objects [*without modifying]
3282the definition of the class to be inserted. This interesting property is achieved without using global variables
3283(stateless value traits could use global variables to achieve the same goal), so:
3284
3285*  [*Thread-safety guarantees]: Better thread-safety guarantees can be achieved with stateful
3286   value traits, since accessing global resources might require synchronization primitives that
3287   can be avoided when using internal state.
3288*  [*Flexibility]: A stateful value traits type can be configured at run-time.
3289*  [*Run-time polymorphism]: A value traits might implement node <-> value
3290   transformations as virtual functions. A single container type could be
3291   configured at run-time to use different node <-> value relationships.
3292
3293Stateful value traits have many advantages but also some downsides:
3294
3295*  [*Performance]: Value traits operations should be very efficient since they are basic operations used by containers.
3296   [*A heavy node <-> value transformation will hurt intrusive containers' performance].
3297*  [*Exception guarantees]: The stateful ValueTraits must maintain no-throw guarantees, otherwise, the
3298   container invariants won't be preserved.
3299*  [*Static functions]: Some static functions offered by intrusive containers are not
3300   available because node <-> value transformations are not static.
3301*  [*Bigger iterators]: The size of some iterators is increased because the iterator
3302   needs to store a pointer to the stateful value traits to implement node to value
3303   transformations (e.g. `operator*()` and `operator->()`).
3304
3305An easy and useful example of stateful value traits is when an array of values can be indirectly introduced
3306in a list guaranteeing no additional allocation apart from the initial resource reservation:
3307
3308[import ../example/doc_stateful_value_traits.cpp]
3309[doc_stateful_value_traits]
3310
3311[endsect]
3312
3313[endsect]
3314
3315[section:thread_safety Thread safety guarantees]
3316
3317Intrusive containers have thread safety guarantees similar to STL containers.
3318
3319*  Several threads having read or write access to different instances is safe as long as inserted
3320   objects are different.
3321*  Concurrent read-only access to the same container is safe.
3322
3323Some Intrusive hooks (auto-unlink hooks, for example) modify containers without
3324having a reference to them: this is considered a write access to the container.
3325
3326Other functions, like checking if an object is already inserted in a container using the `is_linked()`
3327member of safe hooks, constitute read access on the container without having a reference to it, so no other
3328thread should have write access (direct or indirect) to that container.
3329
3330Since the same object can be inserted in several containers at the same time using different hooks,
3331the thread safety of [*Boost.Intrusive] is related to the containers and also to the object whose lifetime
3332is manually managed by the user.
3333
3334As we can see, the analysis of the thread-safety of a program using [*Boost.Intrusive] is harder
3335than with non-intrusive containers.
3336
3337To analyze the thread safety, consider the following points:
3338
3339*  The auto-unlink hook's destructor and `unlink()` functions modify the container indirectly.
3340*  The safe mode and auto-unlink hooks' `is_linked()` functions are a read access to the container.
3341*  Inserting an object in containers that will be modified by different threads has no thread safety
3342   guarantee, although in most platforms it will be thread-safe without locking.
3343
3344[endsect]
3345
3346[section:boost_intrusive_iterators Boost.Intrusive Iterator features]
3347
3348[section:null_forward_iterators Null forward iterators]
3349
3350[*Boost.Intrusive] implements
3351[@http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3644.pdf C++14 Null Forward Iterators],
3352a feature that was introduced with C++14. This means that equality and inequality comparison are defined
3353over all iterators for the same underlying sequence and the value initialized-iterators.
3354
3355Value initialized iterators behave as if they refer past the end of the same empty sequence:
3356
3357[c++]
3358
3359   list<MyType> l = { ... };
3360   auto ni = list<MyType>::iterator();
3361   auto nd = list<MyType2>::iterator();
3362   ni == ni; // True.
3363   nd != nd; // False.
3364   ni == nd; // Won't compile.
3365
3366[endsect]
3367
3368[section:scary_iterators Scary Iterators]
3369
3370The paper N2913, titled [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2913.pdf,
3371SCARY Iterator Assignment and Initialization], proposed a requirement that a standard container's
3372iterator types have no dependency on any type argument apart from the container's `value_type`,
3373`difference_type`, `pointer type`, and `const_pointer` type. In particular, according to the proposal,
3374the types of a standard container's iterators should not depend on the container's `key_compare`,
3375`hasher`, `key_equal`, or `allocator` types.
3376
3377That paper demonstrated that SCARY operations were crucial to the performant implementation of common
3378design patterns using STL components. It showed that implementations that support SCARY operations reduce
3379object code bloat by eliminating redundant specializations of iterator and algorithm templates.
3380
3381[*Boost.Intrusive] containers are a bit different from standard containers. In particular, they have no
3382allocator parameter and they can be configured with additional options not present in STL-like containers.
3383Thus [*Boost.Intrusive] offers its own `SCARY iterator` implementation, where iterator types don't
3384change when the container is configured with an option that does not alter the value <-> node transformation.
3385More concretely, the following options and conditions guarantee that iterator types are unchanged:
3386
3387* [*All containers]: `size_type<>`, `constant_time_size<>`,
3388* [*`slist`]: `cache_last<>`, `linear<>`,
3389* [*`unordered_[multi]set`]: `hash<>`, `equal<>`, `power_2_buckets<>`, `cache_begin<>`.
3390* [*All tree-like containers] (`[multi]set`, `avl_[multi]set`, `sg_[multi]set`, `bs_[multi]set`,
3391   `splay_[multi]set`, `treap_[multi]set`): `compare<>`.
3392* [*`treap_[multi]set`]: `priority<>`
3393* [*`bs_[multi]set`, `sg_[multi]set`, `treap_[multi]set`, `splay_[multi]set`]:
3394   They share the same iterator type when configured with the same options.
3395
3396[endsect]
3397
3398[endsect]
3399
3400[section:equal_range_stability Stability and insertion with hint in ordered associative containers with equivalent keys]
3401
3402[*Boost.Intrusive] ordered associative containers with equivalent keys offer stability guarantees, following
3403[@http://open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233 C++ standard library's defect #233 resolution],
3404explained in document [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html Comments on LWG issue 233: Insertion hints in associative containers].
3405This means that:
3406
3407*  A ['Insert without hint] member function always insert at the upper bound of an equal range.
3408*  A ['Insert with hint] member function inserts the new value [*before the hint] if hint's and new node's keys are equivalent.
3409*  Implements Andrew Koenig ['as close as possible to hint] proposal. A new element is always be inserted as close to the hint as possible.
3410   So, for example, if there is a subsequence of equivalent values, `a.begin()` as the hint means that the new element should be inserted
3411   before the subsequence even if `a.begin()` is far away. This allows code to always append (or prepend) an equal range with something
3412   as simple as: `m.insert(m.end(), new_node);` or `m.insert(m.begin(), new_node);`
3413
3414[endsect]
3415
3416[section:obtaining_same_type_reducing_space Obtaining the same types and reducing symbol length]
3417
3418The flexible option specification mechanism used by [*Boost.Intrusive] for hooks and containers
3419has a couple of downsides:
3420
3421*  If a user specifies the same options in different order or specifies some options and leaves the
3422   rest as defaults, the type of the created container/hook will be different. Sometimes
3423   this is annoying, because two programmers specifying the same options might end up with incompatible
3424   types. For example, the following two lists, although using the same options, do not have
3425   the same type:
3426
3427[c++]
3428
3429   #include <boost/intrusive/list.hpp>
3430
3431   using namespace boost::intrusive;
3432
3433   //Explicitly specify constant-time size and size type
3434   typedef list<T, constant_time_size<true>, size_type<std::size_t> List1;
3435
3436   //Implicitly specify constant-time size and size type
3437   typedef list<T> List2;
3438
3439*  Option specifiers lead to long template symbols for classes and functions. Option specifiers themselves
3440   are verbose and without variadic templates, several default template parameters are assigned for
3441   non-specified options. Object and debugging information files can grow and compilation times
3442   may suffer if long names are produced.
3443
3444To solve these issues [*Boost.Intrusive] offers some helper metafunctions that reduce symbol lengths
3445and create the same type if the same options (either explicitly or implicitly) are used. These also
3446improve compilation times. All containers and hooks have their respective `make_xxx` versions.
3447The previously shown example can be rewritten like this to obtain the same list type:
3448
3449[c++]
3450
3451  #include <boost/intrusive/list.hpp>
3452
3453   using namespace boost::intrusive;
3454
3455   #include <boost/intrusive/list.hpp>
3456
3457   using namespace boost::intrusive;
3458
3459   //Explicitly specify constant-time size and size type
3460   typedef make_list<T, constant_time_size<true>, size_type<std::size_t>::type List1;
3461
3462   //Implicitly specify constant-time size and size type
3463   typedef make_list<T>::type List2;
3464
3465Produced symbol lengths and compilation times will usually be shorter and object/debug files smaller.
3466If you are concerned with file sizes and compilation times, this option is your best choice.
3467
3468[endsect]
3469
3470[section:design_notes Design Notes]
3471
3472When designing [*Boost.Intrusive] the following guidelines have been taken into account:
3473
3474[section:performance_sensitive Boost.Intrusive in performance sensitive environments]
3475
3476[*Boost.Intrusive] should be a valuable tool in performance sensitive environments,
3477and following this guideline, [*Boost.Intrusive] has been designed to offer well
3478known complexity guarantees. Apart from that, some options, like optional
3479constant-time, have been designed to offer faster complexity guarantees in some
3480functions, like `slist::splice`.
3481
3482The advanced lookup and insertion functions for associative containers, taking
3483an arbitrary key type and predicates, were designed to avoid unnecessary object
3484constructions.
3485
3486[endsect]
3487
3488[section:space_constrained Boost.Intrusive in space constrained environments]
3489
3490[*Boost.Intrusive] should be useful in space constrained environments,
3491and following this guideline [*Boost.Intrusive] separates node algorithms
3492and intrusive containers to avoid instantiating node algorithms for each
3493user type. For example, a single class of red-black algorithms will be instantiated
3494to implement all set and multiset containers using raw pointers. This way,
3495[*Boost.Intrusive] seeks to avoid any code size overhead associated with templates.
3496
3497Apart from that, [*Boost.Intrusive] implements some size improvements: for example,
3498red-black trees embed the color bit in the parent pointer lower bit, if nodes
3499are two-byte aligned. The option to forgo constant-time size operations can
3500reduce container size, and this extra size optimization is noticeable
3501when the container is empty or contains few values.
3502
3503[endsect]
3504
3505[section:basic_building_block Boost.Intrusive as a basic building block]
3506
3507[*Boost.Intrusive] can be a basic building block to build more complex containers
3508and this potential has motivated many design decisions. For example, the ability
3509to have more than one hook per user type opens the opportunity to implement multi-index
3510containers on top of [*Boost.Intrusive].
3511
3512[*Boost.Intrusive] containers implement advanced functions taking function objects
3513as arguments (`clone_from`, `erase_and_dispose`, `insert_check`, etc.). These
3514functions come in handy when implementing non-intrusive containers
3515(for example, STL-like containers) on top of intrusive containers.
3516
3517[endsect]
3518
3519[section:extending_intrusive Extending Boost.Intrusive]
3520
3521[*Boost.Intrusive] offers a wide range of containers but also allows the
3522construction of custom containers reusing [*Boost.Intrusive] elements.
3523The programmer might want to use node algorithms directly or
3524build special hooks that take advantage of an application environment.
3525
3526For example, the programmer can customize parts of [*Boost.Intrusive]
3527to manage old data structures whose definition can't be changed.
3528
3529[endsect]
3530
3531[endsect]
3532
3533[section:performance Performance]
3534
3535[*Boost.Intrusive] containers offer speed improvements compared to non-intrusive containers
3536primarily because:
3537
3538*  They minimize memory allocation/deallocation calls.
3539*  They obtain better memory locality.
3540
3541This section will show performance tests comparing some operations on
3542`boost::intrusive::list` and `std::list`:
3543
3544*  Insertions using `push_back` and container destruction will show the
3545   overhead associated with memory allocation/deallocation.
3546*  The `reverse` member function will show the advantages of the compact
3547   memory representation that can be achieved with intrusive containers.
3548*  The `sort` and `write access` tests will show the advantage of intrusive containers
3549   minimizing memory accesses compared to containers of pointers.
3550
3551Given an object of type `T`, [classref boost::intrusive::list boost::intrusive::list<T>]
3552can replace `std::list<T>` to avoid memory allocation overhead,
3553or it can replace `std::list<T*>` when the user wants containers with
3554polymorphic values or wants to share values between several containers.
3555Because of this versatility, the performance tests will be executed for 6 different
3556list types:
3557
3558*  3 intrusive lists holding a class named `itest_class`,
3559   each one with a different linking policy (`normal_link`, `safe_link`, `auto_unlink`).
3560   The `itest_class` objects will be tightly packed in a `std::vector<itest_class>` object.
3561
3562*  `std::list<test_class>`, where `test_class` is exactly the same as `itest_class`,
3563   but without the intrusive hook.
3564
3565*  `std::list<test_class*>`. The list will contain pointers to `test_class` objects
3566   tightly packed in a `std::vector<test_class>` object. We'll call this configuration ['compact pointer list]
3567
3568*  `std::list<test_class*>`. The list will contain pointers to `test_class` objects owned by a
3569   `std::list<test_class>` object. We'll call this configuration ['disperse pointer list].
3570
3571Both `test_class` and `itest_class` are templatized classes that can be configured with
3572a boolean to increase the size of the object. This way, the tests can be executed with
3573small and big objects. Here is the first part of the testing code, which shows
3574the definitions of `test_class` and `itest_class` classes, and some other
3575utilities:
3576
3577[import ../perf/perf_list.cpp]
3578[perf_list_value_type]
3579
3580As we can see, `test_class` is a very simple class holding an `int`. `itest_class`
3581is just a class that has a base hook ([classref boost::intrusive::list_base_hook list_base_hook])
3582and also derives from `test_class`.
3583
3584`func_ptr_adaptor` is just a functor adaptor to convert function objects taking
3585`test_list` objects to function objects taking pointers to them.
3586
3587You can find the full test code in the
3588[@../../libs/intrusive/perf/perf_list.cpp perf_list.cpp] source file.
3589
3590[section:performance_results_push_back Back insertion and destruction]
3591
3592The first test will measure the benefits we can obtain with intrusive containers
3593avoiding memory allocations and deallocations. All the objects to be
3594inserted in intrusive containers are allocated in a single allocation call,
3595whereas `std::list` will need to allocate memory for each object and deallocate it
3596for every erasure (or container destruction).
3597
3598Let's compare the code to be executed for each container type for different insertion tests:
3599
3600[perf_list_push_back_intrusive]
3601
3602For intrusive containers, all the values are created in a vector and after that
3603inserted in the intrusive list.
3604
3605[perf_list_push_back_stdlist]
3606
3607For a standard list, elements are pushed back using push_back().
3608
3609[perf_list_push_back_stdptrlist]
3610
3611For a standard compact pointer list, elements are created in a vector and pushed back
3612in the pointer list using push_back().
3613
3614[perf_list_push_back_disperse_stdptrlist]
3615
3616For a ['disperse pointer list], elements are created in a list and pushed back
3617in the pointer list using push_back().
3618
3619These are the times in microseconds for each case, and the normalized time:
3620
3621[table Back insertion + destruction times for Visual C++ 7.1 / Windows XP
3622    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3623    [[`normal_link` intrusive list]     [5000 / 22500]                        [1 / 1]]
3624    [[`safe_link` intrusive list]       [7812 / 32187]                        [1.56 / 1.43]]
3625    [[`auto_unlink` intrusive list]     [10156 / 41562]                       [2.03 / 1.84]]
3626    [[Standard list]                    [26875 / 97500]                       [5.37 / 4.33]]
3627    [[Standard compact pointer list]    [76406 / 86718]                      [15.28 / 3.85]]
3628    [[Standard disperse pointer list]  [146562 / 175625]                     [29.31 / 7.80]]
3629]
3630
3631[table Back insertion + destruction times for GCC 4.1.1 / MinGW over Windows XP
3632    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3633    [[`normal_link` intrusive list]     [4375 / 22187]                  [1 / 1]]
3634    [[`safe_link` intrusive list]       [7812 / 32812]                  [1.78 / 1.47]]
3635    [[`auto_unlink` intrusive list]     [10468 / 42031]                 [2.39 / 1.89]]
3636    [[Standard list]                    [81250 / 98125]                [18.57 / 4.42]]
3637    [[Standard compact pointer list]    [83750 / 94218]                [19.14 / 4.24]]
3638    [[Standard disperse pointer list]  [155625 / 175625]                [35.57 / 7.91]]
3639]
3640
3641[table Back insertion + destruction times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)
3642    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3643    [[`normal_link` intrusive list]     [4792 / 20495]                  [1 / 1]]
3644    [[`safe_link` intrusive list]       [7709 / 30803]                  [1.60 / 1.5]]
3645    [[`auto_unlink` intrusive list]     [10180 / 41183]                 [2.12 / 2.0]]
3646    [[Standard list]                    [17031 / 32586]                 [3.55 / 1.58]]
3647    [[Standard compact pointer list]    [27221 / 34823]                 [5.68 / 1.69]]
3648    [[Standard disperse pointer list]  [102272 / 60056]                [21.34 / 2.93]]
3649]
3650
3651The results are logical: intrusive lists just need one allocation. The destruction
3652time of the `normal_link` intrusive container is trivial (complexity: `O(1)`),
3653whereas `safe_link` and `auto_unlink` intrusive containers need to put the hooks of
3654erased values in the default state (complexity: `O(NumElements)`). That's why
3655`normal_link` intrusive list shines in this test.
3656
3657Non-intrusive containers need to make many more allocations and that's why they
3658lag behind. The `disperse pointer list` needs to make `NumElements*2` allocations,
3659so the result is not surprising.
3660
3661The Linux test shows that standard containers perform very well against intrusive containers
3662with big objects. Nearly the same GCC version in MinGW performs worse, so maybe
3663a good memory allocator is the reason for these excellent results.
3664
3665[endsect]
3666
3667[section:performance_results_reversing Reversing]
3668
3669The next test measures the time needed to complete calls to the member function `reverse()`.
3670Values (`test_class` and `itest_class`) and lists are created as explained in the
3671previous section.
3672
3673Note that for pointer lists, `reverse` [*does not need to access `test_class` values
3674stored in another list or vector],
3675since this function just needs to adjust internal pointers, so in theory all tested
3676lists need to perform the same operations.
3677
3678These are the results:
3679
3680[table Reverse times for Visual C++ 7.1 / Windows XP
3681    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3682    [[`normal_link` intrusive list]     [2656 / 10625]                 [1 / 1.83]]
3683    [[`safe_link` intrusive list]       [2812 / 10937]                 [1.05 / 1.89]]
3684    [[`auto_unlink` intrusive list]     [2710 / 10781]                 [1.02 / 1.86]]
3685    [[Standard list]                    [5781 / 14531]                 [2.17 / 2.51]]
3686    [[Standard compact pointer list]    [5781 / 5781]                  [2.17 / 1]]
3687    [[Standard disperse pointer list]  [10781 / 15781]                 [4.05 / 2.72]]
3688]
3689
3690[table Reverse times for GCC 4.1.1 / MinGW over Windows XP
3691    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3692    [[`normal_link` intrusive list]     [2656 / 10781]                 [1 / 2.22]]
3693    [[`safe_link` intrusive list]       [2656 / 10781]                 [1 / 2.22]]
3694    [[`auto_unlink` intrusive list]     [2812 / 10781]                 [1.02 / 2.22]]
3695    [[Standard list]                    [4843 / 12500]                 [1.82 / 2.58]]
3696    [[Standard compact pointer list]    [4843 / 4843]                  [1.82 / 1]]
3697    [[Standard disperse pointer list]   [9218 / 12968]                 [3.47 / 2.67]]
3698]
3699
3700[table Reverse times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)
3701    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3702    [[`normal_link` intrusive list]     [2742 / 10847]                 [1 / 3.41]]
3703    [[`safe_link` intrusive list]       [2742 / 10847]                 [1 / 3.41]]
3704    [[`auto_unlink` intrusive list]     [2742 / 11027]                 [1 / 3.47]]
3705    [[Standard list]                    [3184 / 10942]                 [1.16 / 3.44]]
3706    [[Standard compact pointer list]    [3207 / 3176]                  [1.16 / 1]]
3707    [[Standard disperse pointer list]   [5814 / 13381]                 [2.12 / 4.21]]
3708]
3709
3710For small objects the results show that the compact storage of values in intrusive
3711containers improve locality and reversing is faster than with standard containers,
3712whose values might be dispersed in memory because each value is independently
3713allocated. Note that the dispersed pointer list (a list of pointers to values
3714allocated in another list) suffers more because nodes of the pointer list
3715might be more dispersed, since allocations from both lists are interleaved
3716in the code:
3717
3718[c++]
3719
3720   //Object list (holding `test_class`)
3721   stdlist objects;
3722
3723   //Pointer list (holding `test_class` pointers)
3724   stdptrlist l;
3725
3726   for(int i = 0; i < NumElements; ++i){
3727      //Allocation from the object list
3728      objects.push_back(stdlist::value_type(i));
3729      //Allocation from the pointer list
3730      l.push_back(&objects.back());
3731   }
3732
3733For big objects the compact pointer list wins because the reversal test doesn't need access
3734to values stored in another container. Since all the allocations for nodes of
3735this pointer list are likely to be close (since there is no other allocation in the
3736process until the pointer list is created) locality is better than with intrusive
3737containers. The dispersed pointer list, as with small values, has poor locality.
3738
3739[endsect]
3740
3741[section:performance_results_sorting Sorting]
3742
3743The next test measures the time needed to complete calls to the member function
3744`sort(Pred pred)`. Values (`test_class` and `itest_class`) and lists are created as explained in the
3745first section. The values will be sorted in ascending and descending order each
3746iteration. For example, if ['l] is a list:
3747
3748[c++]
3749
3750   for(int i = 0; i < NumIter; ++i){
3751      if(!(i % 2))
3752         l.sort(std::greater<stdlist::value_type>());
3753      else
3754         l.sort(std::less<stdlist::value_type>());
3755   }
3756
3757For a pointer list, the function object will be adapted using `func_ptr_adaptor`:
3758
3759[c++]
3760
3761   for(int i = 0; i < NumIter; ++i){
3762      if(!(i % 2))
3763         l.sort(func_ptr_adaptor<std::greater<stdlist::value_type> >());
3764      else
3765         l.sort(func_ptr_adaptor<std::less<stdlist::value_type> >());
3766   }
3767
3768Note that for pointer lists, `sort` will take a function object that [*will access
3769`test_class` values stored in another list or vector], so pointer lists will suffer
3770an extra indirection: they will need to access the `test_class` values stored in
3771another container to compare two elements.
3772
3773These are the results:
3774
3775[table Sort times for Visual C++ 7.1 / Windows XP
3776    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3777    [[`normal_link` intrusive list]     [16093 / 38906]                [1 / 1]]
3778    [[`safe_link` intrusive list]       [16093 / 39062]                [1 / 1]]
3779    [[`auto_unlink` intrusive list]     [16093 / 38906]                [1 / 1]]
3780    [[Standard list]                    [32343 / 56406]                [2.0 / 1.44]]
3781    [[Standard compact pointer list]    [33593 / 46093]                [2.08 / 1.18]]
3782    [[Standard disperse pointer list]   [46875 / 68593]                [2.91 / 1.76]]
3783]
3784
3785[table Sort times for GCC 4.1.1 / MinGW over Windows XP
3786    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3787    [[`normal_link` intrusive list]     [15000 / 39218]                [1 / 1]]
3788    [[`safe_link` intrusive list]       [15156 / 39531]                [1.01 / 1.01]]
3789    [[`auto_unlink` intrusive list]     [15156 / 39531]                [1.01 / 1.01]]
3790    [[Standard list]                    [34218 / 56875]                [2.28 / 1.45]]
3791    [[Standard compact pointer list]    [35468 / 49218]                [2.36 / 1.25]]
3792    [[Standard disperse pointer list]   [47656 / 70156]                [3.17 / 1.78]]
3793]
3794
3795[table Sort times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)
3796    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3797    [[`normal_link` intrusive list]     [18003 / 40795]                [1 / 1]]
3798    [[`safe_link` intrusive list]       [18003 / 41017]                [1 / 1]]
3799    [[`auto_unlink` intrusive list]     [18230 / 40941]                [1.01 / 1]]
3800    [[Standard list]                    [26273 / 49643]                [1.45 / 1.21]]
3801    [[Standard compact pointer list]    [28540 / 43172]                [1.58 / 1.05]]
3802    [[Standard disperse pointer list]   [35077 / 57638]                [1.94 / 1.41]]
3803]
3804
3805The results show that intrusive containers are faster than standard
3806containers. We can see that the pointer
3807list holding pointers to values stored in a vector is quite fast, so the extra
3808indirection that is needed to access the value is minimized because all the values
3809are tightly stored, improving caching. The disperse list, on the other hand, is
3810slower because the indirection to access values stored in the object list is
3811more expensive than accessing values stored in a vector.
3812
3813[endsect]
3814
3815[section:performance_results_write_access Write access]
3816
3817The next test measures the time needed to iterate through all the elements of a list, and
3818increment the value of the internal `i_` member:
3819
3820[c++]
3821
3822   stdlist::iterator it(l.begin()), end(l.end());
3823   for(; it != end; ++it)
3824      ++(it->i_);
3825
3826Values (`test_class` and `itest_class`) and lists are created as explained in
3827the first section. Note that for pointer lists, the iteration will suffer
3828an extra indirection: they will need to access the `test_class` values stored in
3829another container:
3830
3831[c++]
3832
3833   stdptrlist::iterator it(l.begin()), end(l.end());
3834   for(; it != end; ++it)
3835      ++((*it)->i_);
3836
3837These are the results:
3838
3839[table Write access times for Visual C++ 7.1 / Windows XP
3840    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3841    [[`normal_link` intrusive list]     [2031 / 8125]                 [1 / 1]]
3842    [[`safe_link` intrusive list]       [2031 / 8281]                 [1 / 1.01]]
3843    [[`auto_unlink` intrusive list]     [2031 / 8281]                 [1 / 1.01]]
3844    [[Standard list]                    [4218 / 10000]                [2.07 / 1.23]]
3845    [[Standard compact pointer list]    [4062 / 8437]                 [2.0 / 1.03]]
3846    [[Standard disperse pointer list]   [8593 / 13125]                [4.23 / 1.61]]
3847]
3848
3849[table Write access times for GCC 4.1.1 / MinGW over Windows XP
3850    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3851    [[`normal_link` intrusive list]     [2343 / 8281]                 [1 / 1]]
3852    [[`safe_link` intrusive list]       [2500 / 8281]                 [1.06 / 1]]
3853    [[`auto_unlink` intrusive list]     [2500 / 8281]                 [1.06 / 1]]
3854    [[Standard list]                    [4218 / 10781]                [1.8 / 1.3]]
3855    [[Standard compact pointer list]    [3906 / 8281]                 [1.66 / 1]]
3856    [[Standard disperse pointer list]   [8281 / 13750]                [3.53 / 1.66]]
3857]
3858
3859[table Write access times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)
3860    [[Container]                       [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
3861    [[`normal_link` intrusive list]     [2286 / 8468]                 [1 / 1.1]]
3862    [[`safe_link` intrusive list]       [2381 / 8412]                 [1.04 / 1.09]]
3863    [[`auto_unlink` intrusive list]     [2301 / 8437]                 [1.01 / 1.1]]
3864    [[Standard list]                    [3044 / 9061]                 [1.33 / 1.18]]
3865    [[Standard compact pointer list]    [2755 / 7660]                 [1.20 / 1]]
3866    [[Standard disperse pointer list]   [6118 / 12453]                [2.67 / 1.62]]
3867]
3868
3869As with the read access test, the results show that intrusive containers outperform
3870all other containers if the values are tightly packed in a vector.
3871The disperse list is again the slowest.
3872
3873[endsect]
3874
3875[section:performance_results_conclusions Conclusions]
3876
3877Intrusive containers can offer performance benefits that cannot be achieved with
3878equivalent non-intrusive containers. Memory locality improvements are noticeable
3879when the objects to be inserted are small. Minimizing memory allocation/deallocation calls is also
3880an important factor and intrusive containers make this simple if all objects
3881to be inserted in intrusive containers are allocated using `std::vector` or `std::deque`.
3882
3883[endsect]
3884
3885[endsect]
3886
3887[section:release_notes Release Notes]
3888
3889[section:release_notes_boost_1_73_00 Boost 1.73 Release]
3890
3891*  Fixed bugs:
3892   *  [@https://github.com/boostorg/intrusive/issues/46  GitHub #46: ['UB due to union based type punning]]
3893
3894[endsect]
3895
3896[section:release_notes_boost_1_71_00 Boost 1.71 Release]
3897
3898*  Fixed bugs:
3899   *  [@https://github.com/boostorg/intrusive/pull/42  GitHub #42: ['Documentation does not describe treap priority_of_value changes]]
3900   *  [@https://github.com/boostorg/intrusive/pull/43  GitHub #43: ['Fix tests with BOOST_INTRUSIVE_VARIADIC_TEMPLATES enabled]]
3901   *  [@https://github.com/boostorg/intrusive/pull/45  GitHub #45: ['Disable variadic templates for MSVC-12 to avoid ICEs]]
3902
3903[endsect]
3904
3905[section:release_notes_boost_1_70_00 Boost 1.70 Release]
3906
3907*  Fixed bugs:
3908   *  [@https://github.com/boostorg/intrusive/pull/33 GitHub Pull #33: ['Fix compilation in case if key is void*, again]]
3909   *  [@https://github.com/boostorg/intrusive/issues/34 GitHub Issue #34: ['-Wdeprecated-copy on gcc9]]
3910   *  [@https://github.com/boostorg/intrusive/issues/35 GitHub Issue #35: ['key_of_value on treap_set seems to be broken in 1.69]]
3911   *  [@https://github.com/boostorg/intrusive/issues/38 GitHub Issue #38: ['treap: Same type for priority and key comparison leads to ambiguous base class error]]
3912   *  [@https://github.com/boostorg/intrusive/pull/39 GitHub Pull #39: ['Fix -Wextra-semi clang warnings]]
3913
3914[endsect]
3915
3916[section:release_notes_boost_1_67_00 Boost 1.67 Release]
3917
3918*  Fixed bugs:
3919   *  [@https://github.com/boostorg/intrusive/issues/29 GitHub Issues #29: ['Uninitialized variable warning pointer_plus_bits.hpp]]
3920
3921[endsect]
3922
3923[section:release_notes_boost_1_65_00 Boost 1.65 Release]
3924
3925*  Fixed bugs:
3926   *  [@https://svn.boost.org/trac/boost/ticket/12894 Boost Trac #12894: ['Allow non std::size_t size_type]]
3927   *  [@https://svn.boost.org/trac/boost/ticket/12698 Boost Trac #12698: ['base64 iterators can't be used with iterator_advance]]
3928   *  [@https://github.com/boostorg/intrusive/pull/23 GitHub Pull #23: ['Conditionally replace deprecated/removed C++98 std::random_shuffle by...]]
3929   *  [@https://github.com/boostorg/intrusive/pull/24 GitHub Pull #24: ['Adds support for MSVC ARM64 target]]
3930
3931[endsect]
3932
3933[section:release_notes_boost_1_64_00 Boost 1.64 Release]
3934
3935*  Fixed bugs:
3936   *  [@https://svn.boost.org/trac/boost/ticket/12745 Boost Trac #12745: ['key_nodeptr_comp broken if the key type is void*]]
3937   *  [@https://svn.boost.org/trac/boost/ticket/12761 Boost Trac #12761: ['intrusive::set::swap doesn't swap the comparison function*]]
3938
3939[endsect]
3940
3941[section:release_notes_boost_1_63_00 Boost 1.63 Release]
3942
3943*  Fixed bugs:
3944   *  [@https://svn.boost.org/trac/boost/ticket/12556 Boost Trac #12556: ['member_value_traits.hpp has a missing #include]]
3945
3946[endsect]
3947
3948[section:release_notes_boost_1_62_00 Boost 1.62 Release]
3949
3950*  Fixed bugs:
3951   *  [@https://svn.boost.org/trac/boost/ticket/11476 Boost Trac #11476: ['has_member_function_callable_with.hpp is massively broken with BOOST_NO_CXX11_DECLTYPE]]
3952   *  [@https://svn.boost.org/trac/boost/ticket/11994 Boost Trac #11994: ['Support intrusive container key extractors that return the key by value]]
3953   *  [@https://svn.boost.org/trac/boost/ticket/12184 Boost Trac #12184: ['clang -Wdocumentation warning]]
3954   *  [@https://svn.boost.org/trac/boost/ticket/12190 Boost Trac #12190: ['Intrusive List + Flat Map combination crashes]]
3955   *  [@https://svn.boost.org/trac/boost/ticket/12229 Boost Trac #12229: ['intrusive::unordered_set<T>::rehash() broken]]
3956   *  [@https://svn.boost.org/trac/boost/ticket/12245 Boost Trac #12245: ['bstree uses a shared static size_traits for constant_time_size<false>]]
3957   *  [@https://svn.boost.org/trac/boost/ticket/12432 Boost Trac #12432: ['Forced KeyOfValue creation when using custom compare on insert_check]]
3958
3959*  Implemented `merge` functions in ordered associative containers.
3960*  Officially documented `root()` function for tree-based containers.
3961
3962[endsect]
3963
3964[section:release_notes_boost_1_61_00 Boost 1.61 Release]
3965
3966*  Fixed bugs:
3967   *  [@https://svn.boost.org/trac/boost/ticket/11832 Boost Trac #11832: ['clang-cl + boost intrusive = miscompile]]
3968   *  [@https://svn.boost.org/trac/boost/ticket/11865 Boost Trac #11865: ['Intrusive list explicit ctor error with Clang 3.6 (C++11/14)]]
3969   *  [@https://svn.boost.org/trac/boost/ticket/11992 Boost Trac #11992: ['Add an overload of insert_check taking a key_type]]
3970   *  [@https://github.com/boostorg/intrusive/pull/19 GitHub Pull #19: ['ebo_functor_holder: compile fix for copy constructor]]
3971
3972[endsect]
3973
3974[section:release_notes_boost_1_60_00 Boost 1.60 Release]
3975
3976*  [link intrusive.advanced_lookups_insertions Advanced lookup and insertions] in ordered associative containers
3977   now support comparison functions that are not required to offer the same strict weak ordering as `key_compare`,
3978   the container must be partitioned in regards to the passed comparison object.
3979*  Fixed bugs:
3980   *  [@https://svn.boost.org/trac/boost/ticket/11701 Boost Trac #11701: ['Regression in boost::intrusive::set::equal_range]]
3981   *  [@https://svn.boost.org/trac/boost/ticket/11765 Boost Trac #11765: ['sgtree.hpp:830: bad if test ?]]
3982
3983[endsect]
3984
3985[section:release_notes_boost_1_59_00 Boost 1.59 Release]
3986
3987*  Implemented [link intrusive.map_multimap map and multimap-like interfaces].
3988*  Refactored hashtable containers to reduce template instantiations.
3989*  Fixed bugs:
3990   *  [@https://svn.boost.org/trac/boost/ticket/11222 Boost Trac #11222: ['intrusive/pointer_traits.hpp fails to compile with C++98]]
3991
3992[endsect]
3993
3994[section:release_notes_boost_1_58_00 Boost 1.58 Release]
3995
3996*  Reduced compile-time dependencies, headers, and the use of Boost.Preprocessor, specially for hooks and iterators.
3997*  Fixed bugs:
3998   *  [@https://svn.boost.org/trac/boost/ticket/6720  Boost Trac #6720: ['intrusive::unordered_set::clear_and_dispose does not compile on VC11 Beta when passed a stateless lambda]]
3999   *  [@https://svn.boost.org/trac/boost/ticket/10771 Boost Trac #10771: ['remove_if is broken for slist]]
4000   *  [@https://svn.boost.org/trac/boost/ticket/10853 Boost Trac #10853: ['problem with detection of const_cast_from]]
4001   *  [@https://svn.boost.org/trac/boost/ticket/10987 Boost Trac #10987: ['bug in any_xxx_node_traits, returning by reference]]
4002
4003[endsect]
4004
4005[section:release_notes_boost_1_57_00 Boost 1.57 Release]
4006
4007*  Experimental version of node checkers, contributed by Matei David. Many thanks!
4008*  Implemented [@http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3644.pdf N3644: Null Forward Iterators] from C++14.
4009*  Fixed bugs:
4010   *  [@https://github.com/boostorg/intrusive/pull/12 GitHub Pull #12: ['Fix MSVC14 warning C4456: declaration of 'x_parent_right' hides previous local declaration]]
4011   *  [@https://svn.boost.org/trac/boost/ticket/10520 Boost Trac #10520: ['Conversion warning in intrusive/detail/utilities.hpp]]
4012   *  [@https://svn.boost.org/trac/boost/ticket/10469 Boost Trac #10469: ['Erasing from intrusive unordered_multiset with optimize_multikey goes into an infinite loop]]
4013
4014[endsect]
4015
4016[section:release_notes_boost_1_56_00 Boost 1.56 Release]
4017
4018*  Improved Doxygen generated reference and updated and fixed forward-declaration header.
4019
4020*  [*ABI breaking]: Fixed ABI regression introduced in Boost 1.55 version, mainly noticeable on MSVC compilers.
4021
4022*  [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers,
4023   `splay_set_base_hook` and `splay_set_member_hook`from splay containers and `bool splay = true`
4024   extra parameter in `splaytree_algorithms` functions.
4025
4026*  Fixed bugs:
4027   *  [@https://svn.boost.org/trac/boost/ticket/8468 #8468: Compile error on visual studio 2010/2012 using vector with custom allocator and aligned types]
4028   *  [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]].
4029   *  [@https://svn.boost.org/trac/boost/ticket/9650 #9650: ['"intrusive list with stateful value traits"]].
4030   *  [@https://svn.boost.org/trac/boost/ticket/9746 #9746: Modern Sun CC compiler detects error in intrusive library header]
4031   *  [@https://svn.boost.org/trac/boost/ticket/9940 #9940: bad bug in intrusive list with safe_link (or auto_unlink) hooks]
4032   *  [@https://svn.boost.org/trac/boost/ticket/9948 #9948: remove use of const_cast in intrusive containers]
4033   *  [@https://svn.boost.org/trac/boost/ticket/9949 #9949: clear header node hooks upon intrusive container destruction]
4034   *  [@https://svn.boost.org/trac/boost/ticket/9961 #9961: tests for hooks not derived frorm generic_hook]
4035
4036*  Optimized tree rebalancing code to avoid redundant assignments.
4037
4038*  Added 64 bit prime values for `suggested_upper_bucket_count`/`suggested_lower_bucket_count` in 64 bit platforms.
4039
4040*  Deleted workarounds for old SUN_CC compilers, those are now unsupported as modern SunPro compilers are standard-corforming enough.
4041
4042[endsect]
4043
4044[section:release_notes_boost_1_55_00 Boost 1.55 Release]
4045
4046*  [*Source breaking]: Deprecated `xxx_dont_splay` functions from splay containers.
4047   Deprecated `splay_set_base_hook` and `splay_set_member_hook`from splay containers, use
4048  `bs_set_base_hook` or `bs_set_member_hook` instead.
4049   Both will be removed in Boost 1.56.
4050
4051*  [*ABI breaking]: Hash containers' end iterator was implemented pointing to one-past the end of the bucket array
4052   (see [@https://svn.boost.org/trac/boost/ticket/8698 #8698]) causing severe bugs when values to be inserted
4053   where allocated next to the bucket array. End iterator implementation was changed to point to the beginning
4054   of the bucket array.
4055
4056*  Big refactoring in order to reduce template and debug symbol bloat. Test object files have been slashed
4057   to half in MSVC compilers in Debug mode. Toolchains without Identical COMDAT Folding (ICF) should notice size improvements.
4058
4059*  Implemented [link intrusive.scary_iterators SCARY iterators].
4060
4061[endsect]
4062
4063[section:release_notes_boost_1_54_00 Boost 1.54 Release]
4064
4065*  Added `BOOST_NO_EXCEPTIONS` support (bug [@https://svn.boost.org/trac/boost/ticket/7849 #7849]).
4066
4067[endsect]
4068
4069[section:release_notes_boost_1_53_00 Boost 1.53 Release]
4070
4071*  Fixed bugs
4072   [@https://svn.boost.org/trac/boost/ticket/7174 #7174],
4073   [@https://svn.boost.org/trac/boost/ticket/7529 #7529],
4074   [@https://svn.boost.org/trac/boost/ticket/7815 #7815].
4075*  Fixed GCC -Wshadow warnings.
4076*  Added missing `explicit` keyword in several intrusive container constructors.
4077*  Replaced deprecated BOOST_NO_XXXX with newer BOOST_NO_CXX11_XXX macros.
4078*  Small documentation fixes.
4079
4080[endsect]
4081
4082[section:release_notes_boost_1_51_00 Boost 1.51 Release]
4083
4084*  Fixed bugs
4085  [@https://svn.boost.org/trac/boost/ticket/6841 #6841],
4086  [@https://svn.boost.org/trac/boost/ticket/6907 #6907],
4087  [@https://svn.boost.org/trac/boost/ticket/6922 #6922],
4088  [@https://svn.boost.org/trac/boost/ticket/7033 #7033],
4089
4090* Added `bounded_range` function to trees.
4091
4092[endsect]
4093
4094[section:release_notes_boost_1_49_00 Boost 1.49 Release]
4095
4096*  Fixed bugs
4097  [@https://svn.boost.org/trac/boost/ticket/6347 #6347],
4098  [@https://svn.boost.org/trac/boost/ticket/6223 #6223],
4099  [@https://svn.boost.org/trac/boost/ticket/6153 #6153].
4100
4101
4102[endsect]
4103
4104[section:release_notes_boost_1_48_00 Boost 1.48 Release]
4105
4106*  Fixed bugs
4107  [@https://svn.boost.org/trac/boost/ticket/4797 #4797],
4108  [@https://svn.boost.org/trac/boost/ticket/5165 #5165],
4109  [@https://svn.boost.org/trac/boost/ticket/5183 #5183],
4110  [@https://svn.boost.org/trac/boost/ticket/5191 #5191].
4111
4112[endsect]
4113
4114[section:release_notes_boost_1_46_00 Boost 1.46 Release]
4115
4116*  Fixed bug
4117  [@https://svn.boost.org/trac/boost/ticket/4980 #4980],
4118
4119[endsect]
4120
4121[section:release_notes_boost_1_45_00 Boost 1.45 Release]
4122
4123*  Added `function_hook` option.
4124*  Fixed bugs
4125  [@https://svn.boost.org/trac/boost/ticket/2611 #2611],
4126  [@https://svn.boost.org/trac/boost/ticket/3288 #3288],
4127  [@https://svn.boost.org/trac/boost/ticket/3304 #3304],
4128  [@https://svn.boost.org/trac/boost/ticket/3489 #3489],
4129  [@https://svn.boost.org/trac/boost/ticket/3668 #3668],
4130  [@https://svn.boost.org/trac/boost/ticket/3339 #3688],
4131  [@https://svn.boost.org/trac/boost/ticket/3698 #3698],
4132  [@https://svn.boost.org/trac/boost/ticket/3706 #3706],
4133  [@https://svn.boost.org/trac/boost/ticket/3721 #3721].
4134  [@https://svn.boost.org/trac/boost/ticket/3729 #3729],
4135  [@https://svn.boost.org/trac/boost/ticket/3746 #3746],
4136  [@https://svn.boost.org/trac/boost/ticket/3781 #3781],
4137  [@https://svn.boost.org/trac/boost/ticket/3840 #3840],
4138  [@https://svn.boost.org/trac/boost/ticket/3849 #3849],
4139  [@https://svn.boost.org/trac/boost/ticket/3339 #3339],
4140  [@https://svn.boost.org/trac/boost/ticket/3419 #3419],
4141  [@https://svn.boost.org/trac/boost/ticket/3431 #3431],
4142  [@https://svn.boost.org/trac/boost/ticket/4021 #4021].
4143
4144[endsect]
4145
4146
4147[section:release_notes_boost_1_40_00 Boost 1.40 Release]
4148
4149*  Code cleanup in bstree_algorithms.hpp and avl_tree_algorithms.hpp
4150*  Fixed bug
4151  [@https://svn.boost.org/trac/boost/ticket/3164 #3164].
4152
4153[endsect]
4154
4155
4156[section:release_notes_boost_1_39_00 Boost 1.39 Release]
4157
4158*  Optimized `list::merge` and `slist::merge`
4159*  `list::sort` and `slist::sort` are now stable.
4160*  Fixed bugs
4161  [@https://svn.boost.org/trac/boost/ticket/2689 #2689],
4162  [@https://svn.boost.org/trac/boost/ticket/2755 #2755],
4163  [@https://svn.boost.org/trac/boost/ticket/2786 #2786],
4164  [@https://svn.boost.org/trac/boost/ticket/2807 #2807],
4165  [@https://svn.boost.org/trac/boost/ticket/2810 #2810],
4166  [@https://svn.boost.org/trac/boost/ticket/2862 #2862].
4167
4168[endsect]
4169
4170[section:release_notes_boost_1_38_00 Boost 1.38 Release]
4171
4172*  New treap-based containers: treap, treap_set, treap_multiset.
4173*  Corrected compilation bug for Windows-based 64 bit compilers.
4174*  Corrected exception-safety bugs in container constructors.
4175*  Updated documentation to show rvalue-references functions instead of emulation functions.
4176
4177[endsect]
4178
4179[section:release_notes_boost_1_37_00 Boost 1.37 Release]
4180
4181*  Intrusive now takes advantage of compilers with variadic templates.
4182*  `clone_from` functions now copy predicates and hash functions of associative containers.
4183*  Added incremental hashing to unordered containers via `incremental<>` option.
4184*  Update some function parameters from `iterator` to `const_iterator` in containers
4185   to keep up with the draft of the next standard.
4186*  Added an option to specify include files for intrusive configurable assertion macros.
4187
4188[endsect]
4189
4190[section:release_notes_boost_1_36_00 Boost 1.36 Release]
4191
4192*  Added `linear<>` and `cache_last<>` options to singly linked lists.
4193*  Added `optimize_multikey<>` option to unordered container hooks.
4194*  Optimized unordered containers when `store_hash` option is used in the hook.
4195*  Implementation changed to be exception agnostic so that it can be used
4196   in environments without exceptions.
4197*  Added `container_from_iterator` function to tree-based containers.
4198
4199[endsect]
4200
4201[endsect]
4202
4203[section:references References]
4204
4205* SGI's [@http://www.sgi.com/tech/stl/ STL Programmer's Guide].
4206   [*Boost.Intrusive] is based on STL concepts and interfaces.
4207
4208* Dr. Dobb's, September 1, 2005: [@http://www.ddj.com/architect/184402007 ['Implementing Splay Trees in C++] ].
4209   [*Boost.Intrusive] splay containers code is based on this article.
4210
4211* Olaf's original intrusive container library: [@http://freenet-homepage.de/turtle++/intrusive.html ['STL-like intrusive containers] ].
4212
4213[endsect]
4214
4215[section:acknowledgements Acknowledgements]
4216
4217[*Olaf Krzikalla] would like to thank:
4218
4219*  [*Markus Schaaf] for pointing out the possibility and the advantages of the derivation
4220approach.
4221
4222*  [*Udo Steinbach] for encouragements to present this work for boost, a lot of fixes and
4223helpful discussions.
4224
4225*  [*Jaap Suter] for the initial hint, which eventually lead to the member value_traits.
4226
4227[*Ion Gaztanaga] would like to thank:
4228
4229*  [*Olaf Krzikalla] for the permission to continue his great work.
4230
4231*  [*Joaquin M. Lopez Munoz] for his thorough review, help, and ideas.
4232
4233*  [*Cory Nelson], [*Daniel James], [*Dave Harris], [*Guillaume Melquiond],
4234   [*Henri Bavestrello], [*Hervé Bronnimann], [*Kai Bruning], [*Kevin Sopp],
4235   [*Paul Rose], [*Pavel Vozelinek], [*Howard Hinnant], [*Olaf Krzikalla],
4236   [*Samuel Debionne], [*Stjepan Rajko], [*Thorsten Ottosen], [*Tobias Schwinger],
4237   [*Tom Brinkman] and [*Steven Watanabe]
4238   for their comments and reviews in the Boost.Intrusive formal review.
4239
4240*  Thanks to [*Julienne Walker] and [*The EC Team] ([@http://eternallyconfuzzled.com])
4241   for their great algorithms.
4242
4243*  Thanks to [*Daniel K. O.] for his AVL tree rebalancing code.
4244
4245*  Thanks to [*Ralf Mattethat] for his splay tree article and code.
4246
4247*  Special thanks to [*Steven Watanabe] and [*Tobias Schwinger] for their
4248   invaluable suggestions and improvements.
4249
4250[endsect]
4251
4252[include auto_index_helpers.qbk]
4253
4254[section:index Indexes]
4255
4256[named_index class_name Class Index]
4257[named_index typedef_name Typedef Index]
4258[named_index function_name Function Index]
4259[named_index macro_name Macro Index]
4260[/index]
4261
4262[endsect]
4263
4264[xinclude autodoc.xml]
4265