indices.html 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  5. <title>Boost.MultiIndex Documentation - Tutorial - Index types</title>
  6. <link rel="stylesheet" href="../style.css" type="text/css">
  7. <link rel="start" href="../index.html">
  8. <link rel="prev" href="basics.html">
  9. <link rel="up" href="index.html">
  10. <link rel="next" href="key_extraction.html">
  11. </head>
  12. <body>
  13. <h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
  14. "middle" width="277" height="86">Boost.MultiIndex Tutorial: Index types</h1>
  15. <div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
  16. Basics
  17. </a></div>
  18. <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
  19. Boost.MultiIndex tutorial
  20. </a></div>
  21. <div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key estraction" border="0"><br>
  22. Key extraction
  23. </a></div><br clear="all" style="clear: all;">
  24. <hr>
  25. <h2>Contents</h2>
  26. <ul>
  27. <li><a href="#classification">Classification</a>
  28. <li><a href="#rnk_indices">Ranked indices</a>
  29. <ul>
  30. <li><a href="#rnk_spec">Specification</a></li>
  31. <li><a href="#rnk_ops">Rank operations</a></li>
  32. </ul>
  33. </li>
  34. <li><a href="#hashed_indices">Hashed indices</a>
  35. <ul>
  36. <li><a href="#hash_unique_non_unique">Unique and non-unique variants</a></li>
  37. <li><a href="#hash_spec">Specification</a></li>
  38. <li><a href="#hash_lookup">Lookup</a></li>
  39. <li><a href="#hash_updating">Updating</a></li>
  40. <li><a href="#guarantees">Guarantees on iterator validity and exception safety</a></li>
  41. </ul>
  42. </li>
  43. <li><a href="#rnd_indices">Random access indices</a>
  44. <ul>
  45. <li><a href="#rnd_spec">Specification</a></li>
  46. <li><a href="#rnd_interface">Interface</a></li>
  47. <li><a href="#rnd_vs_vector">Comparison with <code>std::vector</code></a></li>
  48. </ul>
  49. </li>
  50. <li><a href="#rearrange">Index rearranging</a></li>
  51. <li><a href="#iterator_to"><code>iterator_to</code></a></li>
  52. <li><a href="#ordered_node_compression">Ordered indices node compression</a></li>
  53. </ul>
  54. <h2><a name="classification">Classification</a></h2>
  55. <p>
  56. Boost.MultiIndex provides eight different index types, which can be classified as
  57. shown in the table below. <a href="basics.html#ord_indices">Ordered</a> and
  58. <a href="basics.html#seq_indices">sequenced</a> indices,
  59. which are the most commonly used, have been explained in the basics section;
  60. the rest of index types can be regarded as variations of the former providing
  61. some added benefits, functionally or in the area of performance.
  62. </p>
  63. <p align="center">
  64. <table cellspacing="0">
  65. <caption><b>Boost.MultiIndex indices.</b></caption>
  66. <tr>
  67. <th align="center"colspan="2">type</th>
  68. <th align="center">specifier</th>
  69. </tr>
  70. <tr>
  71. <td align="center" rowspan="6">&nbsp;&nbsp;key-based&nbsp;&nbsp;</td>
  72. <td align="center" rowspan="4">&nbsp;&nbsp;ordered&nbsp;&nbsp;</td>
  73. <td align="center">&nbsp;&nbsp;<code>ordered_unique</code>&nbsp;&nbsp;</td>
  74. </tr>
  75. <tr class="odd_tr">
  76. <td align="center">&nbsp;&nbsp;<code>ordered_non_unique</code>&nbsp;&nbsp;</td>
  77. </tr>
  78. <tr>
  79. <td align="center">&nbsp;&nbsp;<code>ranked_unique</code>&nbsp;&nbsp;</td>
  80. </tr>
  81. <tr class="odd_tr">
  82. <td align="center">&nbsp;&nbsp;<code>ranked_non_unique</code>&nbsp;&nbsp;</td>
  83. </tr>
  84. <tr>
  85. <td align="center" rowspan="2">&nbsp;&nbsp;hashed&nbsp;&nbsp;</td>
  86. <td align="center">&nbsp;&nbsp;<code>hashed_unique</code>&nbsp;&nbsp;</td>
  87. </tr>
  88. <tr class="odd_tr">
  89. <td align="center">&nbsp;&nbsp;<code>hashed_non_unique</code>&nbsp;&nbsp;</td>
  90. </tr>
  91. <tr>
  92. <td align="center" rowspan="2" colspan="2">&nbsp;&nbsp;non key-based&nbsp;&nbsp;</td>
  93. <td align="center"><code>&nbsp;&nbsp;sequenced&nbsp;&nbsp;</code></td>
  94. </tr>
  95. <tr class="odd_tr">
  96. <td align="center"><code>&nbsp;&nbsp;random_access&nbsp;&nbsp;</code></td>
  97. </tr>
  98. </table>
  99. </p>
  100. <p>
  101. Key-based indices, of which ordered indices are the usual example, provide
  102. efficient lookup of elements based on some piece of information called the
  103. <i>element key</i>: there is an extensive suite of
  104. <a href="key_extraction.html">key extraction</a>
  105. utility classes allowing for the specification of such keys. Fast lookup
  106. imposes an internally managed order on these indices that the user is not
  107. allowed to modify; non key-based indices, on the other hand, can be freely
  108. rearranged at the expense of lacking lookup facilities. Sequenced indices,
  109. modeled after the interface of <code>std::list</code>, are the customary
  110. example of a non key-based index.
  111. </p>
  112. <h2><a name="rnk_indices">Ranked indices</a></h2>
  113. <p>
  114. Suppose we have a <code>std::multiset</code> of numbers and we want to output
  115. the values above the 75h <a href="http://en.wikipedia.org/wiki/Percentile">percentile</a>:
  116. </p>
  117. <blockquote><pre>
  118. <span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=identifier>int_multiset</span><span class=special>;</span>
  119. <span class=keyword>void</span> <span class=identifier>output_above_75th_percentile</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>int_multiset</span><span class=special>&amp;</span> <span class=identifier>s</span><span class=special>)</span>
  120. <span class=special>{</span>
  121. <span class=identifier>int_multiset</span><span class=special>::</span><span class=identifier>const_iterator</span> <span class=identifier>it</span><span class=special>=</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>begin</span><span class=special>();</span>
  122. <span class=identifier>std</span><span class=special>::</span><span class=identifier>advance</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>size</span><span class=special>()*</span><span class=number>3</span><span class=special>/</span><span class=number>4</span><span class=special>);</span> <span class=comment>// linear on s.size();</span>
  123. <span class=identifier>std</span><span class=special>::</span><span class=identifier>copy</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream_iterator</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>,</span><span class=string>&quot;\n&quot;</span><span class=special>));</span>
  124. <span class=special>}</span>
  125. </pre></blockquote>
  126. <p>
  127. The problem with this code is that getting to the beginning of the desired subsequence
  128. involves a linear traversal of the container. Ranked indices provide the mechanisms to do this
  129. much faster:
  130. </p>
  131. <blockquote><pre>
  132. <span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
  133. <span class=keyword>int</span><span class=special>,</span>
  134. <span class=identifier>indexed_by</span><span class=special>&lt;</span>
  135. <span class=identifier>ranked_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
  136. <span class=special>&gt;</span>
  137. <span class=special>&gt;</span> <span class=identifier>int_multiset</span><span class=special>;</span>
  138. <span class=keyword>void</span> <span class=identifier>output_above_75th_percentile</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>int_multiset</span><span class=special>&amp;</span> <span class=identifier>s</span><span class=special>)</span>
  139. <span class=special>{</span>
  140. <span class=identifier>int_multiset</span><span class=special>::</span><span class=identifier>const_iterator</span> <span class=identifier>it</span><span class=special>=</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>nth</span><span class=special>(</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>size</span><span class=special>()*</span><span class=number>3</span><span class=special>/</span><span class=number>4</span><span class=special>);</span> <span class=comment>// logarithmic</span>
  141. <span class=identifier>std</span><span class=special>::</span><span class=identifier>copy</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream_iterator</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>,</span><span class=string>&quot;\n&quot;</span><span class=special>));</span>
  142. <span class=special>}</span>
  143. </pre></blockquote>
  144. <p>
  145. <code>nth(n)</code> returns an iterator to the element whose <i>rank</i>, i.e. its distance
  146. from the beginning of the index, is <code>n</code>, and does so efficiently in logarithmic time.
  147. Conversely, <code>rank(it)</code> computes in logarithmic time the rank of the element
  148. pointed to by <code>it</code>, or <code>size()</code> if <code>it==end()</code>.
  149. </p>
  150. <blockquote><pre>
  151. <span class=identifier>int_multiset</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>10</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
  152. <span class=identifier>int_multiset</span><span class=special>::</span><span class=identifier>size_type</span> <span class=identifier>r</span><span class=special>=</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>rank</span><span class=special>(</span><span class=identifier>it</span><span class=special>);</span> <span class=comment>// rank of 10;</span>
  153. </pre></blockquote>
  154. <p>
  155. Ranked indices provide the same interface as ordered indices plus several rank-related operations.
  156. The cost of this extra functionality is higher memory consumption due to some internal additional
  157. data (one word per element) and somewhat longer execution times in insertion and erasure
  158. &#8212;in particular, erasing an element takes time proportional to <code>log(n)</code>, where
  159. <code>n</code> is the number of elements in the index, whereas for ordered indices this time is
  160. constant.
  161. The <a href="../reference/rnk_indices.html">reference</a> describes these indices in complete detail.
  162. </p>
  163. <h3><a name="rnk_spec">Specification</a></h3>
  164. <p>
  165. The specification of ranked indices is done exactly as with <a href="basics.html#ord_spec">ordered indices</a>,
  166. except that <code>ranked_unique</code> and <code>ranked_non_unique</code> are used instead.
  167. </p>
  168. <blockquote><pre>
  169. <span class=special>(</span><span class=identifier>ranked_unique</span> <span class=special>|</span> <span class=identifier>ranked_non_unique</span><span class=special>)
  170. </span><span class=special>&lt;[</span><i>(tag)</i><span class=special>[,</span><i>(key extractor)</i><span class=special>[,</span><i>(comparison predicate)</i><span class=special>]]]&gt;</span>
  171. <span class=special>(</span><span class=identifier>ranked_unique</span> <span class=special>|</span> <span class=identifier>ranked_non_unique</span><span class=special>)</span>
  172. <span class=special>&lt;[</span><i>(key extractor)</i><span class=special>[,</span><i>(comparison predicate)</i><span class=special>]]&gt;</span>
  173. </pre></blockquote>
  174. <h3><a name="rnk_ops">Rank operations</a></h3>
  175. <p>
  176. Besides <code>nth</code> and <code>rank</code>, ranked indices provide member functions
  177. <ul>
  178. <li><code>find_rank</code>,</li>
  179. <li><code>lower_bound_rank</code>,</li>
  180. <li><code>upper_bound_rank</code>,</li>
  181. <li><code>equal_range_rank</code> and </li>
  182. <li><code>range_rank</code></li>
  183. </ul>
  184. that behave as their normal
  185. <a href="basics.html#special_lookup">lookup</a> and <a href="basics.html#range">range retrieval</a>
  186. counterparts (<code>find</code>, <code>lower_bound</code> etc.) but return ranks rather than iterators.
  187. </p>
  188. <blockquote><pre>
  189. <span class=keyword>void</span> <span class=identifier>percentile</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>n</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>int_multiset</span><span class=special>&amp;</span> <span class=identifier>s</span><span class=special>)</span>
  190. <span class=special>{</span>
  191. <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=identifier>n</span><span class=special>&lt;&lt;</span><span class=string>&quot; lies in the &quot;</span><span class=special>&lt;&lt;</span>
  192. <span class=identifier>s</span><span class=special>.</span><span class=identifier>upper_bound_rank</span><span class=special>(</span><span class=identifier>n</span><span class=special>)*</span><span class=number>100.0</span><span class=special>/</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>size</span><span class=special>()&lt;&lt;</span><span class=string>&quot; percentile\n&quot;</span><span class=special>;</span>
  193. <span class=special>}</span>
  194. </pre></blockquote>
  195. <p>
  196. You might think that <code>upper_bound_rank(n)</code> is mere shorthand for
  197. <code>rank(upper_bound(n))</code>: in reality, though, you should prefer using
  198. <code>*_rank</code> operations directly as they run faster than the
  199. alternative formulations.
  200. </p>
  201. <h2><a name="hashed_indices">Hashed indices</a></h2>
  202. <p>
  203. Hashed indices constitute a trade-off with respect to ordered indices: if correctly used,
  204. they provide much faster lookup of elements, at the expense of losing sorting
  205. information.
  206. Let us revisit our <code>employee_set</code> example: suppose a field for storing
  207. the Social Security number is added, with the requisite that lookup by this
  208. number should be as fast as possible. Instead of the usual ordered index, a
  209. hashed index can be resorted to:
  210. </p>
  211. <blockquote><pre>
  212. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  213. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>hashed_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  214. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  215. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  216. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  217. <span class=keyword>struct</span> <span class=identifier>employee</span>
  218. <span class=special>{</span>
  219. <span class=keyword>int</span> <span class=identifier>id</span><span class=special>;</span>
  220. <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
  221. <span class=keyword>int</span> <span class=identifier>ssnumber</span><span class=special>;</span>
  222. <span class=identifier>employee</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>id</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>name</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>ssnumber</span><span class=special>):</span>
  223. <span class=identifier>id</span><span class=special>(</span><span class=identifier>id</span><span class=special>),</span><span class=identifier>name</span><span class=special>(</span><span class=identifier>name</span><span class=special>),</span><span class=identifier>ssnumber</span><span class=special>(</span><span class=identifier>ssnumber</span><span class=special>){}</span>
  224. <span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&amp;</span> <span class=identifier>e</span><span class=special>)</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>id</span><span class=special>&lt;</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
  225. <span class=special>};</span>
  226. <span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
  227. <span class=identifier>employee</span><span class=special>,</span>
  228. <span class=identifier>indexed_by</span><span class=special>&lt;</span>
  229. <span class=comment>// sort by employee::operator&lt;</span>
  230. <span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
  231. <span class=comment>// sort by less&lt;string&gt; on name</span>
  232. <span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
  233. <span class=comment>// hashed on ssnumber</span>
  234. <span class=identifier>hashed_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>ssnumber</span><span class=special>&gt;</span> <span class=special>&gt;</span>
  235. <span class=special>&gt;</span>
  236. <span class=special>&gt;</span> <span class=identifier>employee_set</span>
  237. </pre></blockquote>
  238. <p>
  239. Note that the hashed index does not guarantee any particular ordering of the
  240. elements: so, for instance, we cannot efficiently query the employees whose SSN is
  241. greater than a given number. Usually, you must consider these restrictions when
  242. determining whether a hashed index is preferred over an ordered one.
  243. </p>
  244. <p>
  245. Hashed indices replicate the interface as <code>std::unordered_set</code> and
  246. <code>std::unordered_multiset</code>, with only minor differences where required
  247. by the general constraints of <code>multi_index_container</code>s, and provide
  248. additional useful capabilities like in-place updating of elements.
  249. Check the <a href="../reference/hash_indices.html">reference</a> for a
  250. complete specification of the interface of hashed indices,
  251. and <a href="../examples.html#example8">example 8</a> and
  252. <a href="../examples.html#example9">example 9</a> for practical applications.
  253. </p>
  254. </p>
  255. <h3><a name="hash_unique_non_unique">Unique and non-unique variants</a></h3>
  256. <p>
  257. Just like ordered indices, hashed indices have unique and non-unique variants, selected
  258. with the specifiers <code>hashed_unique</code> and <code>hashed_non_unique</code>,
  259. respectively. In the latter case, elements with equivalent keys are kept together and can
  260. be jointly retrieved by means of the <code>equal_range</code> member function.
  261. </p>
  262. <h3><a name="hash_spec">Specification</a></h3>
  263. <p>
  264. Hashed indices specifiers have two alternative syntaxes, depending on whether
  265. <a href="basics.html#tagging">tags</a> are provided or not:
  266. </p>
  267. <blockquote><pre>
  268. <span class=special>(</span><span class=identifier>hashed_unique</span> <span class=special>|</span> <span class=identifier>hashed_non_unique</span><span class=special>)
  269. </span><span class=special>&lt;[</span><i>(tag)</i><span class=special>[,</span><i>(key extractor)</i><span class=special>[,</span><i>(hash function)</i><span class=special>[,</span><i>(equality predicate)</i><span class=special>]]]]&gt;</span>
  270. <span class=special>(</span><span class=identifier>hashed_unique</span> <span class=special>|</span> <span class=identifier>hashed_non_unique</span><span class=special>)</span>
  271. <span class=special>&lt;[</span><i>(key extractor)</i><span class=special>[,</span><i>(hash function)</i><span class=special>[,</span><i>(equality predicate)</i><span class=special>]]]&gt;</span>
  272. </pre></blockquote>
  273. <p>
  274. The key extractor parameter works in exactly the same way as for
  275. <a href="basics.html#key_extraction">ordered indices</a>; lookup, insertion,
  276. etc., are based on the key returned by the extractor rather than the whole
  277. element.
  278. </p>
  279. <p>
  280. The hash function is the very core of the fast lookup capabilities of this type of
  281. indices: a hasher is just a unary function object
  282. returning an <code>std::size_t</code> value for any given
  283. key. In general, it is impossible that every key map to a different hash value, for
  284. the space of keys can be greater than the number of permissible hash codes: what
  285. makes for a good hasher is that the probability of a collision (two different
  286. keys with the same hash value) is as close to zero as possible. This is a statistical
  287. property depending on the typical distribution of keys in a given application, so
  288. it is not feasible to have a general-purpose hash function with excellent results
  289. in <i>every</i> possible scenario; the default value for this parameter uses
  290. <a href="../../../functional/hash/index.html">Boost.Hash</a>, which often provides good
  291. enough results.
  292. </p>
  293. <p>
  294. The equality predicate is used to determine whether two keys are to be treated
  295. as the same. The default
  296. value <code>std::equal_to&lt;KeyFromValue::result_type&gt;</code> is in most
  297. cases exactly what is needed, so very rarely will you have to provide
  298. your own predicate. Note that hashed indices require that two
  299. equivalent keys have the same hash value, which
  300. in practice greatly reduces the freedom in choosing an equality predicate.
  301. </p>
  302. <h3><a name="hash_lookup">Lookup</a></h3>
  303. <p>
  304. The lookup interface of hashed indices consists in member functions
  305. <code>find</code>, <code>count</code> and <code>equal_range</code>.
  306. Note that <code>lower_bound</code> and <code>upper_bound</code> are not
  307. provided, as there is no intrinsic ordering of keys in this type of indices.
  308. </p>
  309. <p>
  310. Just as with ordered indices, these member functions take keys
  311. as their search arguments, rather than entire objects. Remember that
  312. ordered indices lookup operations are further augmented to accept
  313. <i>compatible keys</i>, which can roughly be regarded as "subkeys".
  314. For hashed indices, a concept of
  315. <a href="../reference/hash_indices.html#lookup">compatible key</a> is also
  316. supported, though its usefulness is much more limited: basically,
  317. a compatible key is an object which is entirely equivalent to
  318. a native object of <code>key_type</code> value, though maybe with
  319. a different internal representation:
  320. </p>
  321. <blockquote><pre>
  322. <span class=comment>// US SSN numbering scheme</span>
  323. <span class=keyword>struct</span> <span class=identifier>ssn</span>
  324. <span class=special>{</span>
  325. <span class=identifier>ssn</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>area_no</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>group_no</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>serial_no</span><span class=special>):</span>
  326. <span class=identifier>area_no</span><span class=special>(</span><span class=identifier>area_no</span><span class=special>),</span><span class=identifier>group_no</span><span class=special>(</span><span class=identifier>group_no</span><span class=special>),</span><span class=identifier>serial_no</span><span class=special>(</span><span class=identifier>serial_no</span><span class=special>)</span>
  327. <span class=special>{}</span>
  328. <span class=keyword>int</span> <span class=identifier>to_int</span><span class=special>()</span><span class=keyword>const</span>
  329. <span class=special>{</span>
  330. <span class=keyword>return</span> <span class=identifier>serial_no</span><span class=special>+</span><span class=number>10000</span><span class=special>*</span><span class=identifier>group_no</span><span class=special>+</span><span class=number>1000000</span><span class=special>*</span><span class=identifier>area_no</span><span class=special>;</span>
  331. <span class=special>}</span>
  332. <span class=keyword>private</span><span class=special>:</span>
  333. <span class=keyword>int</span> <span class=identifier>area_no</span><span class=special>;</span>
  334. <span class=keyword>int</span> <span class=identifier>group_no</span><span class=special>;</span>
  335. <span class=keyword>int</span> <span class=identifier>serial_no</span><span class=special>;</span>
  336. <span class=special>};</span>
  337. <span class=comment>// interoperability with SSNs in raw int form</span>
  338. <span class=keyword>struct</span> <span class=identifier>ssn_equal</span>
  339. <span class=special>{</span>
  340. <span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ssn</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span>
  341. <span class=special>{</span>
  342. <span class=keyword>return</span> <span class=identifier>x</span><span class=special>.</span><span class=identifier>to_int</span><span class=special>()==</span><span class=identifier>y</span><span class=special>;</span>
  343. <span class=special>}</span>
  344. <span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>int</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>ssn</span><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span>
  345. <span class=special>{</span>
  346. <span class=keyword>return</span> <span class=identifier>x</span><span class=special>==</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>to_int</span><span class=special>();</span>
  347. <span class=special>}</span>
  348. <span class=special>};</span>
  349. <span class=keyword>struct</span> <span class=identifier>ssn_hash</span>
  350. <span class=special>{</span>
  351. <span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ssn</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span>
  352. <span class=special>{</span>
  353. <span class=keyword>return</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;()(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>to_int</span><span class=special>());</span>
  354. <span class=special>}</span>
  355. <span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>int</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span>
  356. <span class=special>{</span>
  357. <span class=keyword>return</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;()(</span><span class=identifier>x</span><span class=special>);</span>
  358. <span class=special>}</span>
  359. <span class=special>};</span>
  360. <span class=keyword>typedef</span> <span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>2</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>employee_set_by_ssn</span><span class=special>;</span>
  361. <span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
  362. <span class=identifier>employee_set_by_ssn</span><span class=special>&amp;</span> <span class=identifier>ssn_index</span><span class=special>=</span><span class=identifier>es</span><span class=special>.</span><span class=identifier>get</span><span class=special>&lt;</span><span class=number>2</span><span class=special>&gt;();</span>
  363. <span class=special>...</span>
  364. <span class=comment>// find an employee by ssn</span>
  365. <span class=identifier>employee</span> <span class=identifier>e</span><span class=special>=*(</span><span class=identifier>ssn_index</span><span class=special>.</span><span class=identifier>find</span><span class=special>(</span><span class=identifier>ssn</span><span class=special>(</span><span class=number>12</span><span class=special>,</span><span class=number>1005</span><span class=special>,</span><span class=number>20678</span><span class=special>),</span><span class=identifier>ssn_hash</span><span class=special>(),</span><span class=identifier>ssn_equal</span><span class=special>()));</span>
  366. </pre></blockquote>
  367. <p>
  368. In the example, we provided a hash functor <code>ssn_hash</code> and an
  369. equality predicate <code>ssn_equal</code> allowing for interoperability
  370. between <code>ssn</code> objects and the raw <code>int</code>s stored as
  371. <code>SSN</code>s in <code>employee_set</code>.
  372. </p>
  373. <p>
  374. By far, the most useful application of compatible keys in the context
  375. of hashed indices lies in the fact that they allow for seamless usage of
  376. <a href="key_extraction.html#composite_keys">composite keys</a>.
  377. </p>
  378. <h3><a name="hash_updating">Updating</a></h3>
  379. <p>
  380. Hashed indices have
  381. <a href="../reference/hash_indices.html#replace"><code>replace</code></a>,
  382. <a href="../reference/hash_indices.html#modify"><code>modify</code></a> and
  383. <a href="../reference/hash_indices.html#modify_key"><code>modify_key</code></a>
  384. member functions, with the same functionality as in ordered indices.
  385. </p>
  386. <h3><a name="guarantees">Guarantees on iterator validity and exception safety</a></h3>
  387. <p>
  388. Due to the internal constraints imposed by the Boost.MultiIndex framework,
  389. hashed indices provide guarantees on iterator validity and
  390. exception safety that are actually stronger than required by the
  391. C++ standard with respect to unordered associative containers:
  392. <ul>
  393. <li>Iterator validity is preserved in any case during insertion or rehashing:
  394. C++ unordered associative containers can invalidate iterators when a rehash (implicit or explicit)
  395. is performed.</li>
  396. <li>Erasing an element or range of elements via iterators does not throw ever,
  397. as the internal hash function and equality predicate objects are not actually
  398. invoked.</li>
  399. <li><code>rehash</code> provides the strong exception safety guarantee
  400. unconditionally. The standard only warrants it for unordered associative containers if the internal hash function and
  401. equality predicate objects do not throw. The somewhat surprising consequence
  402. is that a standard-compliant <code>std::unordered_set</code> might erase
  403. elements if an exception is thrown during rehashing!</li>
  404. </ul>
  405. In general, these stronger guarantees play in favor of the user's convenience,
  406. specially that which refers to iterator stability. A (hopefully minimal)
  407. degradation in performance might result in exchange for these commodities,
  408. though.
  409. </p>
  410. <h2><a name="rnd_indices">Random access indices</a></h2>
  411. <p>
  412. Random access indices offer the same kind of functionality as
  413. <a href="basics.html#seq_indices">sequenced indices</a>, with the extra advantages
  414. that their iterators are random access, and <code>operator[]</code>
  415. and <code>at()</code> are provided for accessing
  416. elements based on their position in the index. Let us rewrite a
  417. container used in a previous <a href="basics.html#list_fast_lookup">example</a>,
  418. using random access instead of sequenced indices:
  419. </p>
  420. <blockquote><pre>
  421. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  422. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>random_access_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  423. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  424. <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
  425. <span class=comment>// text container with fast lookup based on a random access index</span>
  426. <span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
  427. <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
  428. <span class=identifier>indexed_by</span><span class=special>&lt;</span>
  429. <span class=identifier>random_access</span><span class=special>&lt;&gt;,</span>
  430. <span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=special>&gt;</span>
  431. <span class=special>&gt;</span>
  432. <span class=special>&gt;</span> <span class=identifier>text_container</span><span class=special>;</span>
  433. <span class=comment>// global text container object</span>
  434. <span class=identifier>text_container</span> <span class=identifier>tc</span><span class=special>;</span>
  435. </pre></blockquote>
  436. <p>
  437. Random access capabilities allow us to efficiently write code
  438. like the following:
  439. </p>
  440. <blockquote><pre>
  441. <span class=keyword>void</span> <span class=identifier>print_page</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>page_num</span><span class=special>)</span>
  442. <span class=special>{</span>
  443. <span class=keyword>static</span> <span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>words_per_page</span><span class=special>=</span><span class=number>50</span><span class=special>;</span>
  444. <span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>pos0</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>min</span><span class=special>(</span><span class=identifier>tc</span><span class=special>.</span><span class=identifier>size</span><span class=special>(),</span><span class=identifier>page_num</span><span class=special>*</span><span class=identifier>words_per_page</span><span class=special>);</span>
  445. <span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>pos1</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>min</span><span class=special>(</span><span class=identifier>tc</span><span class=special>.</span><span class=identifier>size</span><span class=special>(),</span><span class=identifier>pos0</span><span class=special>+</span><span class=identifier>words_per_page</span><span class=special>);</span>
  446. <span class=comment>// note random access iterators can be added offsets</span>
  447. <span class=identifier>std</span><span class=special>::</span><span class=identifier>copy</span><span class=special>(</span>
  448. <span class=identifier>tc</span><span class=special>.</span><span class=identifier>begin</span><span class=special>()+</span><span class=identifier>pos0</span><span class=special>,</span><span class=identifier>tc</span><span class=special>.</span><span class=identifier>begin</span><span class=special>()+</span><span class=identifier>pos1</span><span class=special>,</span>
  449. <span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream_iterator</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>));</span>
  450. <span class=special>}</span>
  451. <span class=keyword>void</span> <span class=identifier>print_random_word</span><span class=special>()</span>
  452. <span class=special>{</span>
  453. <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=identifier>tc</span><span class=special>[</span><span class=identifier>rand</span><span class=special>()%</span><span class=identifier>tc</span><span class=special>.</span><span class=identifier>size</span><span class=special>()];</span>
  454. <span class=special>}</span>
  455. </pre></blockquote>
  456. <p>
  457. This added flexibility comes at a price: insertions and deletions at positions
  458. other than the end of the index have linear complexity, whereas these operations
  459. are constant time for sequenced indices. This situation is reminiscent of the
  460. differences in complexity behavior between <code>std::list</code> and
  461. <code>std::vector</code>: in the case of random access indices, however,
  462. insertions and deletions never incur any element copying, so the actual
  463. performance of these operations can be acceptable, despite the theoretical
  464. disadvantage with respect to sequenced indices.
  465. </p>
  466. <p>
  467. <a href="../examples.html#example10">Example 10</a> and
  468. <a href="../examples.html#example11">example 11</a> in the examples section put
  469. random access indices in practice.
  470. </p>
  471. <h3><a name="rnd_spec">Specification</a></h3>
  472. <p>
  473. Random access indices are specified with the <code>random_access</code> construct,
  474. where the <a href="basics.html#tagging">tag</a> parameter is, as usual, optional:
  475. </p>
  476. <blockquote><pre>
  477. <span class=identifier>random_access</span><span class=special>&lt;[</span><i>(tag)</i><span class=special>]&gt;</span>
  478. </pre></blockquote>
  479. <h3><a name="rnd_interface">Interface</a></h3>
  480. <p>
  481. All public functions offered by sequenced indices are also provided
  482. by random access indices, so that the latter can act as a drop-in replacement
  483. of the former (save with respect to their complexity bounds, as explained above).
  484. Besides, random access
  485. indices have <code>operator[]</code> and <code>at()</code> for positional
  486. access to the elements, and member functions
  487. <a href="../reference/rnd_indices.html#capacity_memfun"><code>capacity</code></a> and
  488. <a href="../reference/rnd_indices.html#reserve"><code>reserve</code></a>
  489. that control internal reallocation in a similar manner as the homonym
  490. facilities in <code>std::vector</code>. Check the
  491. <a href="../reference/rnd_indices.html">reference</a> for details.
  492. </p>
  493. <h3><a name="rnd_vs_vector">Comparison with <code>std::vector</code></a></h3>
  494. <p>
  495. It is tempting to see random access indices as an analogue of <code>std::vector</code>
  496. for use in Boost.MultiIndex, but this metaphor can be misleading, as both constructs,
  497. though similar in many respects, show important semantic differences. An
  498. advantage of random access indices is that their iterators, as well as references
  499. to their elements, are <i>stable</i>, that is, they remain valid after any insertions
  500. or deletions. On the other hand, random access indices have several disadvantages with
  501. respect to <code>std::vector</code>s:
  502. <ul>
  503. <li>They do not provide <i>memory contiguity</i>, a property
  504. of <code>std::vector</code>s by which elements are stored adjacent to one
  505. another in a single block of memory.
  506. </li>
  507. <li>As usual in Boost.MultiIndex, elements of random access indices are immutable
  508. and can only be modified through member functions
  509. <a href="../reference/rnd_indices.html#replace"><code>replace</code></a> and
  510. <a href="../reference/rnd_indices.html#modify"><code>modify</code></a>.
  511. This precludes the usage of many mutating
  512. algorithms that are nonetheless applicable to <code>std::vector</code>s.
  513. </li>
  514. </ul>
  515. The latter shortcoming can be partially remedied by means of the
  516. <a href="#rearrange">rearranging interface</a> these indices provide.
  517. </p>
  518. <p>
  519. In general, it is more instructive to regard random access indices as
  520. a variation of sequenced indices providing random access semantics, instead
  521. of insisting on the <code>std::vector</code> analogy.
  522. </p>
  523. <h2><a name="rearrange">Index rearranging</a></h2>
  524. <p>
  525. By design, index elements are immutable, i.e. iterators only grant
  526. <code>const</code> access to them, and only through the provided
  527. updating interface (<code>replace</code>, <code>modify</code> and
  528. <code>modify_key</code>) can the elements be modified. This restriction
  529. is set up so that the internal invariants of key-based indices are
  530. not broken (for instance, ascending order traversal in ordered
  531. indices), but induces important limitations in non key-based indices:
  532. </p>
  533. <blockquote><pre>
  534. <span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
  535. <span class=keyword>int</span><span class=special>,</span>
  536. <span class=identifier>indexed_by</span><span class=special>&lt;</span>
  537. <span class=identifier>random_access</span><span class=special>&lt;&gt;,</span>
  538. <span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
  539. <span class=special>&gt;</span>
  540. <span class=special>&gt;</span> <span class=identifier>container</span><span class=special>;</span>
  541. <span class=identifier>container</span> <span class=identifier>c</span><span class=special>;</span>
  542. <span class=identifier>std</span><span class=special>::</span><span class=identifier>mt19937</span> <span class=identifier>rng</span><span class=special>;</span>
  543. <span class=special>...</span>
  544. <span class=comment>// compiler error: assignment to read-only objects</span>
  545. <span class=identifier>std</span><span class=special>::</span><span class=identifier>shuffle</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>rng</span><span class=special>);</span>
  546. </pre></blockquote>
  547. <p>
  548. What is unfortunate about the previous example is that the operation
  549. performed by <code>std::shuffle</code> is potentially compatible
  550. with <code>multi_index_container</code> invariants, as its result can be
  551. described by a permutation of the elements in the random access index
  552. with no actual modifications to the elements themselves. There are many
  553. more examples of such compatible algorithms in the C++ standard library,
  554. like for instance all sorting and partition functions.
  555. </p>
  556. <p>
  557. Sequenced and random access indices provide a means to take advantage
  558. of such external algorithms. In order to introduce this facility we need
  559. a preliminary concept: a <i>view</i> of an index is defined as
  560. some iterator range [<code>first</code>,<code>last</code>) over the
  561. elements of the index such that all its elements are contained in the
  562. range exactly once. Continuing with our example, we can apply
  563. <code>std::shuffle</code> on an ad hoc view obtained from the
  564. container:
  565. </p>
  566. <blockquote><pre>
  567. <span class=comment>// note that the elements of the view are not copies of the elements
  568. // in c, but references to them</span>
  569. <span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>v</span><span class=special>;</span>
  570. <span class=identifier>BOOST_FOREACH</span><span class=special>(</span><span class=keyword>const</span> <span class=keyword>int</span><span class=special>&amp;</span> <span class=identifier>i</span><span class=special>,</span><span class=identifier>c</span><span class=special>)</span><span class=identifier>v</span><span class=special>.</span><span class=identifier>push_back</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>cref</span><span class=special>(</span><span class=identifier>i</span><span class=special>));</span>
  571. <span class=comment>// this compiles OK, as reference_wrappers are swappable</span>
  572. <span class=identifier>std</span><span class=special>::</span><span class=identifier>shuffle</span><span class=special>(</span><span class=identifier>v</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>v</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>rng</span><span class=special>);</span>
  573. </pre></blockquote>
  574. <p>
  575. Elements of <code>v</code> are <code>reference_wrapper</code>s (from
  576. <a href="../../../../doc/html/ref.html">Boost.Ref</a>) to the actual elements
  577. in the multi-index container. These objects still do not allow modification
  578. of the referenced entities, but they are swappable,
  579. which is the only requirement <code>std::shuffle</code> imposes. Once
  580. we have our desired rearrange stored in the view, we can transfer it to
  581. the container with
  582. </p>
  583. <blockquote><pre>
  584. <span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>v</span><span class=special>.</span><span class=identifier>begin</span><span class=special>());</span>
  585. </pre></blockquote>
  586. <p>
  587. <code>rearrange</code> accepts an input iterator signaling the beginning
  588. of the external view (and end iterator is not needed since the length of
  589. the view is the same as that of the index) and internally relocates the
  590. elements of the index so that their traversal order matches the view.
  591. Albeit with some circumventions, <code>rearrange</code> allows for the
  592. application of a varied range of algorithms to non key-based indices.
  593. Please note that the view concept is very general, and in no way tied
  594. to the particular implementation example shown above. For instance, indices
  595. of a <code>multi_index_container</code> are indeed views with respect to
  596. its non key-based indices:
  597. </p>
  598. <blockquote><pre>
  599. <span class=comment>// rearrange as index #1 (ascending order)</span>
  600. <span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>get</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;().</span><span class=identifier>begin</span><span class=special>());</span>
  601. <span class=comment>// rearrange in descending order</span>
  602. <span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>get</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;().</span><span class=identifier>rbegin</span><span class=special>());</span>
  603. </pre></blockquote>
  604. <p>
  605. The only important requirement imposed on views is that they must be
  606. <i>free</i>, i.e. they are not affected by relocations on the base index:
  607. thus, <code>rearrange</code> does not accept the following:
  608. </p>
  609. <blockquote><pre>
  610. <span class=comment>// undefined behavior: [rbegin(),rend()) is not free with respect
  611. // to the base index</span>
  612. <span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>rbegin</span><span class=special>());</span>
  613. </pre></blockquote>
  614. <p>
  615. The view concept is defined in detail in the
  616. <a href="../reference/indices.html#views">reference</a>.
  617. See <a href="../examples.html#example11">example 11</a> in the examples section
  618. for a demonstration of use of <code>rearrange</code>.
  619. </p>
  620. <h2><a name="iterator_to"><code>iterator_to</code></a></h2>
  621. <p>
  622. All indices of Boost.MultiIndex provide a member function called <code>iterator_to</code>
  623. which returns an iterator to a given element of the container:
  624. </p>
  625. <blockquote><pre>
  626. <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
  627. <span class=keyword>int</span><span class=special>,</span>
  628. <span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
  629. <span class=special>&gt;</span> <span class=identifier>c</span><span class=special>;</span>
  630. <span class=special>...</span>
  631. <span class=comment>// convoluted way to do c.pop_back()</span>
  632. <span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>iterator_to</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>back</span><span class=special>()));</span>
  633. <span class=comment>// The following, though similar to the previous code,
  634. // does not work: iterator_to accepts a reference to
  635. // the element in the container, not a copy.</span>
  636. <span class=keyword>int</span> <span class=identifier>x</span><span class=special>=</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>back</span><span class=special>();</span>
  637. <span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>iterator_to</span><span class=special>(</span><span class=identifier>x</span><span class=special>));</span> <span class=comment>// run-time failure ensues</span>
  638. </pre></blockquote>
  639. <p>
  640. <code>iterator_to</code> provides a way to retrieve an iterator to an element
  641. from a pointer to the element, thus making iterators and pointers interchangeable
  642. for the purposes of element pointing (not so for traversal) in many situations.
  643. This notwithstanding, it is not the aim of <code>iterator_to</code> to
  644. promote the usage of pointers as substitutes for real iterators: the latter are
  645. specifically designed for handling the elements of a container,
  646. and not only benefit from the iterator orientation of container interfaces,
  647. but are also capable of exposing many more programming bugs than raw pointers, both
  648. at compile and run time. <code>iterator_to</code> is thus meant to be used
  649. in scenarios where access via iterators is not suitable or desireable:
  650. <ul>
  651. <li>Interoperability with preexisting APIs based on pointers or references.</li>
  652. <li>Publication of pointer-based interfaces (for instance, when
  653. designing a C-compatible library).
  654. </li>
  655. <li>The exposure of pointers in place of iterators can act as a <i>type
  656. erasure</i> barrier effectively decoupling the user of the code
  657. from the implementation detail of which particular container is being
  658. used. Similar techniques, like the famous Pimpl idiom, are used
  659. in large projects to reduce dependencies and build times.
  660. </li>
  661. <li>Self-referencing contexts where an element acts upon its owner
  662. container and no iterator to itself is available.
  663. </li>
  664. </ul>
  665. </p>
  666. <h2><a name="ordered_node_compression">Ordered indices node compression</a></h2>
  667. <p>
  668. Ordered and ranked indices are implemented by means of a data structure
  669. known as a <i>red-black tree</i>. Nodes of a red-back tree contain pointers
  670. to the parent and the two children nodes, plus a 1-bit field referred to as
  671. the <i>node color</i> (hence the name of the structure). Due to alignment
  672. issues, on most architectures the color field occupies one entire word, that is,
  673. 4 bytes in 32-bit systems and 8 bytes in 64-bit environments. This waste
  674. of space can be avoided by embedding the color bit inside one of the
  675. node pointers, provided not all the bits of the pointer representation contain
  676. useful information: this is precisely the case in many architectures where
  677. such nodes are aligned to even addresses, which implies that the least
  678. significant bit of the address must always be zero.
  679. </p>
  680. <p>
  681. Boost.MultiIndex ordered and ranked indices implement this type of node compression
  682. whenever applicable. As compared with common implementations of the STL
  683. container <code>std::set</code>, node compression can
  684. result in a reduction of header overload by 25% (from 16 to 12 bytes on
  685. typical 32-bit architectures, and from 32 to 24 bytes on 64-bit systems).
  686. The impact on performance of this optimization has been checked to be negligible
  687. for moderately sized containers, whereas containers with many elements (hundreds
  688. of thousands or more) perform faster with this optimization, most likely due to
  689. L1 and L2 cache effects.
  690. </p>
  691. <p>
  692. Node compression can be disabled by globally setting the macro
  693. <code>BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES</code>.
  694. </p>
  695. <hr>
  696. <div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
  697. Basics
  698. </a></div>
  699. <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
  700. Boost.MultiIndex tutorial
  701. </a></div>
  702. <div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key estraction" border="0"><br>
  703. Key extraction
  704. </a></div><br clear="all" style="clear: all;">
  705. <br>
  706. <p>Revised August 6th 2018</p>
  707. <p>&copy; Copyright 2003-2018 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
  708. Distributed under the Boost Software
  709. License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
  710. LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
  711. http://www.boost.org/LICENSE_1_0.txt</a>)
  712. </p>
  713. </body>
  714. </html>