Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cceb28ac6b | |||
| 2ef40ef45a | |||
| 867a0fb9c9 | |||
| bac508586e | |||
| 1186efb3f0 | |||
| f0c0ae11a8 | |||
| ebb7d18ce6 | |||
| 3e9d0232d2 | |||
| 55723474d2 | |||
| 1bf606a75d | |||
| 7b1bcc810d | |||
| 78a83060f7 | |||
| bf08ab429c | |||
| a739892808 | |||
| 80517e00d7 | |||
| 4223235333 | |||
| 9dfc424d7a | |||
| 270d048f12 | |||
| 604128d17a | |||
| 4c3b315b0b | |||
| 6b58056716 | |||
| 7d1417fe8c | |||
| 12ba0771e8 | |||
| fd2b4ede68 | |||
| 5e50c69465 | |||
| 86059ad43f | |||
| b14efa6fbf | |||
| 9c8c001d5d | |||
| 06b509b35c | |||
| 45adb9c08a | |||
| 436ea292c6 | |||
| a5210bff85 | |||
| 1eebcfcf5f | |||
| 8290474391 | |||
| c80e451d22 | |||
| 90bc0b7662 | |||
| 5d016b4003 | |||
| 11f09a3558 | |||
| 03ebcdd0f4 | |||
| 62911d5198 | |||
| 05e70771fd | |||
| 6b5f74732b | |||
| a404be8a6b | |||
| 47b98dd304 | |||
| d881480b52 | |||
| 15accb2836 | |||
| 78f6bf5446 | |||
| aebc21ee44 | |||
| ff403f0a62 | |||
| efd8ea14ef | |||
| 58fd64b622 | |||
| f83aa3c780 | |||
| 26ce890ff8 | |||
| c4a9b8f8e6 | |||
| 3a4ac5c0a4 | |||
| ae87c1d454 | |||
| 40634a5f23 | |||
| 16778f3ff3 | |||
| 47b172ab68 | |||
| d6932847ec | |||
| 88a418d563 | |||
| 16325e6039 | |||
| 7be686f18e | |||
| 8bdf62586f | |||
| 6fa0f070b9 | |||
| 1130b76e4b | |||
| 2e22bed967 | |||
| 88f3a9ca8b | |||
| 8e573eba2c | |||
| 2e361f8b6a | |||
| 259f87b550 | |||
| bbeb058580 | |||
| 5cd33a9a81 | |||
| 252398ac13 | |||
| 64b5247bea | |||
| bcec2c0467 | |||
| c6e0231bed | |||
| c757629a6d | |||
| 14d94f24fa | |||
| 18c8724a46 | |||
| 5f0ac92335 | |||
| c8e707ddd7 | |||
| f7d22b4de3 | |||
| c16d49acd0 | |||
| 28192c181a | |||
| 444ebbe95b | |||
| 5ecebcbc78 | |||
| 9a782276a4 | |||
| f86dce9db1 | |||
| 2448ba2a95 | |||
| 8ecbfdf080 | |||
| f9c9851ef3 | |||
| 708f8bd4ab | |||
| c21722cd10 | |||
| db3889ceff | |||
| 3be7ae350e | |||
| 2a6813f2e7 | |||
| 842bc1ba70 | |||
| a1944a19a2 | |||
| c2d7a65cfd | |||
| cf84a0dc1c | |||
| 5fec019715 | |||
| c7bfd7cf83 | |||
| 1235106ac0 | |||
| 5e790014c1 | |||
| a9c89540ac | |||
| 1fc02c6b1d | |||
| f54edbf0d3 | |||
| 7274eca56c | |||
| e953c2b4ff | |||
| cf076474d2 | |||
| 4c7a97e890 | |||
| 10fe2cd1ab | |||
| b81ee48320 | |||
| e043cadb7c | |||
| 233fd40984 | |||
| 67c04d598f | |||
| f1dde3d84e | |||
| f8eb1b16ce | |||
| 119d6d4a1c | |||
| 8682a33fcb | |||
| 34da3c9fd5 | |||
| 0bacd6fbed | |||
| 98d4cea748 | |||
| a872178185 | |||
| 027b5105ac | |||
| d18e3fd6a5 | |||
| ae533e1b16 | |||
| 4f6d05b115 | |||
| 1e39e5f9af | |||
| c1f8fc6348 | |||
| f1dcc889ec | |||
| 1669a1fb2d | |||
| 5fd646dc67 | |||
| ac2a6d72a3 | |||
| 8d3cfd51a8 | |||
| 35a151c9b0 | |||
| aa0ef9b10c | |||
| cc3da5b51c | |||
| 83a1b490ea | |||
| 12b9ac21c4 | |||
| 5190a31109 | |||
| 192d43569b | |||
| aa5cfdfb3c | |||
| 519d96871f | |||
| 9c61f94492 | |||
| dd5a6bd9a4 | |||
| 37ca90b823 | |||
| 964d83df51 | |||
| b16c15342a | |||
| e636c5ec72 | |||
| 1654aaa24e | |||
| 4797a93e7b | |||
| 41d3f814ba | |||
| 5aa6cc3b03 | |||
| 2cdc3c3778 | |||
| f30144473d | |||
| 7a6121fbbf | |||
| 538977752f | |||
| 2d346be3fb | |||
| 405e8b2a53 | |||
| 9ca897dae2 | |||
| 683ab3be1d | |||
| aa4edd99cf | |||
| a87b1eea96 | |||
| 3c1395a626 | |||
| 80812e471a | |||
| edd622e5ac | |||
| 4db9b44b75 | |||
| c6a1c3dd92 | |||
| 7aacfe029e | |||
| 1361bfe530 | |||
| b92f05140b | |||
| 95d44a6109 | |||
| c7f63a348f | |||
| f1ad358bff | |||
| cfa63b8a4c | |||
| 41be013bc6 | |||
| 1e00c5139b | |||
| b3de839dee | |||
| 18234ebeee | |||
| 92207dde6a | |||
| 7343ddf980 | |||
| 434680c817 | |||
| b28164d7f8 |
@@ -1,16 +0,0 @@
|
||||
# Boost.MultiIndex examples and tests Jamfile
|
||||
#
|
||||
# Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# See http://www.boost.org/libs/multi_index for library home page.
|
||||
|
||||
subproject libs/multi_index ;
|
||||
|
||||
# please order by name to ease maintenance
|
||||
|
||||
subinclude libs/multi_index/example ;
|
||||
subinclude libs/multi_index/test ;
|
||||
subinclude libs/multi_index/perf ;
|
||||
@@ -5,6 +5,9 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Acknowledgements</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<link rel="start" href="index.html">
|
||||
<link rel="prev" href="release_notes.html">
|
||||
<link rel="up" href="index.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -94,7 +97,7 @@ purpose. It is provided "as is" without express or implied warranty.
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
<span style="float:right;"><img src="lopez.jpg" width="160" height="120"></span>
|
||||
<span style="float:right;margin-left:10px"><img src="lopez.jpg" width="160" height="120"></span>
|
||||
I would like to dedicate this piece of work to Rosa Bernárdez, my very first
|
||||
C++ teacher, for her unconditional support in many endeavors of which programming is
|
||||
by no means the most important. In memory of my cat López (2001-2003): he
|
||||
@@ -118,6 +121,57 @@ capabilities are built. Toon Knapen helped adjust the library for VisualAge 6.0.
|
||||
Markus Schöpflin provided a Jamfile tweak for GCC under Tru64 UNIX.
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_34">Boost 1.34 release</a></h2>
|
||||
|
||||
<p>
|
||||
<span style="float:left;margin-right:10px"><img src="hector.jpg" width="150" height="198"></span>
|
||||
Thanks go to Pavel Voženílek for his useful comments and suggestions
|
||||
during the development of this release, and to Rosa Bernárdez for reviewing
|
||||
the new material in the documentation.
|
||||
Alo Sarv suggested a notational improvement in the specification of
|
||||
partial searches with composite keys.
|
||||
Maxim Yegorushkin proposed a valuable
|
||||
<a href="tutorial/indices.html#ordered_node_compression">spatial optimization</a>
|
||||
for ordered indices and provided figures of its impact on performance
|
||||
for containers with large numbers of elements.
|
||||
Caleb Epstein performed the tests under MSVC++ 8.0 described in the
|
||||
performance section. The following people have reported bugs and problems with
|
||||
previous versions and prereleases of the library: Alexei Alexandrov,
|
||||
Matías Capeletto, John Eddy, Martin Eigel, Guillaume Lazzara,
|
||||
Felipe Magno de Almeida, Julien Pervillé, Hubert Schmid, Toby Smith.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
New member in the family! Thanks to Héctor for his patience during
|
||||
long development sessions and his occasional contributions to the source
|
||||
codebase.
|
||||
<br style="clear:all;">
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_35">Boost 1.35 release</a></h2>
|
||||
|
||||
<p>
|
||||
<a href="tutorial/key_extraction.html#global_fun"><code>global_fun</code></a>
|
||||
was included after a proposal by Markus Werle. Bruno Martínez Aguerre
|
||||
suggested the inclusion of
|
||||
<a href="tutorial/indices.html#iterator_to"><code>iterator_to</code></a>. The
|
||||
rollback versions of <code>modify</code> and <code>modify_key</code> arose
|
||||
from discussions with Matías Capeletto. Steven Watanabe spotted an
|
||||
include guard bug present from the first release of the library.
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_36">Boost 1.36 release</a></h2>
|
||||
|
||||
<p>
|
||||
Thanks to Amit Jain for reporting a problem with allocator management.
|
||||
Michael Fawcett proposed the addition of an allocator constructor to
|
||||
<code>multi_index_container</code>.
|
||||
A report from Zachary Zhou has led to
|
||||
<a href="release_notes.html#stable_update">enhancing the behavior of
|
||||
hashed indices update functions</a> so that they meet some intuitive expectations.
|
||||
Grzegorz Jakacki spotted some internal dead code.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
|
||||
@@ -131,9 +185,9 @@ Index
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised July 11th 2005</p>
|
||||
<p>Revised June 25th 2008</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2008 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Compiler specifics</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<link rel="start" href="index.html">
|
||||
<link rel="prev" href="reference/key_extraction.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="performance.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -32,9 +36,9 @@ along with suitable workarounds when available.
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#bcb_64">Borland C++ Builder 6.4</a></li>
|
||||
<li><a href="#comeau_433_win_vc7_71">Comeau C/C++ 4.3.3 for Windows (VC++ 7.0/7.1 backend)</a></li>
|
||||
<li><a href="#compaq_65">Compaq C++ 6.5-042 for Tru64 UNIX</a></li>
|
||||
<li><a href="#bcb_64">Borland C++ Builder 6.4 and later</a></li>
|
||||
<li><a href="#comeau_43101_win_vc7_71">Comeau C/C++ 4.3.10.1 for Windows (VC++ 9.0 backend)</a></li>
|
||||
<li><a href="#compaq_65">Compaq C++ 6.5-042 and later for Tru64 UNIX</a></li>
|
||||
<li>
|
||||
<a href="#gcc_32">GNU GCC 3.2 and later</a>
|
||||
<ul>
|
||||
@@ -42,19 +46,31 @@ along with suitable workarounds when available.
|
||||
<li><a href="#gcc_4_darwin">Darwin GCC 4.0</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#acc_60">HP aC++ A.06.00 for HP-UX</a></li>
|
||||
<li><a href="#acc_612_ia64">HP aC++ A.06.12 and later for HP-UX IA64</a></li>
|
||||
<li><a href="#acc_380_pa_risc">HP aC++ A.03.80 for HP-UX PA-RISC</a></li>
|
||||
<li><a href="#va_60">IBM VisualAge C++ V6.0 for AIX</a></li>
|
||||
<li><a href="#intel_71_8x_lin">Intel C++ Compiler for Linux 7.1/8.0/8.1</a></li>
|
||||
<li><a href="#intel_em64t_81_lin">Intel C++ Compiler Extended Memory 64 Technology 8.1 for Linux</a></li>
|
||||
<li><a href="#intel_7x_win">Intel C++ Compiler for Windows 32-bit 7.0/7.1</a></li>
|
||||
<li><a href="#intel_71_win_stlport_453">Intel C++ Compiler for Windows 32-bit 7.1 + STLport 4.5.3</a></li>
|
||||
<li><a href="#intel_8x_9x_win">Intel C++ Compiler for Windows 32-bit 8.0/8.1/9.0</a></li>
|
||||
<li><a href="#cw_83_9x">Metrowerks CodeWarrior 8.3 and later</a></li>
|
||||
<li><a href="#msvc_60">Microsoft Visual C++ 6.0 Service Pack 5</a></li>
|
||||
<li><a href="#msvc_60_stlport_453">Microsoft Visual C++ 6.0 Service Pack 5 + STLport 4.5.3</a></li>
|
||||
<li><a href="#msvc_70">Microsoft Visual C++ 7.0</a></li>
|
||||
<li><a href="#xl_90">IBM XL C/C++ V9.0 for AIX and later</a></li>
|
||||
<li><a href="#intel_81_lin">Intel C++ Compiler for Linux 8.1 and later</a></li>
|
||||
<li><a href="#intel_91_mac">Intel C++ Compiler for Mac OS 9.1 and later</a></li>
|
||||
<li><a href="#intel_80_win">Intel C++ Compiler for Windows 32-bit 8.0 and later</a></li>
|
||||
<li><a href="#intel_100_win64">Intel C++ Compiler for Windows 64-bit 10.0 and later</a></li>
|
||||
<li><a href="#cw_83">Metrowerks CodeWarrior 8.3</a></li>
|
||||
<li><a href="#cw_9x">Metrowerks CodeWarrior 9 and later</a></li>
|
||||
<li>
|
||||
<a href="#msvc_60">Microsoft Visual C++ 6.0 Service Pack 5</a>
|
||||
<ul>
|
||||
<li><a href="#msvc_60_stlport_453">Microsoft Visual C++ 6.0 Service Pack 5 + STLport 4.5.3 and later</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#msvc_70">Microsoft Visual C++ 7.0</a>
|
||||
<ul>
|
||||
<li><a href="#msvc_70_stlport_501">Microsoft Visual C++ 7.0 + STLport 5.0.1</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#msvc_71">Microsoft Visual C++ 7.1</a></li>
|
||||
<li><a href="#msvc_80">Microsoft Visual C++ 8.0</a></li>
|
||||
<li><a href="#msvc_80">Microsoft Visual C++ 8.0 and later</a></li>
|
||||
<li><a href="#sun_10">Sun Studio 10 and later for Solaris</a></li>
|
||||
<li><a href="#portability">Portability techniques</a>
|
||||
<ul>
|
||||
<li><a href="#member_offset">Use of <code>member_offset</code></a></li>
|
||||
@@ -72,26 +88,36 @@ along with suitable workarounds when available.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="bcb_64">Borland C++ Builder 6.4</a></h2>
|
||||
<h2><a name="bcb_64">Borland C++ Builder 6.4 and later</a></h2>
|
||||
|
||||
<p>
|
||||
Currently, Boost.MultiIndex cannot be used with BCB 6.4. The
|
||||
number of problems encountered during the tests makes it unlikely that
|
||||
future versions of the library can be made to work under
|
||||
this compiler.
|
||||
Currently, Boost.MultiIndex cannot be used with any of BCB 6.4 up to BCB 2006
|
||||
and CodeGear C++Builder 2010.
|
||||
The number of problems encountered during the tests makes it unlikely that
|
||||
future versions of the library can be made to work under these compilers.
|
||||
</p>
|
||||
|
||||
<h2><a name="comeau_433_win_vc7_71">Comeau C/C++ 4.3.3 for Windows (VC++ 7.0/7.1 backend)</a></h2>
|
||||
<h2><a name="comeau_43101_win_vc7_71">Comeau C/C++ 4.3.10.1 for Windows (VC++ 9.0 backend)</a></h2>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.38. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this compiler. The library fails to compile,
|
||||
however, when Microsoft Visual C++ 6.0 is used as the backend.
|
||||
however, when Microsoft Visual C++ 6.0 is used as the backend. Last time they were
|
||||
tested (Boost.1.34.1), VC++ 7.0/7.1 backends worked correctly. The beta 2 version of
|
||||
the Comeau compiler 4.3.10.1 has been used.
|
||||
</p>
|
||||
|
||||
<h2><a name="compaq_65">Compaq C++ 6.5-042 for Tru64 UNIX</a></h2>
|
||||
<h2><a name="compaq_65">Compaq C++ 6.5-042 and later for Tru64 UNIX</a></h2>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this compiler.
|
||||
<b>Note:</b> Last tested in Boost 1.38. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this compiler. Last tested for version 7.1-006.
|
||||
</p>
|
||||
|
||||
<h2><a name="gcc_32">GNU GCC 3.2 and later</a></h2>
|
||||
@@ -99,22 +125,18 @@ No problems have been detected with this compiler.
|
||||
<p>
|
||||
No problems have been detected with several versions of this compiler
|
||||
starting from 3.2. The following versions have been explicitly tested:
|
||||
<ul>
|
||||
<li>GCC 3.2 20020903 under Linux,</li>
|
||||
<li>GCC 3.2 20020927 (prerelease) under Cygwin 1.5.7,</li>
|
||||
<li>GCC 3.2.3 under Linux, (mingw special 20030504-1) under Win32,</li>
|
||||
<li>GCC 3.3 20030304 (Apple builds 1666 and 1671) under Mac OS,</li>
|
||||
<li>GCC 3.3.3 (cygwin special) under Cygwin 1.5.7,</li>
|
||||
<li>GCC 3.3.5 under Linux,</li>
|
||||
<li>GCC 3.3.6 under Linux and Tru64 (see <a href="#gcc_tru64">below</a>),</li>
|
||||
<li>GCC 3.4.2 (mingw-special) under Win32,</li>
|
||||
<li>GCC 3.4.3 under Linux, Solaris and Tru64 (see <a href="#gcc_tru64">below</a>),</li>
|
||||
<li>GCC 3.4.4 (cygming special) under Cygwin, under Linux,
|
||||
under Tru64 (see <a href="#gcc_tru64">below</a>), (mingw special) under Win32,</li>
|
||||
<li>GCC 4.0.0 20041026 (Apple build 4061) under Mac OS
|
||||
(see <a href="#gcc_4_darwin">below</a>),</li>
|
||||
<li>GCC 4.0.0 under Linux, (Apple build 5026) under Mac OS,</li>
|
||||
<li>GCC 4.0.1 under Linux.</li>
|
||||
<ul>
|
||||
<li>GCC 3.4.3 under Linux x86-64,</li>
|
||||
<li>GCC 4.0.1 (Apple Computer, Inc. build 5370), (Apple Inc. build 5490), (Apple Inc. build 5493) under Mac OS,</li>
|
||||
<li>GCC 4.1.2 20080704 (Red Hat 4.1.2-44) under Linux x86-64,</li>
|
||||
<li>GCC 4.2.1 20070719 [FreeBSD] under FreeBSD,</li>
|
||||
<li>GCC 4.2.4 under Linux x86-64,</li>
|
||||
<li>GCC 4.3.2 under Linux x86-64,</li>
|
||||
<li>GCC 4.3.3 under Linux x86-64,</li>
|
||||
<li>GCC 4.3.3 gnu++0x under Linux x86-64,</li>
|
||||
<li>GCC 4.3.4 under Linux x86-64,</li>
|
||||
<li>GCC 4.4.1 under Linux, Linux x86-64 and MinGW,</li>
|
||||
<li>GCC 4.4.1 gnu++0x under Linux x86-64 and MinGW.</li>
|
||||
</ul>
|
||||
Boost.MultiIndex does not work with versions 3.1 and prior of GCC.
|
||||
</p>
|
||||
@@ -140,21 +162,43 @@ prior), corresponds to a prerelease version of GNU GCC 4.0.0 which introduces
|
||||
a <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17435">regression bug</a>
|
||||
related to binding of references to temporary objects. This bug precludes the
|
||||
usage of Boost.MultiIndex
|
||||
<a href="advanced_topics.html#invariant_check">invariant-checking mode</a>; other
|
||||
<a href="tutorial/debug.html#invariant_check">invariant-checking mode</a>; other
|
||||
than this, Boost.MultiIndex works correctly.
|
||||
The bug is corrected in GCC 4.0 Apple build 5026, which is in sync with the official
|
||||
release of GNU GCC 4.0.0, so the invariant-checking mode is available from this
|
||||
upgrade.
|
||||
</p>
|
||||
|
||||
<h2><a name="acc_60">HP aC++ A.06.00 for HP-UX</a></h2>
|
||||
<h2><a name="acc_612_ia64">HP aC++ A.06.12 and later for HP-UX IA64</a></h2>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.38. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this compiler.
|
||||
Last tested for version A.06.17.
|
||||
</p>
|
||||
|
||||
<h2><a name="acc_380_pa_risc">HP aC++ A.03.80 for HP-UX PA-RISC</a></h2>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.38. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this compiler.
|
||||
Last tested for version A.03.85.
|
||||
</p>
|
||||
|
||||
<h2><a name="va_60">IBM VisualAge C++ V6.0 for AIX</a></h2>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.33.1. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
|
||||
refer to the section on
|
||||
@@ -181,47 +225,44 @@ Serialization capabilities are not available as Boost.Serialization is not
|
||||
supported on this platform.
|
||||
</p>
|
||||
|
||||
<h2><a name="intel_71_8x_lin">Intel C++ Compiler for Linux 7.1/8.0/8.1</a></h2>
|
||||
|
||||
<p>
|
||||
No problems have been detected with these compilers.
|
||||
</p>
|
||||
|
||||
<h2><a name="intel_em64t_81_lin">Intel C++ Compiler Extended Memory 64 Technology 8.1
|
||||
for Linux</a></h2>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this compiler.
|
||||
</p>
|
||||
|
||||
<h2><a name="intel_7x_win">Intel C++ Compiler for Windows 32-bit 7.0/7.1</a></h2>
|
||||
<h2><a name="xl_90">IBM XL C/C++ V9.0 for AIX and later</a></h2>
|
||||
|
||||
<p>
|
||||
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
|
||||
refer to the section on
|
||||
<a href="#member_offset">use of <code>member_offset</code></a> for workarounds.
|
||||
<code>member_offset</code> causes the compiler to emit warnings about the
|
||||
use of <code>offsetof</code> with non-POD types: these warnings can be suppressed
|
||||
by setting the compiler option <code>-qsuppress=1540-1281</code>, or, alternatively,
|
||||
by inserting the following preprocessor directive:
|
||||
</p>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#pragma</span> <span class=identifier>info</span><span class=special>(</span><span class=identifier>nolan</span><span class=special>)</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
When used on top of MSVC++ 7.0 or prior, argument dependent lookup is
|
||||
disabled by default. This will cause problems with many Boost libraries,
|
||||
and in particular with the serialization part of Boost.MultiIndex.
|
||||
Argument dependent lookup is enabled by adding
|
||||
<code>/Qoption,c,--arg_dep_lookup</code> to the project options.
|
||||
This latter pragma, however, may also eliminate other warnings not related
|
||||
to the use of <code>offsetof</code>.
|
||||
Other than this, Boost.MultiIndex works without problems.
|
||||
Last tested for version V10.1.
|
||||
</p>
|
||||
|
||||
<h2><a name="#intel_71_win_stlport_453">
|
||||
Intel C++ Compiler for Windows 32-bit 7.1 + STLport 4.5.3</a></h2>
|
||||
<h2><a name="intel_81_lin">Intel C++ Compiler for Linux 8.1 and later</a></h2>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex works for this configuration. The same limitations apply as
|
||||
in Intel C++ 7.1 with its original Dinkumware standard library. STLport 4.6.2 has
|
||||
also been confirmed to work correctly.
|
||||
No problems have been detected with this compiler.
|
||||
Last tested for compiler versions 10.0 to 11.1.
|
||||
</p>
|
||||
|
||||
<h2><a name="intel_8x_9x_win">Intel C++ Compiler for Windows 32-bit 8.0/8.1/9.0</a></h2>
|
||||
<h2><a name="intel_91_mac">Intel C++ Compiler for Mac OS 9.1 and later</a></h2>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this compiler.
|
||||
Tested from version 10.1 to 11.0.
|
||||
</p>
|
||||
|
||||
<h2><a name="intel_80_win">Intel C++ Compiler for Windows 32-bit 8.0 and later</a></h2>
|
||||
|
||||
<p>
|
||||
When used on top of MSVC++ 7.0 or prior, argument dependent lookup is
|
||||
@@ -230,17 +271,70 @@ and in particular with the serialization part of Boost.MultiIndex.
|
||||
Argument dependent lookup is enabled by adding
|
||||
<code>/Qoption,c,--arg_dep_lookup</code> to the project options.
|
||||
Other than this, Boost.MultiIndex works without problems.
|
||||
Last tested for compiler version 11.1.
|
||||
</p>
|
||||
|
||||
<h2><a name="cw_83_9x">Metrowerks CodeWarrior 8.3 and later</a></h2>
|
||||
<h2><a name="intel_100_win64">Intel C++ Compiler for Windows 64-bit 10.0 and later</a></h2>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex works correctly with versions of this compiler from 8.3 to
|
||||
9.5, under the two operating systems tested: Mac OS and Windows.
|
||||
No problems have been detected with this compiler.
|
||||
Last tested for compiler version 11.1.
|
||||
</p>
|
||||
|
||||
<h2><a name="cw_83">Metrowerks CodeWarrior 8.3</a></h2>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.36. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Predefined key extractors instantiated on a given type do not accept
|
||||
objects of derived types. For instance:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>struct</span> <span class=identifier>base</span><span class=special>{};</span>
|
||||
<span class=keyword>struct</span> <span class=identifier>derived</span><span class=special>:</span><span class=keyword>public</span> <span class=identifier>base</span><span class=special>{};</span>
|
||||
<span class=special>...</span>
|
||||
|
||||
<span class=identifier>identity</span><span class=special><</span><span class=identifier>base</span><span class=special>></span> <span class=identifier>key_extractor</span><span class=special>;</span>
|
||||
<span class=identifier>derived</span> <span class=identifier>x</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// not accepted by this compiler: an explicit cast to base is required</span>
|
||||
<span class=identifier>key_extractor</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Other than this, Boost.MultiIndex works without problems under Mac OS and Windows (last
|
||||
tested under Windows only).
|
||||
</p>
|
||||
|
||||
<h2><a name="cw_9x">Metrowerks CodeWarrior 9 and later</a></h2>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.34.1. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex works correctly with versions of this compiler from 9.0 to
|
||||
9.5, both under Mac OS and Windows.
|
||||
</p>
|
||||
|
||||
<h2><a name="msvc_60">Microsoft Visual C++ 6.0 Service Pack 5</a></h2>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.36. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
Beginning with Boost.1.36, Boost.Serialization is no longer supported in this
|
||||
compiler, thus the serialization capabilities cannot be used.
|
||||
</p>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
|
||||
refer to the section on
|
||||
@@ -313,6 +407,37 @@ in compilers without partial template specialization"</a>.
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
Due to problems with function template ordering support,
|
||||
<a href="reference/key_extraction.html#composite_key_compare"><code>composite_key_compare</code></a>
|
||||
and related classes do not accept the notational variations of
|
||||
<code>operator()</code> where one of the operands is treated as if
|
||||
included into a tuple of length 1. As a result, the user cannot ever
|
||||
omit tuple enclosing when specifying the arguments of lookup operations
|
||||
involving composite keys.
|
||||
</p>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
Predefined key extractors instantiated on a given type do not accept
|
||||
objects of derived types. For instance:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>struct</span> <span class=identifier>base</span><span class=special>{};</span>
|
||||
<span class=keyword>struct</span> <span class=identifier>derived</span><span class=special>:</span><span class=keyword>public</span> <span class=identifier>base</span><span class=special>{};</span>
|
||||
<span class=special>...</span>
|
||||
|
||||
<span class=identifier>identity</span><span class=special><</span><span class=identifier>base</span><span class=special>></span> <span class=identifier>key_extractor</span><span class=special>;</span>
|
||||
<span class=identifier>derived</span> <span class=identifier>x</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// not accepted by this compiler: an explicit cast to base is required</span>
|
||||
<span class=identifier>key_extractor</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
MSVC++ 6.0 presents serious limitations for the maximum length of
|
||||
symbol names generated by the compiler, which might result in the
|
||||
@@ -336,7 +461,7 @@ This problem is a recurrent bug of the compiler, and has been reported in
|
||||
other unrelated libraries, like the
|
||||
<a href="../../../libs/graph/doc/table_of_contents.html">Boost Graph Library</a>,
|
||||
<a href="../../../libs/multi_array/doc/index.html">Boost.MultiArray</a>,
|
||||
<a href="../../../libs/regex/doc/index.html">Boost.Regex</a>,
|
||||
<a href="../../../libs/regex/index.html">Boost.Regex</a>,
|
||||
<a href="http://www.cgal.org/">CGAL</a> and
|
||||
<a href="http://www.mysql.com/downloads/api-mysql++.html">MySQL++</a>.
|
||||
The error is triggered, though not in a systematic manner, by the use
|
||||
@@ -361,7 +486,7 @@ with equivalent operations:
|
||||
<p>
|
||||
The second workaround has not been confirmed by the author, but it is given
|
||||
on the Internet in connection with this error appearing in other libraries.
|
||||
Replace line 84 of <code><xlocnum></code>
|
||||
Replace line 84 of <code><xlocnum></code>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#define</span> <span class=identifier>_VIRTUAL</span> <span class=keyword>virtual</span>
|
||||
@@ -405,27 +530,35 @@ The following measures can help alleviate these problems:
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<h3>
|
||||
<a name="msvc_60_stlport_453">Microsoft Visual C++ 6.0 Service Pack 5
|
||||
+ STLport 4.5.3</a>
|
||||
</h2>
|
||||
+ STLport 4.5.3 and later</a>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.36. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex works for this configuration. The same limitations apply as
|
||||
in MSVC++ 6.0 with its original Dinkumware standard library. STLport 4.6.2 has
|
||||
also been confirmed to work correctly.
|
||||
in MSVC++ 6.0 with its original Dinkumware standard library. STLport 4.6.2 and
|
||||
5.0.1 has also been confirmed to work correctly.
|
||||
</p>
|
||||
|
||||
<h2><a name="msvc_70">Microsoft Visual C++ 7.0</a></h2>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.35. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
It is not possible to use the serialization capabilities of Boost.MultiIndex
|
||||
along with the dynamic version of STLport, as some linking errors result.
|
||||
Use instead the static version of STLport. This bug is reportedly fixed in
|
||||
STLport 5.0 (in beta stage as of this writing.)
|
||||
Beginning with Boost.1.36, Boost.Serialization is no longer supported in this
|
||||
compiler, thus the serialization capabilities cannot be used.
|
||||
</p>
|
||||
|
||||
<h2><a name="msvc_70">Microsoft Visual C++ 7.0</a></h2>
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
|
||||
@@ -489,23 +622,74 @@ can be remedied as explained in
|
||||
in compilers without partial template specialization"</a>.
|
||||
</p>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
Due to problems with function template ordering support,
|
||||
<a href="reference/key_extraction.html#composite_key_compare"><code>composite_key_compare</code></a>
|
||||
and related classes do not accept the notational variations of
|
||||
<code>operator()</code> where one of the operands is treated as if
|
||||
included into a tuple of length 1. As a result, the user cannot ever
|
||||
omit tuple enclosing when specifying the arguments of lookup operations
|
||||
involving composite keys.
|
||||
</p>
|
||||
|
||||
<blockquote><hr></blockquote>
|
||||
|
||||
<p>
|
||||
Predefined key extractors instantiated on a given type do not accept
|
||||
objects of derived types. For instance:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>struct</span> <span class=identifier>base</span><span class=special>{};</span>
|
||||
<span class=keyword>struct</span> <span class=identifier>derived</span><span class=special>:</span><span class=keyword>public</span> <span class=identifier>base</span><span class=special>{};</span>
|
||||
<span class=special>...</span>
|
||||
|
||||
<span class=identifier>identity</span><span class=special><</span><span class=identifier>base</span><span class=special>></span> <span class=identifier>key_extractor</span><span class=special>;</span>
|
||||
<span class=identifier>derived</span> <span class=identifier>x</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// not accepted by this compiler: an explicit cast to base is required</span>
|
||||
<span class=identifier>key_extractor</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h3><a name="msvc_70_stlport_501">Microsoft Visual C++ 7.0 + STLport 5.0.1</a></h3>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Last tested in Boost 1.35. The information might be no longer accurate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex works for this configuration. The same issues apply as in
|
||||
MSVC++ 7.0 with its original Dinkumware standard library.
|
||||
</p>
|
||||
|
||||
<h2><a name="msvc_71">Microsoft Visual C++ 7.1</a></h2>
|
||||
|
||||
<p>
|
||||
Problems have been reported when compiling the library with the <code>/Gm</code>
|
||||
option (Enable Minimal Rebuild.) Seemingly, this is due to an
|
||||
internal defect of the compiler (see for instance
|
||||
<a href="http://lists.boost.org/MailArchives/boost-users/msg05988.php">
|
||||
<a href="http://lists.boost.org/boost-users/2004/02/5987.php">
|
||||
this mention of a similar issue</a> in the Boost Users mailing list.)
|
||||
If <code>/Gm</code> is turned off, Boost.MultiIndex compiles and runs
|
||||
without further problems.
|
||||
</p>
|
||||
|
||||
<h2><a name="msvc_80">Microsoft Visual C++ 8.0</a></h2>
|
||||
<h2><a name="msvc_80">Microsoft Visual C++ 8.0 and later</a></h2>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this compiler. The Beta 2 version of
|
||||
this product was used for the testing.
|
||||
No problems have been detected with this compiler, both in 32-bit and 64-bit modes.
|
||||
Last tested for compiler versions 8.0 to 10.0.
|
||||
</p>
|
||||
|
||||
<h2><a name="sun_10">Sun Studio 10 and later for Solaris</a></h2>
|
||||
|
||||
<p>
|
||||
No problems have been detected with this platform. Last tested for compiler version
|
||||
Sun C++ 5.10 (Sun Studio 12 Update 1).
|
||||
The option <code>-library=stlport4</code> was used to replace the default
|
||||
standard library with STLport.
|
||||
</p>
|
||||
|
||||
<h2><a name="portability">Portability techniques</a></h2>
|
||||
@@ -523,7 +707,7 @@ to work correctly with <code>member</code>:
|
||||
<ul>
|
||||
<li>MSVC++ 6.0/7.0,</li>
|
||||
<li>Intel C++ 7.0/7.1 for Windows,</li>
|
||||
<li>VisualAge 6.0 for AIX.</li>
|
||||
<li>VisualAge 6.0/9.0 for AIX.</li>
|
||||
</ul>
|
||||
This program can help determine if your compiler
|
||||
properly supports pointers to members as non-type template parameters:
|
||||
@@ -819,7 +1003,7 @@ Consider a typical instantiation of <code>multi_index_container</code>:
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Then, for instance, the type <code>employee_set::nth_type<0>::type</code>
|
||||
Then, for instance, the type <code>employee_set::nth_index<0>::type</code>
|
||||
resolves to the following in GCC:
|
||||
</p>
|
||||
|
||||
@@ -882,7 +1066,7 @@ in the final type by encapsulating it into another, shorter-named construct:
|
||||
<code>employee_set_indices</code> works as a conventional <code>typedef</code>
|
||||
in all respects, save for a detail: its name does not explicitly
|
||||
include the information contained in the <code>indexed_by</code> instantiation.
|
||||
Applying this technique, <code>employee_set::nth_type<0>::type</code>
|
||||
Applying this technique, <code>employee_set::nth_index<0>::type</code>
|
||||
now becomes:
|
||||
</p>
|
||||
|
||||
@@ -928,9 +1112,9 @@ Performance
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised July 26th 2005</p>
|
||||
<p>Revised October 14th 2009</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2009 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Examples</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<link rel="start" href="index.html">
|
||||
<link rel="prev" href="performance.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="tests.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -27,7 +31,7 @@ Tests
|
||||
|
||||
<ul>
|
||||
<li><a href="#example1">Example 1: basic usage</a></li>
|
||||
<li><a href="#example2">Example 2: using member functions as keys</a></li>
|
||||
<li><a href="#example2">Example 2: using functions as keys</a></li>
|
||||
<li><a href="#example3">Example 3: constructing <code>multi_index_container</code>s
|
||||
with <code>ctor_args_list</code></a></li>
|
||||
<li><a href="#example4">Example 4: bidirectional map</a></li>
|
||||
@@ -36,6 +40,9 @@ Tests
|
||||
<li><a href="#example7">Example 7: composite keys</a></li>
|
||||
<li><a href="#example8">Example 8: hashed indices</a></li>
|
||||
<li><a href="#example9">Example 9: serialization and MRU lists</a></li>
|
||||
<li><a href="#example10">Example 10: random access indices</a></li>
|
||||
<li><a href="#example11">Example 11: index rearrangement</a></li>
|
||||
<li><a href="#example12">Example 12: using Boost.Interprocess allocators</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="example1">Example 1: basic usage</a></h2>
|
||||
@@ -49,23 +56,23 @@ Basic program showing the multi-indexing capabilities of Boost.MultiIndex
|
||||
with an admittedly boring set of <code>employee</code> records.
|
||||
</p>
|
||||
|
||||
<h2><a name="example2">Example 2: using member functions as keys</a></h2>
|
||||
<h2><a name="example2">Example 2: using functions as keys</a></h2>
|
||||
|
||||
<p>
|
||||
See <a href="../example/memfun_key.cpp">source code</a>.
|
||||
See <a href="../example/fun_key.cpp">source code</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Usually keys assigned to an index are based on a member variable of the
|
||||
element, but key extractors can be defined which take their value from
|
||||
a member function. This has some similarity with the concept of
|
||||
a member function or a global function. This has some similarity with the concept of
|
||||
<i>calculated keys</i> supported by some relational database engines.
|
||||
The example shows how to use the predefined <code>const_mem_fun</code>
|
||||
key extractor to deal with this situation.
|
||||
and <code>global_fun</code> key extractors to deal with this situation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Keys based on member functions usually will not be actual references,
|
||||
Keys based on functions usually will not be actual references,
|
||||
but rather the temporary values resulting from the invocation of the
|
||||
member function used. This implies that <code>modify_key</code> cannot be
|
||||
applied to this type of extractors, which is a perfectly logical
|
||||
@@ -82,7 +89,7 @@ See <a href="../example/non_default_ctor.cpp">source code</a>.
|
||||
<p>
|
||||
We show a practical example of usage of <code>multi_index_container::ctor_arg_list</code>,
|
||||
whose definition and purpose are explained in the
|
||||
<a href="advanced_topics.html#ctor_args_list">Advanced topics section</a>. The
|
||||
<a href="tutorial/creation.html#ctor_args_list">tutorial</a>. The
|
||||
program groups a sorted collection of numbers based on identification through
|
||||
modulo arithmetics, by which <code>x</code> and <code>y</code> are equivalent
|
||||
if <code>(x%n)==(y%n)</code>, for some fixed <code>n</code>.
|
||||
@@ -97,14 +104,20 @@ See <a href="../example/bimap.cpp">source code</a>.
|
||||
<p>
|
||||
This example shows how to construct a bidirectional map with
|
||||
<code>multi_index_container</code>. By a <i>bidirectional map</i> we mean
|
||||
a container of elements of <code>std::pair<const FromType,const ToType></code>
|
||||
such that no two elements exists with the same <code>first</code>
|
||||
<i>or</i> <code>second</code> value (<code>std::map</code> only
|
||||
guarantees uniqueness of the first member). Fast lookup is provided
|
||||
a container of <code>(const FromType,const ToType)</code> pairs
|
||||
such that no two elements exists with the same first
|
||||
<i>or</i> second component (<code>std::map</code> only
|
||||
guarantees uniqueness of the first component). Fast lookup is provided
|
||||
for both keys. The program features a tiny Spanish-English
|
||||
dictionary with online query of words in both languages.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This bidirectional map can be considered as a primitive precursor
|
||||
to the full-fledged container provided by
|
||||
<a href="../../bimap/index.html">Boost.Bimap</a>.
|
||||
</p>
|
||||
|
||||
<h2><a name="example5">Example 5: sequenced indices</a></h2>
|
||||
|
||||
<p>
|
||||
@@ -136,7 +149,7 @@ be defined as:
|
||||
<span class=keyword>struct</span> <span class=identifier>car_model</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>model</span><span class=special>;</span>
|
||||
<span class=identifier>std</span><span class=special>:</span><span class=identifier>string</span> <span class=identifier>manufacturer</span><span class=special>;</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>manufacturer</span><span class=special>;</span>
|
||||
<span class=keyword>int</span> <span class=identifier>price</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
@@ -170,8 +183,8 @@ involves having the manufactures stored in a separate
|
||||
<p>
|
||||
Although predefined Boost.MultiIndex key extractors can handle many
|
||||
situations involving pointers (see
|
||||
<a href="advanced_topics.html#advanced_key_extractors">advanced features
|
||||
of Boost.MultiIndex key extractors</a> in the Advanced topics section), this case
|
||||
<a href="tutorial/key_extraction.html#advanced_key_extractors">advanced features
|
||||
of Boost.MultiIndex key extractors</a> in the tutorial), this case
|
||||
is complex enough that a suitable key extractor has to be defined. The following
|
||||
utility cascades two key extractors:
|
||||
</p>
|
||||
@@ -251,7 +264,7 @@ See <a href="../example/composite_keys.cpp">source code</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex <a href="advanced_topics.html#composite_keys">
|
||||
Boost.MultiIndex <a href="tutorial/key_extraction.html#composite_keys">
|
||||
<code>composite_key</code></a> construct provides a flexible tool for
|
||||
creating indices with non-trivial sorting criteria.
|
||||
The program features a rudimentary simulation of a file system
|
||||
@@ -294,7 +307,7 @@ instance:
|
||||
<ul>
|
||||
<li>Implement additional commands, like <code>cp</code>.</li>
|
||||
<li>Add handling of absolute paths.</li>
|
||||
<li>Use <a href="advanced_topics.html#serialization">serialization</a>
|
||||
<li>Use <a href="tutorial/creation.html#serialization">serialization</a>
|
||||
to store and retrieve the filesystem state between program runs.</li>
|
||||
</ul>
|
||||
</p>
|
||||
@@ -333,6 +346,96 @@ data structure is implemented with <code>multi_index_container</code> by
|
||||
combining a sequenced index and an index of type <code>hashed_unique</code>.
|
||||
</p>
|
||||
|
||||
<h2><a name="example10">Example 10: random access indices</a></h2>
|
||||
|
||||
<p>
|
||||
See <a href="../example/random_access.cpp">source code</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The example resumes the text container introduced in
|
||||
<a href="#example5">example 5</a> and shows how substituting a random
|
||||
access index for a sequenced index allows for extra capabilities like
|
||||
efficient access by position and calculation of the offset of a given
|
||||
element into the container.
|
||||
</p>
|
||||
|
||||
<h2><a name="example11">Example 11: index rearrangement</a></h2>
|
||||
|
||||
<p>
|
||||
See <a href="../example/rearrange.cpp">source code</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There is a relatively common piece of urban lore claiming that
|
||||
a deck of cards must be shuffled seven times in a row to be perfectly
|
||||
mixed. The statement derives from the works of mathematician Persi
|
||||
Diaconis on <i>riffle shuffling</i>: this shuffling
|
||||
technique involves splitting the deck in two packets roughly the same
|
||||
size and then dropping the cards from both packets so that they become
|
||||
interleaved. It has been shown that when repeating this procedure
|
||||
seven times the statistical distribution of cards is reasonably
|
||||
close to that associated with a truly random permutation. A measure
|
||||
of "randomness" can be estimated by counting <i>rising sequences</i>:
|
||||
consider a permutation of the sequence 1,2, ... , <i>n</i>, a rising sequence
|
||||
is a maximal chain of consecutive elements <i>m</i>, <i>m+1</i>, ... , <i>m+r</i>
|
||||
such that they are arranged in ascending order. For instance, the permutation
|
||||
125364789 is composed of the two rising sequences 1234 and 56789,
|
||||
as becomes obvious by displaying the sequence like this,
|
||||
<span style="vertical-align:sub">1</span><span style="vertical-align:sub">2</span><span style="vertical-align:super">5</span><span style="vertical-align:sub">3</span><span style="vertical-align:super">6</span><span style="vertical-align:sub">4</span><span style="vertical-align:super">7</span><span style="vertical-align:super">8</span><span style="vertical-align:super">9</span>.
|
||||
The average number of rising sequences in a random permutation of
|
||||
<i>n</i> elements is (<i>n</i>+1)/2: by contrast, after a single riffle
|
||||
shuffle of an initially sorted deck of cards, there cannot be more than
|
||||
two rising sequences. The average number of rising sequences approximates
|
||||
to (<i>n</i>+1)/2 as the number of consecutive riffle shuffles increases,
|
||||
with seven shuffles yielding a close result for a 52-card poker deck.
|
||||
Brad Mann's paper
|
||||
<a href="http://www.dartmouth.edu/~chance/teaching_aids/books_articles/Mann.pdf">"How
|
||||
many times should you shuffle a deck of cards?"</a> provides a
|
||||
rigorous yet very accessible treatment of this subject.
|
||||
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The example program estimates the average number of rising sequences
|
||||
in a 52-card deck after repeated riffle shuffling as well as applying
|
||||
a completely random permutation. The deck is modeled by the following
|
||||
container:
|
||||
<blockquote><pre>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>random_access</span><span class=special><>,</span>
|
||||
<span class=identifier>random_access</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
</pre></blockquote>
|
||||
where the first index stores the current arrangement of the deck, while
|
||||
the second index is used to remember the start position. This representation
|
||||
allows for an efficient implementation of a rising sequences counting
|
||||
algorithm in linear time.
|
||||
<a href="reference/rnd_indices.html#rearrange"><code>rearrange</code></a>
|
||||
is used to apply to the deck a shuffle performed externally on an
|
||||
auxiliary data structure.
|
||||
</p>
|
||||
|
||||
<h2><a name="example12">Example 12: using Boost.Interprocess allocators</a></h2>
|
||||
|
||||
<p>
|
||||
See <a href="../example/ip_allocator.cpp">source code</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex supports special allocators such as those provided by
|
||||
<a href="../../interprocess/index.html">Boost.Interprocess</a>,
|
||||
which allows for <code>multi_index_container</code>s to be placed in shared
|
||||
memory. The example features a front-end to a small book database
|
||||
implemented by means of a <code>multi_index_container</code> stored
|
||||
in a Boost.Interprocess memory mapped file. The reader can verify that several
|
||||
instances of the program correctly work simultaneously and immediately see
|
||||
the changes to the database performed by any other instance.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
|
||||
@@ -347,9 +450,9 @@ Tests
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised March 8th 2005</p>
|
||||
<p>Revised May 26th 2009</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2009 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Future work</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<link rel="start" href="index.html">
|
||||
<link rel="prev" href="tests.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="release_notes.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -34,11 +38,9 @@ principle driving the current internal design of <code>multi_index_container</co
|
||||
|
||||
<ul>
|
||||
<li><a href="#ranked_indices">Ranked indices</a></li>
|
||||
<li><a href="#random_access_indices">Random access indices</a></li>
|
||||
<li><a href="#notifying">Notifying indices</a></li>
|
||||
<li><a href="#constraints">Constraints</a></li>
|
||||
<li><a href="#user_defined_indices">User-defined indices</a></li>
|
||||
<li><a href="#bimap">Bidirectional map</a></li>
|
||||
<li><a href="#indexed_maps">Indexed maps</a></li>
|
||||
<li><a href="#move_semantics">Move semantics</a></li>
|
||||
</ul>
|
||||
@@ -56,24 +58,6 @@ has been proposed that order-statistics trees be used to devise a new type of
|
||||
the functionality of ordered indices.
|
||||
</p>
|
||||
|
||||
<h2><a name="random_access_indices">Random access indices</a></h2>
|
||||
|
||||
<p>
|
||||
These indices provide random access iterators and location of elements
|
||||
by their position ordinal. Although they seem at first glance to model
|
||||
the semantics of <code>std::vector</code>, random access indices present
|
||||
important differences:
|
||||
<ul>
|
||||
<li>Iterator and reference validity is preserved on insertion and deletion,</li>
|
||||
<li>memory contiguity is not provided,</li>
|
||||
<li>standard mutating algorithms (vg. <code>std::sort</code>) will in general
|
||||
not work with random access indices, as elements of a
|
||||
<code>multi_index_container</code> cannot be directly moved or swapped;</li>
|
||||
</ul>
|
||||
so it might be more accurate to regard this type of indices as a variation of
|
||||
sequenced indices with random access semantics.
|
||||
</p>
|
||||
|
||||
<h2><a name="notifying">Notifying indices</a></h2>
|
||||
|
||||
<p>
|
||||
@@ -165,19 +149,6 @@ simple enough to make them worth documenting so that the (bold)
|
||||
user can write implementations for her own indices.
|
||||
</p>
|
||||
|
||||
<h2><a name="bimap">Bidirectional map</a></h2>
|
||||
|
||||
<p>
|
||||
<a href="examples.html#example4">Example 4</a> in the examples section
|
||||
features a <i>bidirectional map</i>, implemented as a
|
||||
<code>multi_index_container</code> with two unique ordered indices. This particular
|
||||
structure is deemed important enough as to provide it as a separate
|
||||
class template, relying internally in <code>multi_index_container</code>. As
|
||||
feedback is collected from the users of Boost.MultiIndex, other singular
|
||||
instantiations of <code>multi_index_container</code> might be encapsulated
|
||||
to form a component library of ready to use containers.
|
||||
</p>
|
||||
|
||||
<h2><a name="indexed_maps">Indexed maps</a></h2>
|
||||
|
||||
<p>
|
||||
@@ -255,9 +226,9 @@ Release notes
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised July 5th 2005</p>
|
||||
<p>Revised July 5th 2007</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2007 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
@@ -5,6 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Index</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<link rel="start" href="index.html">
|
||||
<link rel="next" href="tutorial/index.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -13,7 +15,7 @@
|
||||
|
||||
<div class="prev_link"></div>
|
||||
<div class="up_link"></div>
|
||||
<div class="next_link"><a href="tutorial.html"><img src="next.gif" alt="tutorial" border="0"><br>
|
||||
<div class="next_link"><a href="tutorial/index.html"><img src="next.gif" alt="tutorial" border="0"><br>
|
||||
Tutorial
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
@@ -44,16 +46,16 @@ The versatile nature of Boost.MultiIndex allows for the specification of
|
||||
a wide spectrum of different data structures. The following are possible
|
||||
examples of use developed in the documentation:
|
||||
<ul>
|
||||
<li><a href="tutorial.html#multipe_sort">Sets with several iteration orders
|
||||
<li><a href="tutorial/basics.html#multiple_sort">Sets with several iteration orders
|
||||
and search criteria</a>.</li>
|
||||
<li><a href="tutorial.html#list_fast_lookup">Lists with fast lookup</a>
|
||||
<li><a href="tutorial/basics.html#list_fast_lookup">Lists with fast lookup</a>
|
||||
and/or without duplicates.</li>
|
||||
<li><a href="examples.html#example4">Bidirectional maps</a>, i.e. maps
|
||||
searchable either for key or value.</li>
|
||||
<li><a href="examples.html#example9">MRU (most recently used) lists</a>,
|
||||
structures keeping the <i>n</i> last referenced items, beginning with
|
||||
the newest ones.</li>
|
||||
<li><a href="advanced_topics.html#emulate_std_containers">Emulations of
|
||||
<li><a href="tutorial/techniques.html#emulate_std_containers">Emulations of
|
||||
standard containers</a> taking advantage of the extra functionalities
|
||||
provided by Boost.MultiIndex.</li>
|
||||
</ul>
|
||||
@@ -62,8 +64,7 @@ examples of use developed in the documentation:
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="advanced_topics.html">Advanced topics</a></li>
|
||||
<li><a href="tutorial/index.html">Tutorial</a></li>
|
||||
<li><a href="reference/index.html">Reference</a></li>
|
||||
<li><a href="compiler_specifics.html">Compiler specifics</a></li>
|
||||
<li><a href="performance.html">Performance</a></li>
|
||||
@@ -78,15 +79,15 @@ examples of use developed in the documentation:
|
||||
|
||||
<div class="prev_link"></div>
|
||||
<div class="up_link"></div>
|
||||
<div class="next_link"><a href="tutorial.html"><img src="next.gif" alt="tutorial" border="0"><br>
|
||||
<div class="next_link"><a href="tutorial/index.html"><img src="next.gif" alt="tutorial" border="0"><br>
|
||||
Tutorial
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised March 15th 2005</p>
|
||||
<p>Revised February 6th 2006</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.5 KiB |
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Performance</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<link rel="start" href="index.html">
|
||||
<link rel="prev" href="compiler_specifics.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="examples.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -91,7 +95,7 @@ STL containers.
|
||||
<h2><a name="simulation">Manual simulation of a <code>multi_index_container</code></a></h2>
|
||||
|
||||
<p>
|
||||
The section of <a href="advanced_topics.html#simulate_std_containers">simulation
|
||||
The section on <a href="tutorial/techniques.html#emulate_std_containers">emulation
|
||||
of standard containers with <code>multi_index_container</code></a> shows the equivalence
|
||||
between single-index <code>multi_index_container</code>s and some STL containers. Let us now
|
||||
concentrate on the problem of simulating a <code>multi_index_container</code> with two
|
||||
@@ -154,8 +158,8 @@ inefficient, though: while insertion into the data structure is simple enough:
|
||||
<span class=identifier>manual_t2</span> <span class=identifier>c2</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// insert the element 5</span>
|
||||
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>=</span><span class=identifier>c1</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>5</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
|
||||
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(&*</span><span class=identifier>t1</span><span class=special>);</span>
|
||||
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it1</span><span class=special>=</span><span class=identifier>c1</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>5</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
|
||||
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(&*</span><span class=identifier>it1</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
deletion, on the other hand, necessitates a logarithmic search, whereas
|
||||
@@ -164,8 +168,8 @@ deletion, on the other hand, necessitates a logarithmic search, whereas
|
||||
<blockquote><pre>
|
||||
<span class=comment>// remove the element pointed to by it2</span>
|
||||
<span class=identifier>manual_t2</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it2</span><span class=special>=...;</span>
|
||||
<span class=identifier>c1</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(*</span><span class=identifier>it2</span><span class=special>);</span> <span class=comment>// watch out! performs in logarithmic time</span>
|
||||
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it1</span><span class=special>);</span>
|
||||
<span class=identifier>c1</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(**</span><span class=identifier>it2</span><span class=special>);</span> <span class=comment>// watch out! performs in logarithmic time</span>
|
||||
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it2</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
@@ -174,14 +178,14 @@ raw pointers, but with elements of type <code>manual_t1::iterator</code>:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=identifier>manual_t1</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #0</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=identifier>manual_t1</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #0</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special><</span>
|
||||
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span>
|
||||
<span class=identifier>it_compare</span><span class=special><</span>
|
||||
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>greater</span><span class=special><</span><span class=keyword>int</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>manual_t2</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #1</span>
|
||||
<span class=special>></span> <span class=identifier>manual_t2</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #1</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
@@ -194,13 +198,13 @@ equivalent to those of <code>indexed_t</code>:
|
||||
<span class=identifier>manual_t2</span> <span class=identifier>c2</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// insert the element 5</span>
|
||||
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>=</span><span class=identifier>c1</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>5</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
|
||||
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>t1</span><span class=special>);</span>
|
||||
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it1</span><span class=special>=</span><span class=identifier>c1</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>5</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
|
||||
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>it1</span><span class=special>);</span>
|
||||
|
||||
<span class=comment>// remove the element pointed to by it2</span>
|
||||
<span class=identifier>manual_t2</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it2</span><span class=special>=...;</span>
|
||||
<span class=identifier>c1</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(*</span><span class=identifier>it2</span><span class=special>);</span> <span class=comment>// OK: constant time</span>
|
||||
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it1</span><span class=special>);</span>
|
||||
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it2</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
@@ -237,7 +241,7 @@ On the other hand, the manual simulation allocates <i>N</i> nodes per
|
||||
element, the first holding the elements themselves and the rest
|
||||
storing iterators to the "base" container. In practice, an iterator
|
||||
merely holds a raw pointer to the node it is associated to, so its size
|
||||
is independent of the type of the elements. Suming all contributions,
|
||||
is independent of the type of the elements. Summing all contributions,
|
||||
the space allocated per element in a manual simulation is
|
||||
</p>
|
||||
|
||||
@@ -263,7 +267,25 @@ then as:
|
||||
|
||||
<p>
|
||||
The formula shows that <code>multi_index_container</code> is more efficient
|
||||
with regard to memory consumption as the number of indices grow.
|
||||
with regard to memory consumption as the number of indices grow. An implicit
|
||||
assumption has been made that headers of <code>multi_index_container</code>
|
||||
index nodes are the same size that their analogues in STL containers; but there
|
||||
is a particular case in which this is often not the case: ordered indices use a
|
||||
<a href="tutorial/indices.html#ordered_node_compression">spatial optimization
|
||||
technique</a> which is not present in many implementations of
|
||||
<code>std::set</code>, giving an additional advantage to
|
||||
<code>multi_index_container</code>s of one system word per ordered index.
|
||||
Taking this fact into account, the former formula can be adjusted to:
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<i>S<sub>I</sub></i> / <i>S<sub>M</sub></i> =
|
||||
<i>S<sub>I</sub></i> / (<i>S<sub>I</sub></i> + (<i>N</i>-1)<i>p</i> + <i>Ow</i>),
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
where <i>O</i> is the number of ordered indices of the container, and <i>w</i>
|
||||
is the system word size (typically 4 bytes on 32-bit architectures.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -289,9 +311,9 @@ will see later, the reduction can be very significative for
|
||||
</p>
|
||||
|
||||
<p>In the special case of <code>multi_index_container</code>s with only one index,
|
||||
the best we can hope for is equal performance: the tests show that the
|
||||
performance degradation in this particular situation ranges from negligible
|
||||
to small, depending on the compiler used.
|
||||
resulting performance will roughly match that of the STL equivalent containers:
|
||||
tests show that there is at most a negligible degradation with respect to STL,
|
||||
and even in some cases a small improvement.
|
||||
</p>
|
||||
|
||||
<h2><a name="tests">Performance tests</a></h2>
|
||||
@@ -314,15 +336,33 @@ has been measured for different instantiations of <code>multi_index_container</c
|
||||
at values of <i>n</i> 1,000, 10,000 and 100,000,
|
||||
and its execution time compared with that of the equivalent algorithm
|
||||
for the corresponding manual simulation of the data structure based on
|
||||
STL containers. The following compilers have been used:
|
||||
<ul>
|
||||
<li>GNU GCC 3.3.1 for Cygwin 1.5.7,</li>
|
||||
<li>Intel C++ Compiler for Windows 32-bit 7.1,</li>
|
||||
<li>Microsoft Visual C++ 6.0 Service Pack 5,</li>
|
||||
</ul>
|
||||
with their default release settings. All tests were performed on a Wintel
|
||||
box equipped with a P4 1.5GHz processor and 256 MB RAM, running
|
||||
Microsoft Windows 2000 Professional SP2.
|
||||
STL containers. The table below describes the test environments used.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<table cellspacing="0" cellpadding="5">
|
||||
<caption><b>Tests environments.</b></caption>
|
||||
<tr>
|
||||
<th>Compiler</th>
|
||||
<th>Settings</th>
|
||||
<th>OS and CPU</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GCC 3.4.5 (mingw special)</td>
|
||||
<td><code>-O3</code></td>
|
||||
<td>Windows 2000 Pro on P4 1.5 GHz, 256 MB RAM</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td>Intel C++ 7.1</td>
|
||||
<td>default release settings</td>
|
||||
<td>Windows 2000 Pro on P4 1.5 GHz, 256 MB RAM</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Microsoft Visual C++ 8.0</td>
|
||||
<td>default release settings, <code>_SECURE_SCL=0</code></td>
|
||||
<td>Windows XP on P4 Xeon 3.2 GHz, 1 GB RAM</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -357,14 +397,14 @@ which is functionally equivalent to <code>std::set<int></code>.
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<tr>
|
||||
<th width="33%">GCC 3.1.1</th>
|
||||
<th width="33%">GCC 3.4.5</th>
|
||||
<th width="33%">ICC 7.1</th>
|
||||
<th width="33%">MSVC 6.5</th>
|
||||
<th width="33%">MSVC 8.0</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">100%</td>
|
||||
<td align="center">100%</td>
|
||||
<td align="center">100%</td>
|
||||
<td align="center">80%</td>
|
||||
<td align="center">80%</td>
|
||||
<td align="center">80%</td>
|
||||
</tr>
|
||||
</table>
|
||||
<b>Table 1: Relative memory consumption of <code>multi_index_container</code> with 1
|
||||
@@ -372,8 +412,8 @@ ordered index.</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The figures confirm that in this case <code>multi_index_container</code> nodes are the
|
||||
same size than those of its <code>std::set</code> counterpart.
|
||||
The reduction in memory usage is accounted for by the optimization technique implemented
|
||||
in Boost.MultiIndex ordered indices, as <a href="#spatial_efficiency">explained above</a>.
|
||||
</p>
|
||||
|
||||
<h4><a name="time_1r">Execution time</a></h4>
|
||||
@@ -385,11 +425,12 @@ width="556" height="372"><br>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As expected, <code>multi_index_container</code> does perform in this case somewhat
|
||||
worse than <code>std::set</code>. The degradation is within 10% for ICC and
|
||||
MSVC compilers, while in GCC peaks to 20%, which can be significative
|
||||
in certain applications. This latter result is presumably accounted for by
|
||||
a lower quality of the optimizing stage carried out by GCC.
|
||||
Somewhat surprisingly, <code>multi_index_container</code> performs slightly
|
||||
better than <code>std::set</code>. A very likely explanation for this behavior
|
||||
is that the lower memory consumption of <code>multi_index_container</code>
|
||||
results in a higher processor cache hit rate.
|
||||
The improvement is smallest for GCC, presumably because the worse quality of
|
||||
this compiler's optimizer masks the cache-related benefits.
|
||||
</p>
|
||||
|
||||
<h3><a name="test_1s">Results for 1 sequenced index</a></h3>
|
||||
@@ -416,9 +457,9 @@ which is functionally equivalent to <code>std::list<int></code>.
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<tr>
|
||||
<th width="33%">GCC 3.1.1</th>
|
||||
<th width="33%">GCC 3.4.5</th>
|
||||
<th width="33%">ICC 7.1</th>
|
||||
<th width="33%">MSVC 6.5</th>
|
||||
<th width="33%">MSVC 8.0</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">100%</td>
|
||||
@@ -444,9 +485,10 @@ width="556" height="372"><br>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As in the former case, <code>multi_index_container</code> does not attain the performance
|
||||
of its STL counterpart. Again, worst results are those of GCC, with a
|
||||
degradation of up to 20% , while ICC and MSVC do not exceed a mere 5%.
|
||||
<code>multi_index_container</code> does not attain the performance
|
||||
of its STL counterpart, although the figures are close. Again, the worst results
|
||||
are those of GCC, with a degradation of up to 7%, while ICC and MSVC do not
|
||||
exceed a mere 5%.
|
||||
</p>
|
||||
|
||||
<h3><a name="test_2r">Results for 2 ordered indices</a></h3>
|
||||
@@ -470,14 +512,14 @@ The following instantiation of <code>multi_index_container</code> was tested:
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<tr>
|
||||
<th width="33%">GCC 3.1.1</th>
|
||||
<th width="33%">GCC 3.4.5</th>
|
||||
<th width="33%">ICC 7.1</th>
|
||||
<th width="33%">MSVC 6.5</th>
|
||||
<th width="33%">MSVC 8.0</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">90%</td>
|
||||
<td align="center">90%</td>
|
||||
<td align="center">90%</td>
|
||||
<td align="center">70%</td>
|
||||
<td align="center">70%</td>
|
||||
<td align="center">70%</td>
|
||||
</tr>
|
||||
</table>
|
||||
<b>Table 3: Relative memory consumption of <code>multi_index_container</code> with 2
|
||||
@@ -486,7 +528,7 @@ ordered indices.</b>
|
||||
|
||||
<p>
|
||||
These results concinde with the theoretical formula for
|
||||
<i>S<sub>I</sub></i>=36 and <i>p</i>=4.
|
||||
<i>S<sub>I</sub></i> = 28, <i>N</i> = <i>O</i> = 2 and <i>p</i> = <i>w</i> = 4.
|
||||
</p>
|
||||
|
||||
<h4><a name="time_2r">Execution time</a></h4>
|
||||
@@ -500,7 +542,9 @@ width="556" height="372"><br>
|
||||
<p>
|
||||
The experimental results confirm our hypothesis that <code>multi_index_container</code>
|
||||
provides an improvement on execution time by an approximately constant factor,
|
||||
which in this case ranges from 65% to 75% depending on the compiler.
|
||||
which in this case lies around 60%. There is no obvious explanation for the
|
||||
increased advantage of <code>multi_index_container</code> in MSVC for
|
||||
<i>n</i>=10<sup>5</sup>.
|
||||
</p>
|
||||
|
||||
<h3><a name="test_1r1s">Results for 1 ordered index + 1 sequenced index</a></h3>
|
||||
@@ -524,14 +568,14 @@ The following instantiation of <code>multi_index_container</code> was tested:
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<tr>
|
||||
<th width="33%">GCC 3.1.1</th>
|
||||
<th width="33%">GCC 3.4.5</th>
|
||||
<th width="33%">ICC 7.1</th>
|
||||
<th width="33%">MSVC 6.5</th>
|
||||
<th width="33%">MSVC 8.0</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">87.5%</td>
|
||||
<td align="center">87.5%</td>
|
||||
<td align="center">87.5%</td>
|
||||
<td align="center">75%</td>
|
||||
<td align="center">75%</td>
|
||||
<td align="center">75%</td>
|
||||
</tr>
|
||||
</table>
|
||||
<b>Table 4: Relative memory consumption of <code>multi_index_container</code> with 1
|
||||
@@ -540,7 +584,7 @@ ordered index + 1 sequenced index.</b>
|
||||
|
||||
<p>
|
||||
These results concinde with the theoretical formula for
|
||||
<i>S<sub>I</sub></i>=28 and <i>p</i>=4.
|
||||
<i>S<sub>I</sub></i> = 24, <i>N</i> = 2, <i>O</i> = 1 and <i>p</i> = <i>w</i> = 4.
|
||||
</p>
|
||||
|
||||
<h4><a name="time_1r1s">Execution time</a></h4>
|
||||
@@ -556,17 +600,13 @@ width="556" height="372"><br>
|
||||
<p>
|
||||
For <i>n</i>=10<sup>3</sup> and <i>n</i>=10<sup>4</sup>, the results
|
||||
are in agreement with our theoretical analysis, showing a constant factor
|
||||
improvement of 60-75% with respect to the STL-based manual simulation.
|
||||
improvement of 50-65% with respect to the STL-based manual simulation.
|
||||
Curiously enough, this speedup gets even higher when
|
||||
<i>n</i>=10<sup>5</sup> for two of the compilers (35% for ICC,
|
||||
25% for MSVC.) In order to rule out spurious results, the tests
|
||||
have been run many times, yielding similar outcoumes. A tentative
|
||||
explanation of this unexpected behavior may point to a degradation in
|
||||
the execution time of the manual simulation, attributable to poor
|
||||
performance of the standard STL allocator in ICC and MSVC when dealing
|
||||
with many objects of diverse sizes (the manual simulation is comprised of
|
||||
an <code>std::set</code> and a <code>std::list</code>, which demand
|
||||
differently sized nodes.)
|
||||
<i>n</i>=10<sup>5</sup> for two of the compilers, namely GCC and ICC.
|
||||
In order to rule out spurious results, the tests
|
||||
have been run many times, yielding similar outcoumes. Both test environments
|
||||
are deployed on the same machine, which points to some OS-related reason for
|
||||
this phenomenon.
|
||||
</p>
|
||||
|
||||
<h3><a name="test_3r">Results for 3 ordered indices</a></h3>
|
||||
@@ -591,14 +631,14 @@ The following instantiation of <code>multi_index_container</code> was tested:
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<tr>
|
||||
<th width="33%">GCC 3.1.1</th>
|
||||
<th width="33%">GCC 3.4.5</th>
|
||||
<th width="33%">ICC 7.1</th>
|
||||
<th width="33%">MSVC 6.5</th>
|
||||
<th width="33%">MSVC 8.0</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">86.7%</td>
|
||||
<td align="center">86.7%</td>
|
||||
<td align="center">86.7%</td>
|
||||
<td align="center">66.7%</td>
|
||||
<td align="center">66.7%</td>
|
||||
<td align="center">66.7%</td>
|
||||
</tr>
|
||||
</table>
|
||||
<b>Table 5: Relative memory consumption of <code>multi_index_container</code> with 3
|
||||
@@ -607,8 +647,7 @@ ordered indices.</b>
|
||||
|
||||
<p>
|
||||
These results concinde with the theoretical formula for
|
||||
<i>S<sub>I</sub></i>=52 and <i>p</i>=4.
|
||||
|
||||
<i>S<sub>I</sub></i> = 40, <i>N</i> = <i>O</i> = 3 and <i>p</i> = <i>w</i> = 4.
|
||||
</p>
|
||||
|
||||
<h4><a name="time_3r">Execution time</a></h4>
|
||||
@@ -620,7 +659,7 @@ width="556" height="372"><br>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Execution time for this case is between 55% and 65% lower than achieved with
|
||||
Execution time for this case is between 45% and 55% lower than achieved with
|
||||
an STL-based manual simulation of the same data structure.
|
||||
</p>
|
||||
|
||||
@@ -646,14 +685,14 @@ The following instantiation of <code>multi_index_container</code> was tested:
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<tr>
|
||||
<th width="33%">GCC 3.1.1</th>
|
||||
<th width="33%">GCC 3.4.5</th>
|
||||
<th width="33%">ICC 7.1</th>
|
||||
<th width="33%">MSVC 6.5</th>
|
||||
<th width="33%">MSVC 8.0</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">84.6%</td>
|
||||
<td align="center">84.6%</td>
|
||||
<td align="center">84.6%</td>
|
||||
<td align="center">69.2%</td>
|
||||
<td align="center">69.2%</td>
|
||||
<td align="center">69.2%</td>
|
||||
</tr>
|
||||
</table>
|
||||
<b>Table 6: Relative memory consumption of <code>multi_index_container</code> with 2
|
||||
@@ -662,7 +701,7 @@ ordered indices + 1 sequenced index.</b>
|
||||
|
||||
<p>
|
||||
These results concinde with the theoretical formula for
|
||||
<i>S<sub>I</sub></i>=44 and <i>p</i>=4.
|
||||
<i>S<sub>I</sub></i> = 36, <i>N</i> = 3, <i>O</i> = 2 and <i>p</i> = <i>w</i> = 4.
|
||||
</p>
|
||||
|
||||
<h4><a name="time_2r1s">Execution time</a></h4>
|
||||
@@ -691,10 +730,9 @@ of indices increase.
|
||||
|
||||
<p>
|
||||
In the special case of replacing standard containers with single-indexed
|
||||
<code>multi_index_container</code>s, the programmer should balance the benefits brought on
|
||||
by Boost.MultiIndex (subobject searching, in-place updating, etc.) against the
|
||||
resulting degradation in execution time. Depending on the compiler, this degradation
|
||||
can reach up to 20% of the original time.
|
||||
<code>multi_index_container</code>s, the performance of Boost.MultiIndex
|
||||
is comparable with that of the tested STL implementations, and can even yield
|
||||
some improvements both in space consumption and execution time.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
@@ -711,9 +749,9 @@ Examples
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised May 18th 2005</p>
|
||||
<p>Revised May 9th 2006</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Hashed indices reference</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="ord_indices.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="seq_indices.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -40,9 +44,11 @@ Sequenced indices
|
||||
<li><a href="#instantiation_types">Instantiation types</a></li>
|
||||
<li><a href="#types">Nested types</a></li>
|
||||
<li><a href="#constructors">Constructors, copy and assignment</a></li>
|
||||
<li><a href="#iterators">Iterators</a></li>
|
||||
<li><a href="#modifiers">Modifiers</a></li>
|
||||
<li><a href="#observers">Observers</a></li>
|
||||
<li><a href="#lookup">Lookup</a></li>
|
||||
<li><a href="#bucket_interface">Bucket interface</a></li>
|
||||
<li><a href="#hash_policy">Hash policy</a></li>
|
||||
<li><a href="#serialization">Serialization</a></li>
|
||||
</ul>
|
||||
@@ -154,7 +160,7 @@ two different forms, according to whether a tag list for the index is provided o
|
||||
|
||||
<p>
|
||||
If provided, <code>TagList</code> must be an instantiation of the class template
|
||||
<a href="#tag"><code>tag</code></a>.
|
||||
<a href="indices.html#tag"><code>tag</code></a>.
|
||||
The template arguments are used by the corresponding index implementation,
|
||||
refer to the <a href="#hash_indices">hashed indices</a> reference section for further
|
||||
explanations on their acceptable type values.
|
||||
@@ -166,7 +172,7 @@ explanations on their acceptable type values.
|
||||
A hashed index provides fast retrieval of elements of a <code>multi_index_container</code>
|
||||
through hashing tecnhiques. The interface and semantics of hashed indices are modeled according
|
||||
to the proposal for unordered associative containers given in the C++
|
||||
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf">Proposed
|
||||
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1836.pdf">Proposed
|
||||
Draft Tecnhical Report on Standard Library Extensions</a>, also known as TR1. A hashed
|
||||
index is particularized according to a given
|
||||
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
|
||||
@@ -214,6 +220,7 @@ do not exactly conform to the requirements for unordered associative containers.
|
||||
<span class=keyword>typedef</span> <span class=identifier>Pred</span> <span class=identifier>key_equal</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>tuple</span><span class=special><</span>
|
||||
<span class=identifier>size_type</span><span class=special>,</span><span class=identifier>key_from_value</span><span class=special>,</span><span class=identifier>hasher</span><span class=special>,</span><span class=identifier>key_equal</span><span class=special>></span> <span class=identifier>ctor_args</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>TagList</span> <span class=identifier>tag_list</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>Allocator</span> <span class=identifier>allocator_type</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=identifier>pointer</span> <span class=identifier>pointer</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=identifier>const_pointer</span> <span class=identifier>const_pointer</span><span class=special>;</span>
|
||||
@@ -244,7 +251,12 @@ do not exactly conform to the requirements for unordered associative containers.
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>begin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>iterator</span> <span class=identifier>end</span><span class=special>();</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>end</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// modifiers:</span>
|
||||
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
@@ -252,13 +264,17 @@ do not exactly conform to the requirements for unordered associative containers.
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></span>
|
||||
<span class=keyword>void</span> <span class=identifier>insert</span><span class=special>(</span><span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>InputIterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
|
||||
<span class=identifier>iterator</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
|
||||
<span class=identifier>size_type</span> <span class=identifier>erase</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>key_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
<span class=identifier>iterator</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></span> <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
@@ -309,6 +325,11 @@ do not exactly conform to the requirements for unordered associative containers.
|
||||
<span class=identifier>const_local_iterator</span> <span class=identifier>begin</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>local_iterator</span> <span class=identifier>end</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>);</span>
|
||||
<span class=identifier>const_local_iterator</span> <span class=identifier>end</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_local_iterator</span> <span class=identifier>cbegin</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_local_iterator</span> <span class=identifier>cend</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>local_iterator</span> <span class=identifier>local_iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=identifier>const_local_iterator</span> <span class=identifier>local_iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// hash policy:</span>
|
||||
|
||||
@@ -366,7 +387,7 @@ following types:
|
||||
<ul>
|
||||
<li><code>Value</code> from <code>multi_index_container</code>,</li>
|
||||
<li><code>Allocator</code> from <code>multi_index_container</code>,</li>
|
||||
<li><code>TagList</code> from the index specifier (if provided),</li>
|
||||
<li><code>TagList</code> from the index specifier (if provided, otherwise <code>tag<></code> is assumed),</li>
|
||||
<li><code>KeyFromValue</code> from the index specifier,</li>
|
||||
<li><code>Hash</code> from the index specifier,</li>
|
||||
<li><code>Pred</code> from the index specifier.</li>
|
||||
@@ -430,6 +451,18 @@ objects to which <code>*this</code> and <code>x</code> belong, respectively.<br>
|
||||
<b>Returns:</b> <code>*this</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="iterators">Iterators</a></h4>
|
||||
|
||||
<code>iterator iterator_to(const value_type& x);<br>
|
||||
const_iterator iterator_to(const value_type& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>x</code> is a reference to an element of the container.<br>
|
||||
<b>Returns:</b> An iterator to <code>x</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="modifiers">Modifiers</a></h4>
|
||||
|
||||
<code>std::pair<iterator,bool> insert(const value_type& x);</code>
|
||||
@@ -455,7 +488,7 @@ one element can be causing insertion not to be allowed.<br>
|
||||
<code>iterator insert(iterator position,const value_type& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.</br>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.<br>
|
||||
<b>Effects:</b> Inserts <code>x</code> into the <code>multi_index_container</code> to which
|
||||
the index belongs if
|
||||
<ul>
|
||||
@@ -484,7 +517,7 @@ void insert(InputIterator first,InputIterator last);</code>
|
||||
<code>value_type</code> or a type convertible to <code>value_type</code>.
|
||||
<code>first</code> and <code>last</code> are not iterators into any
|
||||
index of the <code>multi_index_container</code> to which this index belongs.
|
||||
<code>last</code> is reachable from <code>first</code>.</br>
|
||||
<code>last</code> is reachable from <code>first</code>.<br>
|
||||
<b>Effects:</b>
|
||||
<blockquote><pre>
|
||||
<span class=identifier>iterator</span> <span class=identifier>hint</span><span class=special>=</span><span class=identifier>end</span><span class=special>();</span>
|
||||
@@ -496,12 +529,15 @@ index of the <code>multi_index_container</code> to which this index belongs.
|
||||
<b>Exception safety:</b> Basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void erase(iterator position);</code>
|
||||
<code>iterator erase(iterator position);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
|
||||
of the index.</br>
|
||||
of the index.<br>
|
||||
<b>Effects:</b> Deletes the element pointed to by <code>position</code>.<br>
|
||||
<b>Returns:</b> An iterator pointing to the element immediately following
|
||||
the one that was deleted, or <code>end()</code>
|
||||
if no such element exists.<br>
|
||||
<b>Complexity:</b> <code>O(D(n))</code>.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
</blockquote>
|
||||
@@ -517,12 +553,13 @@ the number of elements deleted.<br>
|
||||
<b>Exception safety:</b> Basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void erase(iterator first,iterator last);</code>
|
||||
<code>iterator erase(iterator first,iterator last);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> [<code>first</code>,<code>last</code>) is a valid
|
||||
range of the index.<br>
|
||||
<b>Effects:</b> Deletes the elements in [<code>first</code>,<code>last</code>).<br>
|
||||
<b>Returns:</b> <code>last</code>.<br>
|
||||
<b>Complexity:</b> <code>O(m*D(n))</code>, where <code>m</code> is
|
||||
the number of elements in [<code>first</code>,<code>last</code>).<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
@@ -532,7 +569,7 @@ the number of elements in [<code>first</code>,<code>last</code>).<br>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
|
||||
of the index.</br>
|
||||
of the index.<br>
|
||||
<b>Effects:</b> Assigns the value <code>x</code> to the element pointed
|
||||
to by <code>position</code> into the <code>multi_index_container</code> to which
|
||||
the index belongs if, for the value <code>x</code>
|
||||
@@ -543,7 +580,8 @@ the index belongs if, for the value <code>x</code>
|
||||
<code>multi_index_container</code>.</li>
|
||||
</ul>
|
||||
<b>Postconditions:</b> Validity of <code>position</code> is preserved
|
||||
in all cases.<br>
|
||||
in all cases. If the key of the new value is equivalent to that of the replaced value,
|
||||
the position of the element does not change.<br>
|
||||
<b>Returns:</b> <code>true</code> if the replacement took place,
|
||||
<code>false</code> otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(R(n))</code>.<br>
|
||||
@@ -560,7 +598,7 @@ belongs remains in its original state.
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>value_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index.</br>
|
||||
iterator of the index.<br>
|
||||
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
|
||||
pointed to by <code>position</code> and rearranges <code>*position</code> into
|
||||
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
|
||||
@@ -572,7 +610,8 @@ all the indices of the <code>multi_index_container</code>. Rearrangement is succ
|
||||
</ul>
|
||||
If the rearrangement fails, the element is erased.<br>
|
||||
<b>Postconditions:</b> Validity of <code>position</code> is preserved if the
|
||||
operation succeeds.<br>
|
||||
operation succeeds. If the key of the modified value is equivalent to that of the original
|
||||
value, the position of the element does not change.<br>
|
||||
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
|
||||
otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(M(n))</code>.<br>
|
||||
@@ -581,6 +620,42 @@ user-provided operation (except possibly <code>mod</code>), then
|
||||
the element pointed to by <code>position</code> is erased.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Modifier,typename Rollback><br>
|
||||
bool modify(iterator position,Modifier mod,Rollback back);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>value_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index. The sequence of operations <code>mod(e)</code>,
|
||||
<code>back(e)</code>, where <code>e</code> is the element
|
||||
pointed to by <code>position</code>, restores all keys of the element
|
||||
to their original state.<br>
|
||||
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
|
||||
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
|
||||
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
|
||||
<ul>
|
||||
<li>the index is non-unique OR no other element exists
|
||||
with equivalent key,</li>
|
||||
<li>AND rearrangement is allowed by all other indices of the
|
||||
<code>multi_index_container</code>.</li>
|
||||
</ul>
|
||||
If the rearrangement fails, <code>back(e)</code> is invoked and the
|
||||
element is kept at its original position in all indices.<br>
|
||||
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
|
||||
the element is erased under the conditions described below. If the key of the modified value
|
||||
is equivalent to that of the original value, the position of the element does not change.<br>
|
||||
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
|
||||
otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(M(n))</code>.<br>
|
||||
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
|
||||
exception, in which case the modified element is erased. If <code>back</code>
|
||||
throws inside the handling code executing after some other user-provided
|
||||
operation has thrown, it is the exception generated by <code>back</code> that
|
||||
is rethrown.
|
||||
</blockquote>
|
||||
|
||||
<a name="modify_key">
|
||||
<code>template<typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
|
||||
|
||||
@@ -591,27 +666,32 @@ from <code>value_type</code>. <code>Modifier</code> is a model of
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>key_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index.</br>
|
||||
<b>Effects:</b> Calls <code>mod(k)</code> where <code>k</code> is the key
|
||||
obtained by the internal <code>KeyFromValue</code> object of the index from
|
||||
the element pointed to by <code>position</code>, and rearranges
|
||||
<code>*position</code> into all the indices of the <code>multi_index_container</code>.
|
||||
Rearrangement is successful if
|
||||
<ul>
|
||||
<li>the index is non-unique OR no other element exists
|
||||
with equivalent key,</li>
|
||||
<li>AND rearrangement is allowed by all other indices of the
|
||||
<code>multi_index_container</code>.</li>
|
||||
</ul>
|
||||
If the rearrangement fails, the element is erased.<br>
|
||||
<b>Postconditions:</b>Validity of <code>position</code> is preserved if
|
||||
the operation succeeds.<br>
|
||||
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
|
||||
otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(M(n))</code>.<br>
|
||||
<b>Exception safety:</b> Basic. If an exception is thrown by some
|
||||
user-provided operation (except possibly <code>mod</code>), then
|
||||
the element pointed to by <code>position</code> is erased.
|
||||
iterator of the index.<br>
|
||||
<b>Effects:</b> Equivalent to <code>modify(position,mod')</code>,
|
||||
with <code>mod'</code> defined in such a way that
|
||||
<code>mod'(x)</code> is the same as <code>mod(key(x))</code>, where
|
||||
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Modifier,typename Rollback><br>
|
||||
bool modify_key(iterator position,Modifier mod,Rollback back);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>key_from_value</code> is a read/write
|
||||
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
|
||||
from <code>value_type</code>. <code>Modifier</code> and <code>Rollback</code>
|
||||
are models of <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>key_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index.
|
||||
The sequence of operations <code>mod(k)</code>,
|
||||
<code>back(k)</code>, where <code>k</code> is the key of the element
|
||||
pointed to by <code>position</code>, restores k to its original state.<br>
|
||||
<b>Effects:</b> Equivalent to <code>modify(position,mod',back')</code>,
|
||||
with <code>mod'</code> and <code>back</code> defined in such a way that
|
||||
<code>mod'(x)</code> is the same as <code>mod(key(x))</code> and
|
||||
<code>back'(x)</code> is the same as <code>back(key(x))</code>, where
|
||||
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="observers">Observers</a></h4>
|
||||
@@ -647,7 +727,7 @@ Consider a pair (<code>Hash</code>, <code>Pred</code>) where
|
||||
and <code>Pred</code> is a
|
||||
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">
|
||||
<code>Binary Predicate</code></a> inducing an equivalence relation
|
||||
on <code>Key</code>, whit the additional constraint that equivalent
|
||||
on <code>Key</code>, with the additional constraint that equivalent
|
||||
keys have the same hash value.
|
||||
A triplet of types (<code>CompatibleKey</code>, <code>CompatibleHash</code>,
|
||||
<code>CompatiblePred</code>) is said to be a <i>compatible extension</i>
|
||||
@@ -698,7 +778,7 @@ In the context of a compatible extension or a compatible key, the expression
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
|
||||
(<code>hasher</code>, <code>key_equal</code>).</br>
|
||||
(<code>hasher</code>, <code>key_equal</code>).<br>
|
||||
<b>Effects:</b> Returns a pointer to an element whose key is equivalent to
|
||||
<code>x</code>, or <code>end()</code> if such an element does not exist.<br>
|
||||
<b>Complexity:</b> Average case <code>O(1)</code> (constant), worst case
|
||||
@@ -716,7 +796,7 @@ iterator find(<br>
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleHash</code>,
|
||||
<code>CompatiblePred</code>) is a compatible extension of
|
||||
(<code>hasher</code>, <code>key_equal</code>).</br>
|
||||
(<code>hasher</code>, <code>key_equal</code>).<br>
|
||||
<b>Effects:</b> Returns a pointer to an element whose key is equivalent to
|
||||
<code>x</code>, or <code>end()</code> if such an element does not exist.<br>
|
||||
<b>Complexity:</b> Average case <code>O(1)</code> (constant), worst case
|
||||
@@ -729,7 +809,7 @@ size_type count(const CompatibleKey& x)const;
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
|
||||
(<code>hasher</code>, <code>key_equal</code>).</br>
|
||||
(<code>hasher</code>, <code>key_equal</code>).<br>
|
||||
<b>Effects:</b> Returns the number of elements with key equivalent to <code>x</code>.<br>
|
||||
<b>Complexity:</b> Average case <code>O(count(x))</code>, worst case
|
||||
<code>O(n)</code>.<br>
|
||||
@@ -746,7 +826,7 @@ size_type count(<br>
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleHash</code>,
|
||||
<code>CompatiblePred</code>) is a compatible extension of
|
||||
(<code>hasher</code>, <code>key_equal</code>).</br>
|
||||
(<code>hasher</code>, <code>key_equal</code>).<br>
|
||||
<b>Effects:</b> Returns the number of elements with key equivalent to <code>x</code>.<br>
|
||||
<b>Complexity:</b> Average case <code>O(count(x,hash,eq))</code>, worst case
|
||||
<code>O(n)</code>.<br>
|
||||
@@ -758,9 +838,10 @@ std::pair<iterator,iterator> equal_range(const CompatibleKey& x)const;
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
|
||||
(<code>hasher</code>, <code>key_equal</code>).</br>
|
||||
(<code>hasher</code>, <code>key_equal</code>).<br>
|
||||
<b>Effects:</b> Returns a range containing all elements with keys equivalent
|
||||
to <code>x</code> (and only those).<br>
|
||||
to <code>x</code> (and only those), or (<code>end()</code>,<code>end()</code>)
|
||||
if no such elements exist.<br>
|
||||
<b>Complexity:</b> Average case <code>O(count(x))</code>, worst case
|
||||
<code>O(n)</code>.<br>
|
||||
</blockquote>
|
||||
@@ -768,7 +849,7 @@ to <code>x</code> (and only those).<br>
|
||||
<code>template<<br>
|
||||
typename CompatibleKey,typename CompatibleHash, typename CompatiblePred<br>
|
||||
><br>
|
||||
std::pair<iterator,iterator> equal_range(</br>
|
||||
std::pair<iterator,iterator> equal_range(<br>
|
||||
const CompatibleKey& x,<br>
|
||||
const CompatibleHash& hash,const CompatiblePred& eq)const;
|
||||
</code>
|
||||
@@ -776,13 +857,26 @@ std::pair<iterator,iterator> equal_range(</br>
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleHash</code>,
|
||||
<code>CompatiblePred</code>) is a compatible extension of
|
||||
(<code>hasher</code>, <code>key_equal</code>).</br>
|
||||
(<code>hasher</code>, <code>key_equal</code>).<br>
|
||||
<b>Effects:</b> Returns a range containing all elements with keys equivalent
|
||||
to <code>x</code> (and only those).<br>
|
||||
to <code>x</code> (and only those), or (<code>end()</code>,<code>end()</code>)
|
||||
if no such elements exist.<br>
|
||||
<b>Complexity:</b> Average case <code>O(count(x,hash,eq))</code>, worst case
|
||||
<code>O(n)</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="bucket_interface">Bucket interface</a></h4>
|
||||
|
||||
<code>local_iterator local_iterator_to(const value_type& x);<br>
|
||||
const_local_iterator local_iterator_to(const value_type& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>x</code> is a reference to an element of the container.<br>
|
||||
<b>Returns:</b> An iterator to <code>x</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<h4><a name="hash_policy">Hash policy</a></h4>
|
||||
|
||||
@@ -796,7 +890,7 @@ load factor, and <code>bucket_count()>=n</code>.<br>
|
||||
elements contained is preserved.<br>
|
||||
<b>Complexity:</b> Average case <code>O(size())</code>, worst case
|
||||
<code>O(size(n)<sup>2</sup>)</code>.<br>
|
||||
<b>Exeption safety:</b> Strong.
|
||||
<b>Exception safety:</b> Strong.
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="serialization">Serialization</a></h4>
|
||||
@@ -887,9 +981,9 @@ Sequenced indices
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised June 7th 2005</p>
|
||||
<p>Revised July 21st 2009</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2009 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,14 +5,18 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Reference</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="../tutorial/techniques.html">
|
||||
<link rel="up" href="../index.html">
|
||||
<link rel="next" href="multi_index_container.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Reference</h1>
|
||||
|
||||
<div class="prev_link"><a href="../advanced_topics.html"><img src="../prev.gif" alt="advanced topics" border="0"><br>
|
||||
Advanced topics
|
||||
<div class="prev_link"><a href="../tutorial/techniques.html"><img src="../prev.gif" alt="techniques" border="0"><br>
|
||||
Tecnhiques
|
||||
</a></div>
|
||||
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
@@ -32,6 +36,7 @@ Index
|
||||
<li><a href="ord_indices.html">Ordered indices</a></li>
|
||||
<li><a href="hash_indices.html">Hashed indices</a></li>
|
||||
<li><a href="seq_indices.html">Sequenced indices</a></li>
|
||||
<li><a href="rnd_indices.html">Random access indices</a></li>
|
||||
<li><a href="key_extraction.html">Key Extraction</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -68,6 +73,13 @@ The following dependencies among headers of Boost.MultiIndex hold:
|
||||
<code>"boost/multi_index/tag.hpp"</code></a>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="rnd_indices.html#synopsis">
|
||||
<code>"boost/multi_index/random_access_index.hpp"</code></a> includes
|
||||
<ul>
|
||||
<li><a href="indices.html#tag_synopsis">
|
||||
<code>"boost/multi_index/tag.hpp"</code></a>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="key_extraction.html#synopsis"><code>"boost/multi_index/key_extractors.hpp"</code></a>
|
||||
includes
|
||||
<ul>
|
||||
@@ -76,7 +88,9 @@ The following dependencies among headers of Boost.MultiIndex hold:
|
||||
<li><a href="key_extraction.html#member_synopsis">
|
||||
<code>"boost/multi_index/member.hpp"</code></a>,</li>
|
||||
<li><a href="key_extraction.html#mem_fun_synopsis">
|
||||
<code>"boost/multi_index/mem_fun.hpp"</code></a> and</li>
|
||||
<code>"boost/multi_index/mem_fun.hpp"</code></a>,</li>
|
||||
<li><a href="key_extraction.html#global_fun_synopsis">
|
||||
<code>"boost/multi_index/global_fun.hpp"</code></a> and</li>
|
||||
<li><a href="key_extraction.html#composite_key_synopsis">
|
||||
<code>"boost/multi_index/composite_key.hpp"</code></a>.</li>
|
||||
</ul>
|
||||
@@ -101,8 +115,8 @@ object modules.
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="../advanced_topics.html"><img src="../prev.gif" alt="advanced topics" border="0"><br>
|
||||
Advanced topics
|
||||
<div class="prev_link"><a href="../tutorial/techniques.html"><img src="../prev.gif" alt="techniques" border="0"><br>
|
||||
Tecnhiques
|
||||
</a></div>
|
||||
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
@@ -113,9 +127,9 @@ Index
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised May 30th 2005</p>
|
||||
<p>Revised June 19th 2007</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2007 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Index reference</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="multi_index_container.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="ord_indices.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -48,6 +52,7 @@ Ordered indices
|
||||
<li><a href="#other_indices">Other types</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#views">Index views</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="index_concepts">Index concepts</a></h2>
|
||||
@@ -77,7 +82,7 @@ these operations, however, do have an impact on all other indices as
|
||||
well: for instance, insertion through a given index may fail because
|
||||
there exists another index which bans the operation in order to preserve
|
||||
its invariant (like uniqueness of elements.) This circumstance, rather
|
||||
than an obstacle, yields much of the power of Boost.MultiIndex:
|
||||
than being an obstacle, yields much of the power of Boost.MultiIndex:
|
||||
equivalent constructions based on manual composition of standard
|
||||
containers would have to add a fair amount of code in order to
|
||||
globally preserve the invariants of each container while guaranteeing
|
||||
@@ -113,7 +118,7 @@ by <code>std::list</code>.
|
||||
These global operations are not directly exposed to the user, but rather
|
||||
they are wrapped as appropriate by each index (for instance, ordered indices
|
||||
provide a set-like suite of insertion member functions, whereas sequenced
|
||||
indices do have <code>push_back</code> and <code>push_front</code>
|
||||
and random access indices have <code>push_back</code> and <code>push_front</code>
|
||||
operations.) Boost.MultiIndex poses no particular conditions on
|
||||
the interface of indices, save that they must model
|
||||
<a href="http://www.sgi.com/tech/stl/Container.html">
|
||||
@@ -188,8 +193,10 @@ index specifiers
|
||||
<li><a href="hash_indices.html#unique_non_unique"><code>hashed_unique</code> and
|
||||
<code>hashed_non_unique</code></a> for
|
||||
<a href="hash_indices.html">hashed indices</a>,</li>
|
||||
<li>and <a href="seq_indices.html#sequenced"><code>sequenced</code></a> for
|
||||
<a href="seq_indices.html">sequenced indices</a>.</li>
|
||||
<li><a href="seq_indices.html#sequenced"><code>sequenced</code></a> for
|
||||
<a href="seq_indices.html">sequenced indices</a></li>
|
||||
<li>and <a href="rnd_indices.html#random_access"><code>random_access</code></a> for
|
||||
<a href="rnd_indices.html">random access indices</a>.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
@@ -272,7 +279,10 @@ sequence of tags to be assigned to an index in instantiation time.
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Tn</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>tag</span><span class=special>;</span>
|
||||
<span class=keyword>struct</span> <span class=identifier>tag</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
@@ -280,6 +290,13 @@ Elements of <code>tag</code> can be any type, though the user is expected
|
||||
to provide classes with mnemonic names. Duplicate elements are not allowed.
|
||||
The maximum number of elements of a <code>tag</code> instantiation is
|
||||
implementation defined.
|
||||
The nested
|
||||
<code>type</code> is a model of
|
||||
<a href="../../../../libs/mpl/doc/refmanual/random-access-sequence.html">
|
||||
<code>MPL Random Access Sequence</code></a> and
|
||||
<a href="../../../../libs/mpl/doc/refmanual/extensible-sequence.html">
|
||||
<code>MPL Extensible Sequence</code></a> containing the types <code>T0</code>, ... ,
|
||||
<code>Tn</code> in the same order as specified.
|
||||
</p>
|
||||
|
||||
<h2><a name="index_catalog">Indices provided by Boost.MultiIndex</a></h2>
|
||||
@@ -304,7 +321,51 @@ reference</a>.
|
||||
<p>
|
||||
<ul>
|
||||
<li><a href="seq_indices.html">Sequenced indices</a> allow to arrange
|
||||
elements as in a bidirectional list. </li>
|
||||
elements as in a bidirectional list.</li>
|
||||
<li><a href="rnd_indices.html">Random access indices</a> provide
|
||||
constant time positional access and free ordering of elements.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="views">Index views</a></h2>
|
||||
|
||||
<p>
|
||||
The following concept is used by the rearrange facilities of non key-based
|
||||
indices. Given an index <code>i</code> of type <code>Index</code>, a <i>view
|
||||
of <code>i</code></i> is any range [<code>first</code>,<code>last</code>)
|
||||
where <code>first</code> and <code>last</code> are objects of a type
|
||||
<code>Iterator</code> modelling
|
||||
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
|
||||
<code>Input Iterator</code></a> such that
|
||||
<ol>
|
||||
<li>the associated value type of <code>Iterator</code> is convertible
|
||||
to <code>const Index::value_type&</code>
|
||||
</li>
|
||||
<li>and each of the elements of <code>i</code> appears exactly once in
|
||||
[<code>first</code>,<code>last</code>).
|
||||
</li>
|
||||
</ol>
|
||||
Note that the view refers to the actual elements of <code>i</code>, not to
|
||||
copies of them. Additionally, a view is said to be <i>free</i> if its traversal
|
||||
order is not affected by changes in the traversal order of <code>i</code>.
|
||||
Examples of free views are:
|
||||
<ul>
|
||||
<li>[<code>c.begin()</code>,<code>c.end()</code>), where <code>c</code> is
|
||||
any container of reference wrappers (from
|
||||
<a href="../../../../doc/html/ref.html">Boost.Ref</a>) to the elements
|
||||
of <code>i</code> containing exactly one reference to every element.
|
||||
</li>
|
||||
<li>[<code>i'.begin()</code>,<code>i'.end()</code>), where <code>i'</code> is
|
||||
any index belonging to the same <code>multi_index_container</code>
|
||||
as <code>i</code>, except <code>i</code> itself.
|
||||
</li>
|
||||
<li>
|
||||
Any range which is a permutation of the ones described above, as for
|
||||
instance [<code>c.rbegin()</code>,<code>c.rend()</code>), or
|
||||
ranges obtained from the former with the aid of
|
||||
<a href="../../../../libs/iterator/doc/permutation_iterator.html">
|
||||
<code>permutation_iterator</code></a> from Boost.Iterator.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
@@ -322,9 +383,9 @@ Ordered indices
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised May 30th 2005</p>
|
||||
<p>Revised July 21st 2009</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2009 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,14 +5,18 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Key extraction reference</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="rnd_indices.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="../compiler_specifics.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Key extraction reference</h1>
|
||||
|
||||
<div class="prev_link"><a href="seq_indices.html"><img src="../prev.gif" alt="sequenced indices" border="0"><br>
|
||||
Sequenced indices
|
||||
<div class="prev_link"><a href="rnd_indices.html"><img src="../prev.gif" alt="random access indices" border="0"><br>
|
||||
Random access indices
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex reference" border="0"><br>
|
||||
Boost.MultiIndex reference
|
||||
@@ -59,6 +63,12 @@ Compiler specifics
|
||||
<li><a href="#boost_multi_index_mem_fun">Macro <code>BOOST_MULTI_INDEX_MEM_FUN</code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#global_fun_synopsis">Header
|
||||
<code>"boost/multi_index/global_fun.hpp"</code> synopsis</a>
|
||||
<ul>
|
||||
<li><a href="#global_fun">Class template <code>global_fun</code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#composite_key_synopsis">Header
|
||||
<code>"boost/multi_index/composite_key.hpp"</code> synopsis</a>
|
||||
<ul>
|
||||
@@ -127,12 +137,13 @@ for every <code>k1</code> of type <code>const KeyFromValue</code> and
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex provides five general-purpose key extractors:
|
||||
Boost.MultiIndex provides six general-purpose key extractors:
|
||||
<ul>
|
||||
<li><a href="#identity"><code>identity</code></a>,</li>
|
||||
<li><a href="#member"><code>member</code></a>,</li>
|
||||
<li><a href="#const_mem_fun"><code>const_mem_fun</code></a>,</li>
|
||||
<li><a href="#mem_fun"><code>mem_fun</code></a> and</li>
|
||||
<li><a href="#mem_fun"><code>mem_fun</code></a>,</li>
|
||||
<li><a href="#global_fun"><code>global_fun</code></a> and</li>
|
||||
<li><a href="#composite_key"><code>composite_key</code></a>,</li>
|
||||
</ul>
|
||||
plus replacements for some of them:
|
||||
@@ -174,6 +185,7 @@ ultimately dereferencing to values of <code>Type&</code> or
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>mem_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>composite_key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
@@ -211,7 +223,9 @@ that acts as a do-nothing identity functor.
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>Type</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if const ChainedPtr& is not convertible to const Type&</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>></span> <span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span> <span class=comment>// only provided if Type is non-const
|
||||
|
||||
@@ -254,13 +268,13 @@ type to <code>Type</code>.<br>
|
||||
<b>Returns:</b> a reference to the object chained-pointed to by <code>x</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>const Type& operator()(const Type&x)const;</code>
|
||||
<code>const Type& operator()(const Type& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>x</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>Type& operator()(Type &x)const;</code>
|
||||
<code>Type& operator()(Type& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>x</code>.
|
||||
@@ -318,7 +332,9 @@ aimed at accessing a given member of a class.
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>Type</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if const ChainedPtr& is not convertible to const Class&</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>></span> <span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Class</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span> <span class=comment>// only provided if Type is non-const</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
@@ -356,13 +372,13 @@ type to <code>Type</code>.<br>
|
||||
<b>Returns:</b> a reference to the object chained-pointed to by <code>x</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>const Type& operator()(const Class&x)const;</code>
|
||||
<code>const Type& operator()(const Class& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>x.*PtrToMember</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>Type& operator()(const Class&x);</code>
|
||||
<code>Type& operator()(Class& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>x.*PtrToMember</code>.
|
||||
@@ -408,7 +424,9 @@ luckily enough, most compilers accept it nevertheless, so
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>Type</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if const ChainedPtr& is not convertible to const Class&</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>></span> <span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Class</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span> <span class=comment>// only provided if Type is non-const</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
@@ -511,7 +529,9 @@ returning as key the result of invoking a given constant member function of a cl
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special><</span><span class=identifier>Type</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if const ChainedPtr& is not convertible to const Class&</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>></span> <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=identifier>Class</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
@@ -581,7 +601,9 @@ returning as key the result of invoking a given member function of a class.
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special><</span><span class=identifier>Type</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if ChainedPtr& is not convertible to Class&</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>></span> <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Class</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=identifier>Class</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
@@ -642,7 +664,9 @@ these pointers as an additional template parameter.
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special><</span><span class=identifier>Type</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if const ChainedPtr& is not convertible to const Class&</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>></span> <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=identifier>Class</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
@@ -684,7 +708,9 @@ used for extraction.
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special><</span><span class=identifier>Type</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if ChainedPtr& is not convertible to Class&</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>></span> <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Class</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=identifier>Class</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
@@ -751,6 +777,147 @@ but it resolves to
|
||||
for MSVC++ 6.0 or lower.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a name="global_fun_synopsis">Header
|
||||
<a href="../../../../boost/multi_index/global_fun.hpp">
|
||||
<code>"boost/multi_index/global_fun.hpp"</code></a> synopsis</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
|
||||
|
||||
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>class</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(*</span><span class=identifier>PtrToFunction</span><span class=special>)(</span><span class=identifier>Value</span><span class=special>)></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>global_fun</span><span class=special>;</span>
|
||||
|
||||
<span class=special>}</span> <span class=comment>// namespace boost::multi_index</span>
|
||||
|
||||
<span class=special>}</span> <span class=comment>// namespace boost</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h3><a name="global_fun">Class template <code>global_fun</code></a></h3>
|
||||
|
||||
<p>
|
||||
<code>global_fun</code> is a <a href="#key_extractors"><code>Key Extractor</code></a>
|
||||
based on a given global or static member function accepting the base type as argument
|
||||
and returning the associated key.
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>class</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(*</span><span class=identifier>PtrToFunction</span><span class=special>)(</span><span class=identifier>Value</span><span class=special>)></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>global_fun</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special><</span><span class=identifier>Type</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// Only provided under the following circumstances:
|
||||
// - If Value is a reference to a constant type, only provided
|
||||
// when const ChainedPtr& is not convertible to Value;
|
||||
// - if Value is a reference to a non-const type, only provided
|
||||
// when ChainedPtr& is not convertible to Value;
|
||||
// - else, only provided when const ChainedPtr& is not
|
||||
// convertible to const Value&.</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if Value is a reference type</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Value</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if Value is not a reference type</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if Value is not a reference type</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if Value is a reference type</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span>
|
||||
<span class=identifier>remove_reference</span><span class=special><</span><span class=identifier>Value</span><span class=special>>::</span><span class=identifier>type</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// only provided if Value is not a reference type or is
|
||||
// a reference to a constant type</span>
|
||||
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>remove_const</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special><</span><span class=identifier>Value</span><span class=special>>::</span><span class=identifier>type</span><span class=special>>::</span><span class=identifier>type</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>PtrToFunction</code> specifies the particular function used to extract
|
||||
the key of type <code>Type</code> from some <code>BaseType</code>.
|
||||
<code>global_fun</code> supports the following function signatures:
|
||||
<ul>
|
||||
<li><code>Type f(BaseType)</code> (<code>Value</code> is <code>BaseType</code>),</li>
|
||||
<li><code>Type f(const BaseType&)</code> (<code>Value</code> is <code>const BaseType&</code>),</li>
|
||||
<li><code>Type f(BaseType&)</code> (<code>Value</code> is <code>BaseType&</code>).</li>
|
||||
</ul>
|
||||
<code>global_fun<Type,Value,PtrToFunction></code> is a model of:
|
||||
<ul>
|
||||
<li><a href="#key_extractors"><code>Key Extractor</code></a>
|
||||
from <code>reference_wrapper<BaseType></code>,</li>
|
||||
<li><a href="#key_extractors"><code>Key Extractor</code></a>
|
||||
from any <a href="#chained_pointers">chained pointer</a>
|
||||
to <code>BaseType</code>.</li>
|
||||
</ul>
|
||||
When <code>Value</code> is <code>BaseType</code> or
|
||||
<code>const BaseType&</code>,
|
||||
<code>global_fun<Type,Value,PtrToFunction></code> is also a model of:
|
||||
<ul>
|
||||
<li><a href="#key_extractors"><code>Key Extractor</code></a>
|
||||
from <code>BaseType</code>,</li>
|
||||
<li><a href="#key_extractors"><code>Key Extractor</code></a>
|
||||
from <code>reference_wrapper<const BaseType></code>,</li>
|
||||
<li><a href="#key_extractors"><code>Key Extractor</code></a>
|
||||
from any <a href="#chained_pointers">chained pointer</a>
|
||||
to <code>const BaseType</code>.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h4><code>global_fun</code> members</h4>
|
||||
|
||||
<code>template<typename ChainedPtr> Type operator()(const ChainedPtr& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>ChainedPtr</code> is a <a href="#chained_pointers">chained pointer</a>
|
||||
type to <code>Value</code>.<br>
|
||||
<b>Returns:</b> <code>PtrToFunction)(y)</code>, where <code>y</code> is the
|
||||
object chained-pointed to by <code>x</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>Type operator()(Value x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>PtrToFunction(x)</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>Type operator()(const Value& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>PtrToFunction(x)</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>Type operator()(const reference_wrapper<const Value>& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>
|
||||
Type operator()(<br>
|
||||
const reference_wrapper<remove_reference<Value>::type>& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>Type operator()(<br>
|
||||
const reference_wrapper<<br>
|
||||
typename remove_const<<br>
|
||||
typename remove_reference<Value>::type>::type>& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
|
||||
</blockquote>
|
||||
|
||||
<h2>
|
||||
<a name="composite_key_synopsis">Header
|
||||
<a href="../../../../boost/multi_index/composite_key.hpp">
|
||||
@@ -769,7 +936,7 @@ for MSVC++ 6.0 or lower.
|
||||
|
||||
<span class=comment>// comparison operators for composite_key_result:</span>
|
||||
|
||||
<span class=comment>// <b>OP</b> is any of =,<,!=,>,>=,<=</span>
|
||||
<span class=comment>// <b>OP</b> is any of ==,<,!=,>,>=,<=</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>CompositeKey1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey2</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
|
||||
@@ -868,6 +1035,7 @@ at compile time. The returned object is of type
|
||||
<span class=keyword>const</span> <span class=identifier>key_extractor_tuple</span><span class=special>&</span> <span class=identifier>key_extractors</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>key_extractor_tuple</span><span class=special>&</span> <span class=identifier>key_extractors</span><span class=special>()</span>
|
||||
|
||||
<span class=comment>// only provided if const ChainedPtr& is not convertible to const value_type&</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>></span>
|
||||
<span class=identifier>result_type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
@@ -986,7 +1154,7 @@ instantiations as their extracted key.
|
||||
|
||||
<span class=comment>// comparison:</span>
|
||||
|
||||
<span class=comment>// <b>OP</b> is any of =,<,!=,>,>=,<=</span>
|
||||
<span class=comment>// <b>OP</b> is any of ==,<,!=,>,>=,<=</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>CompositeKey1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey2</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
|
||||
@@ -1013,8 +1181,8 @@ as <i>temporary</i>, i.e. they should not be stored or copied.
|
||||
<code>Default Constructible</code></a> or
|
||||
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>.
|
||||
Every object of type <code>composite_key_result<CompositeKey></code> is
|
||||
internally asociated to the <code>CompositeKey</code> from which it is returned
|
||||
and the object of type <code>CompositeKey::result_type</code> to which the
|
||||
internally associated to the <code>CompositeKey</code> from which it is returned
|
||||
and the object of type <code>CompositeKey::value_type</code> to which the
|
||||
composite key was applied.
|
||||
</p>
|
||||
|
||||
@@ -1060,7 +1228,7 @@ bool operator==(<br>
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>length(x)==length(y)</code>. The expression
|
||||
<code>x<sub>i</sub>==y<sub>i</sub></code> is valid for all <code>i</code>
|
||||
in <code>[0,length(x))</code>.</br>
|
||||
in <code>[0,length(x))</code>.<br>
|
||||
<b>Returns:</b> <code>true</code> if and only if
|
||||
<blockquote>
|
||||
<code>x<sub>i</sub>==y<sub>i</sub></code> for all <code>i</code>
|
||||
@@ -1090,7 +1258,7 @@ bool operator<(<br>
|
||||
<b>Requires:</b> The expressions
|
||||
<code>x<sub>i</sub><y<sub>i</sub></code> and
|
||||
<code>y<sub>i</sub><x<sub>i</sub></code> are valid for all <code>i</code>
|
||||
in <code>[0,min(length(x),length(y)))</code>.</br>
|
||||
in <code>[0,min(length(x),length(y)))</code>.<br>
|
||||
<b>Returns:</b> <code>true</code> if and only if there exists some
|
||||
<code>j</code> in the range <code>[0,min(length(x),length(y)))</code>
|
||||
such that
|
||||
@@ -1126,7 +1294,7 @@ bool operator <b><i>OP</i></b>(<br>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> The expressions given below are valid (for the particular
|
||||
<code><b><i>OP</i></b></code> considered.)</br>
|
||||
<code><b><i>OP</i></b></code> considered.)<br>
|
||||
<b>Returns:</b> <code>true</code> if and only if
|
||||
<blockquote>
|
||||
<code>!(x==y)</code> (<code><b><i>OP</i></b></code> is <code>!=</code>),<br>
|
||||
@@ -1267,7 +1435,7 @@ bool operator()(<br>
|
||||
<b>Requires:</b> <code>length(x)==length(y)</code>. The expressions
|
||||
<code>key_eqs().get<i>()(x<sub>i</sub>,y<sub>i</sub>)</code> and
|
||||
<code>key_eqs().get<i>()(y<sub>i</sub>,x<sub>i</sub>)</code>
|
||||
are valid for all <code>i</code> in <code>[0,length(x))</code>.</br>
|
||||
are valid for all <code>i</code> in <code>[0,length(x))</code>.<br>
|
||||
<b>Returns:</b> <code>true</code> if and only
|
||||
<blockquote>
|
||||
<code>key_eqs().get<i>()(x<sub>i</sub>,y<sub>i</sub>)</code>
|
||||
@@ -1417,6 +1585,14 @@ collection of elementary comparison predicates.
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>tuple</span><span class=special><</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
|
||||
@@ -1507,7 +1683,7 @@ bool operator()(<br>
|
||||
<code>key_comps().get<i>()(x<sub>i</sub>,y<sub>i</sub>)</code> and
|
||||
<code>key_comps().get<i>()(y<sub>i</sub>,x<sub>i</sub>)</code>
|
||||
are valid for all <code>i</code>
|
||||
in <code>[0,min(length(x),length(y)))</code>.</br>
|
||||
in <code>[0,min(length(x),length(y)))</code>.<br>
|
||||
<b>Returns:</b> <code>true</code> if and only if there exists some
|
||||
<code>j</code> in the range <code>[0,min(length(x),length(y)))</code>
|
||||
such that
|
||||
@@ -1522,6 +1698,32 @@ starting at <code>i==0</code>. The evaluation is short-circuited as soon as
|
||||
the result is determined to be <code>false</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>
|
||||
template<typename CompositeKey,typename Value><br>
|
||||
bool operator()(<br>
|
||||
const composite_key_result<CompositeKey>& x,const Value& y)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Effects:</b>
|
||||
<blockquote><pre>
|
||||
<span class=keyword>return</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>x</span><span class=special>,</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>cref</span><span class=special>(</span><span class=identifier>y</span><span class=special>)));</span>
|
||||
</pre></blockquote><br>
|
||||
</blockquote>
|
||||
|
||||
<code>
|
||||
template<typename Value,typename CompositeKey><br>
|
||||
bool operator()(<br>
|
||||
const Value& x,const composite_key_result<CompositeKey>& y)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Effects:</b>
|
||||
<blockquote><pre>
|
||||
<span class=keyword>return</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>cref</span><span class=special>(</span><span class=identifier>x</span><span class=special>)),</span><span class=identifier>y</span><span class=special>);</span>
|
||||
</pre></blockquote><br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="composite_key_result_less">Class template
|
||||
<code>composite_key_result_less</code></a></h4>
|
||||
|
||||
@@ -1553,6 +1755,14 @@ are instantiations of <code>std::less</code>.
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>tuple</span><span class=special><</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
|
||||
@@ -1610,6 +1820,14 @@ are instantiations of <code>std::greater</code>.
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>tuple</span><span class=special><</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
|
||||
@@ -1671,6 +1889,16 @@ and functionality as <code>composite_key_result_less<CompositeKeyResult></cod
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special><</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=special>}</span> <span class=comment>// namespace std</span>
|
||||
@@ -1711,6 +1939,16 @@ and functionality as <code>composite_key_result_greater<CompositeKeyResult></
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special><</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special><</span><span class=identifier>CompositeKey</span><span class=special>>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=special>}</span> <span class=comment>// namespace std</span>
|
||||
@@ -1983,9 +2221,22 @@ is lexicographical. Also, the following types are
|
||||
<code>composite_key_result<composite_key<K0,...,Kk> ></code>, with
|
||||
<code>Ki::result_type = Qi</code> for all <code>i = 0,...,k</code>.
|
||||
</blockquote>
|
||||
provided that each <code>Qi</code> is either <code>Ti</code> or a
|
||||
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
|
||||
of <code>Comparei</code>. In this case, the comparison is done
|
||||
provided that
|
||||
<ul>
|
||||
<li>for <code>i = 0,...,min(j,k)-1</code>, <code>Qi</code> is either <code>Ti</code>
|
||||
or <i>not coarser</i> than <code>Ti</code> (<code>Qi</code> is a
|
||||
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
|
||||
of <code>Comparei</code> and there are no two distinct elements of
|
||||
<code>Ti</code> equivalent to one single element of <code>Qi</code>);
|
||||
</li>
|
||||
<li>
|
||||
<code>Qm</code> (with <code>m = min(j,k)</code>) is either <code>Tm</code> or a
|
||||
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
|
||||
of <code>Comparem</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
In this case, the comparison is done
|
||||
lexicographically only on the first <code>1+min(j,k)</code> elements.
|
||||
</p>
|
||||
|
||||
@@ -2000,8 +2251,8 @@ subsets of those associated to <code>!(x<y)&&!(y<x)</code>.
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="seq_indices.html"><img src="../prev.gif" alt="sequenced indices" border="0"><br>
|
||||
Sequenced indices
|
||||
<div class="prev_link"><a href="rnd_indices.html"><img src="../prev.gif" alt="random access indices" border="0"><br>
|
||||
Random access indices
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex reference" border="0"><br>
|
||||
Boost.MultiIndex reference
|
||||
@@ -2012,9 +2263,9 @@ Compiler specifics
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised May 30th 2005</p>
|
||||
<p>Revised June 25th 2008</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2008 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - multi_index_container reference</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="index.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="indices.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -95,10 +99,15 @@ synopsis</a>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index_const_iterator</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span><span class=special>;</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span><span class=special>;</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_iterator</span><span class=special>;</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span><span class=special>;</span> <span class=comment><b>// deprecated</b></span>
|
||||
|
||||
<span class=comment>// multi_index_container global functions for index retrieval:</span>
|
||||
|
||||
@@ -140,9 +149,9 @@ synopsis</a>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
@@ -151,9 +160,9 @@ synopsis</a>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
@@ -162,9 +171,9 @@ synopsis</a>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
@@ -173,9 +182,9 @@ synopsis</a>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
@@ -261,19 +270,26 @@ operators and functions associated with the index (vg. comparison and
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=special>{</span><span class=keyword>typedef</span> <b><span class=identifier>implementation</span> <span class=identifier>defined</span></b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=special>{</span><span class=keyword>typedef</span> <b><span class=identifier>implementation</span> <span class=identifier>defined</span></b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_iterator</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=special>{</span><span class=keyword>typedef</span> <b><span class=identifier>implementation</span> <span class=identifier>defined</span></b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=special>{</span><span class=keyword>typedef</span> <b><span class=identifier>implementation</span> <span class=identifier>defined</span></b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
|
||||
<span class=comment>// construct/copy/destroy:</span>
|
||||
|
||||
<span class=keyword>explicit</span> <span class=identifier>multi_index_container</span><span class=special>(
|
||||
</span><span class=keyword>const</span> <span class=identifier>ctor_args_list</span><span class=special>&</span> <span class=identifier>args_list</span><span class=special>=</span><span class=identifier>ctor_args_list</span><span class=special>(),
|
||||
</span><span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&</span> <span class=identifier>al</span><span class=special>=</span><span class=identifier>allocator_type</span><span class=special>());</span>
|
||||
<span class=keyword>explicit</span> <span class=identifier>multi_index_container</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&</span> <span class=identifier>al</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special>(</span>
|
||||
<span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>InputIterator</span> <span class=identifier>last</span><span class=special>,</span>
|
||||
@@ -299,13 +315,13 @@ operators and functions associated with the index (vg. comparison and
|
||||
<span class=comment>// projection of iterators</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=comment>// multi_index_container associated global class templates:</span>
|
||||
@@ -320,22 +336,26 @@ operators and functions associated with the index (vg. comparison and
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>index</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>nth_index_iterator</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>nth_index_const_iterator</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index_iterator</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_iterator</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>index_iterator</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index_const_iterator</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span> <span class=comment><b>// deprecated</b></span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>index_const_iterator</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
@@ -392,56 +412,56 @@ operators and functions associated with the index (vg. comparison and
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=identifier>N</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=keyword>template</span> <span class=identifier>project</span><span class=special><</span><span class=identifier>N</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=identifier>N</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=keyword>template</span> <span class=identifier>project</span><span class=special><</span><span class=identifier>N</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=keyword>template</span> <span class=identifier>project</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=keyword>template</span> <span class=identifier>project</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=comment>// comparison:</span>
|
||||
@@ -489,7 +509,8 @@ scheme outlined in the
|
||||
<ol>
|
||||
<li><code>Value</code> is the
|
||||
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
|
||||
type of the elements contained.</li>
|
||||
type of the elements contained.
|
||||
</li>
|
||||
<li><code>IndexSpecifierList</code> specifies the indices that the
|
||||
<code>multi_index_container</code> is composed of. It must be a non-empty
|
||||
<a href="../../../../libs/mpl/doc/refmanual/forward-sequence.html">
|
||||
@@ -499,8 +520,27 @@ scheme outlined in the
|
||||
syntactic convenience, the
|
||||
<a href="indices.html#indexed_by"><code>indexed_by</code></a>
|
||||
MPL sequence can be used.
|
||||
<li><code>Allocator</code> must comply with the C++ requirements for
|
||||
allocators <b>[lib.allocator.requirements]</b>.
|
||||
</li>
|
||||
<li><code>Allocator</code> must be an allocator of <code>Value</code> objects
|
||||
satisfying the associated C++ requirements at <b>[lib.allocator.requirements]</b>.
|
||||
The following relaxations to the standard requirements are allowed:
|
||||
<ul>
|
||||
<li>Non-equal allocator instances are supported: swapping two non-equal
|
||||
instances must not throw any exception.
|
||||
</li>
|
||||
<li>For every type <code>T</code>,
|
||||
the type <code>Allocator::rebind<T>::other::pointer</code> can be any
|
||||
kind of
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"><code>Random
|
||||
Access Iterator</code></a>, provided that it is explicitly constructible from
|
||||
the literal <code>0</code> (standing here as the null pointer) or from any
|
||||
<code>p</code> of type <code>T*</code> pointing into an area allocated by
|
||||
some instance of <code>Allocator</code> or some other allocator type rebound
|
||||
from <code>Allocator</code>. A <code>pointer</code> constructed from
|
||||
<code>p</code> shall dereference to <code>*p</code>.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
Indices of a given <code>multi_index_container</code> instantiation cannot have
|
||||
duplicate <a href="indices.html#tags">tags</a>, either within a single
|
||||
@@ -585,7 +625,7 @@ the same order as they were specified.<br>
|
||||
|
||||
<blockquote>
|
||||
<code>index<Tag>::type</code> yields the type of the index which
|
||||
has <code>Tag</code> as an associated <a href="indices.html#tags">tag type</a>.</br>
|
||||
has <code>Tag</code> as an associated <a href="indices.html#tags">tag type</a>.<br>
|
||||
<b>Requires:</b> Some index of the <code>multi_index_container</code> has <code>Tag</code>
|
||||
as an associated tag type.
|
||||
</blockquote>
|
||||
@@ -595,6 +635,7 @@ as an associated tag type.
|
||||
<blockquote>
|
||||
<code>nth_index_iterator<N>::type</code> is equivalent to
|
||||
<code>nth_index<N>::type::iterator</code>.<br>
|
||||
<b>Note:</b> The use of <code>nth_index_iterator</code> is deprecated.
|
||||
</blockquote>
|
||||
|
||||
<code>template<int N> struct nth_index_const_iterator</code>
|
||||
@@ -602,6 +643,7 @@ as an associated tag type.
|
||||
<blockquote>
|
||||
<code>nth_index_const_iterator<N>::type</code> is equivalent to
|
||||
<code>nth_index<N>::type::const_iterator</code>.<br>
|
||||
<b>Note:</b> The use of <code>nth_index_const_iterator</code> is deprecated.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag> struct index_iterator</code>
|
||||
@@ -609,6 +651,7 @@ as an associated tag type.
|
||||
<blockquote>
|
||||
<code>index_iterator<Tag>::type</code> is equivalent to
|
||||
<code>index<Tag>::type::iterator</code>.<br>
|
||||
<b>Note:</b> The use of <code>index_iterator</code> is deprecated.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag> struct index_const_iterator</code>
|
||||
@@ -616,12 +659,13 @@ as an associated tag type.
|
||||
<blockquote>
|
||||
<code>index_const_iterator<Tag>::type</code> is equivalent to
|
||||
<code>index<Tag>::type::const_iterator</code>.<br>
|
||||
<b>Note:</b> The use of <code>index_const_iterator</code> is deprecated.
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
|
||||
|
||||
<code>explicit multi_index_container(<br>
|
||||
const ctor_args_list& comp=ctor_args_list(),<br>
|
||||
const ctor_args_list& args_list=ctor_args_list(),<br>
|
||||
const allocator_type& al=allocator_type());</code>
|
||||
|
||||
<blockquote>
|
||||
@@ -630,6 +674,14 @@ specified argument list and allocator.<br>
|
||||
<b>Complexity:</b> Constant.
|
||||
</blockquote>
|
||||
|
||||
<code>explicit multi_index_container(const allocator_type& al);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Effects:</b> Constructs an empty <code>multi_index_container</code> using the
|
||||
specified allocator and the default value of <code>ctor_args_list</code>.<br>
|
||||
<b>Complexity:</b> Constant.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename InputIterator><br>
|
||||
multi_index_container(<br>
|
||||
InputIterator first,InputIterator last,<br>
|
||||
@@ -641,7 +693,7 @@ multi_index_container(<br>
|
||||
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
|
||||
<code>Input Iterator</code></a> over elements of type
|
||||
<code>Value</code> or a type convertible to <code>Value</code>.
|
||||
<code>last</code> is reachable from <code>first</code>.</br>
|
||||
<code>last</code> is reachable from <code>first</code>.<br>
|
||||
<b>Effects:</b> Constructs and empty <code>multi_index_container</code> using the
|
||||
specified argument list and allocator and fills it with
|
||||
the elements in the range [<code>first</code>,<code>last</code>).
|
||||
@@ -754,21 +806,21 @@ are <i>equivalent</i> if:
|
||||
</p>
|
||||
|
||||
<code>template<int N,typename IteratorType><br>
|
||||
typename nth_index_iterator<N>::type project(IteratorType it);</code>
|
||||
typename nth_index<N>::type::iterator project(IteratorType it);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>0 <= N < I</code>. <code>IteratorType</code>
|
||||
belongs to <code>iterator_type_list</code>. <code>it</code> is a valid
|
||||
iterator of some index of <code>*this</code> (i.e. does not refer to some
|
||||
other <code>multi_index_container</code>.)<br>
|
||||
<b>Effects:</b> Returns an <code>nth_index_iterator<N>::type</code> iterator
|
||||
<b>Effects:</b> Returns an <code>nth_index<N>::type::iterator</code>
|
||||
equivalent to <code>it</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>template<int N,typename IteratorType><br>
|
||||
typename nth_index_const_iterator<N>::type project(IteratorType it)const;</code>
|
||||
typename nth_index<N>::type::const_iterator project(IteratorType it)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>0 <= N < I</code>. <code>IteratorType</code>
|
||||
@@ -776,38 +828,38 @@ belongs to <code>const_iterator_type_list</code> or
|
||||
<code>iterator_type_list</code>. <code>it</code> is a
|
||||
valid (constant or non-constant) iterator of some index of <code>*this</code>
|
||||
(i.e. does not refer to some other <code>multi_index_container</code>.)<br>
|
||||
<b>Effects:</b> Returns an <code>nth_index_const_iterator<N>::type</code>
|
||||
iterator equivalent to <code>it</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag,typename IteratorType><br>
|
||||
typename index_iterator<Tag>::type project(IteratorType it);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Tag</code> is such that
|
||||
<code>index_iterator<Tag>::type</code> is valid. <code>IteratorType</code>
|
||||
belongs to <code>iterator_type_list</code>. <code>it</code> is a valid
|
||||
iterator of some index of <code>*this</code> (i.e. does not refer to some
|
||||
other <code>multi_index_container</code>.)<br>
|
||||
<b>Effects:</b> Returns an <code>index_iterator<Tag>::type</code> iterator
|
||||
<b>Effects:</b> Returns an <code>nth_index<N>::type::const_iterator</code>
|
||||
equivalent to <code>it</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag,typename IteratorType><br>
|
||||
typename index_const_iterator<Tag>::type project(IteratorType it)const;</code>
|
||||
typename index<Tag>::type::iterator project(IteratorType it);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Tag</code> is such that
|
||||
<code>index_const_iterator<Tag>::type</code> is valid. <code>IteratorType</code>
|
||||
<code>index<Tag>::type</code> is valid. <code>IteratorType</code>
|
||||
belongs to <code>iterator_type_list</code>. <code>it</code> is a valid
|
||||
iterator of some index of <code>*this</code> (i.e. does not refer to some
|
||||
other <code>multi_index_container</code>.)<br>
|
||||
<b>Effects:</b> Returns an <code>index<Tag>::type::iterator</code>
|
||||
equivalent to <code>it</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag,typename IteratorType><br>
|
||||
typename index<Tag>::type::const_iterator project(IteratorType it)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Tag</code> is such that
|
||||
<code>index<Tag>::type</code> is valid. <code>IteratorType</code>
|
||||
belongs to <code>const_iterator_type_list</code> or
|
||||
<code>iterator_type_list</code>. <code>it</code> is a valid
|
||||
(constant or non-constant) iterator of some index of <code>*this</code>
|
||||
(i.e. does not refer to some other <code>multi_index_container</code>.)<br>
|
||||
<b>Effects:</b> Returns an <code>index_const_iterator<Tag>::type</code>
|
||||
<b>Effects:</b> Returns an <code>index<Tag>::type::const_iterator</code>
|
||||
iterator equivalent to <code>it</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
@@ -878,9 +930,9 @@ Index reference
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised May 30th 2005</p>
|
||||
<p>Revised November 6th 2008</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2008 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Ordered indices reference</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="indices.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="hash_indices.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -39,6 +43,7 @@ Hashed indices
|
||||
<li><a href="#complexity_signature">Complexity signature</a></li>
|
||||
<li><a href="#instantiation_types">Instantiation types</a></li>
|
||||
<li><a href="#constructors">Constructors, copy and assignment</a></li>
|
||||
<li><a href="#iterators">Iterators</a></li>
|
||||
<li><a href="#modifiers">Modifiers</a></li>
|
||||
<li><a href="#observers">Observers</a></li>
|
||||
<li><a href="#set_operations">Set operations</a></li>
|
||||
@@ -159,7 +164,7 @@ two different forms, according to whether a tag list for the index is provided o
|
||||
|
||||
<p>
|
||||
If provided, <code>TagList</code> must be an instantiation of the class template
|
||||
<a href="#tag"><code>tag</code></a>.
|
||||
<a href="indices.html#tag"><code>tag</code></a>.
|
||||
The template arguments are used by the corresponding index implementation,
|
||||
refer to the <a href="#ord_indices">ordered indices</a> reference section for further
|
||||
explanations on their acceptable type values.
|
||||
@@ -201,7 +206,7 @@ requirements for these types of containers.
|
||||
|
||||
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
|
||||
|
||||
<span class=keyword>namespace</span><span class=special>{</span> <b>implementation defined </b><span class=identifier>unbounded</span><span class=special>;</span> <span class=special>}</span> <span class=comment>// see range()</span>
|
||||
<b>implementation defined </b><span class=identifier>unbounded</span><span class=special>;</span> <span class=comment>// see range()</span>
|
||||
|
||||
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
|
||||
|
||||
@@ -218,6 +223,7 @@ requirements for these types of containers.
|
||||
<span class=keyword>typedef</span> <span class=identifier>Compare</span> <span class=identifier>key_compare</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>value_compare</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>tuple</span><span class=special><</span><span class=identifier>key_from_value</span><span class=special>,</span><span class=identifier>key_compare</span><span class=special>></span> <span class=identifier>ctor_args</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>TagList</span> <span class=identifier>tag_list</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>Allocator</span> <span class=identifier>allocator_type</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=identifier>reference</span> <span class=identifier>reference</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=identifier>const_reference</span> <span class=identifier>const_reference</span><span class=special>;</span>
|
||||
@@ -248,7 +254,14 @@ requirements for these types of containers.
|
||||
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
|
||||
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// capacity:</span>
|
||||
|
||||
<span class=keyword>bool</span> <span class=identifier>empty</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
@@ -262,13 +275,17 @@ requirements for these types of containers.
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></span>
|
||||
<span class=keyword>void</span> <span class=identifier>insert</span><span class=special>(</span><span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>InputIterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
|
||||
<span class=identifier>iterator</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
|
||||
<span class=identifier>size_type</span> <span class=identifier>erase</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>key_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
<span class=identifier>iterator</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></span> <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
|
||||
@@ -391,8 +408,8 @@ section</a>. The complexity signature of ordered indices is:
|
||||
<li>copying: <code>c(n)=n*log(n)</code>,</li>
|
||||
<li>insertion: <code>i(n)=log(n)</code>,</li>
|
||||
<li>hinted insertion: <code>h(n)=1</code> (constant) if the hint element
|
||||
precedes the point of insertion, <code>h(n)=log(n)</code> otherwise,</li>
|
||||
<li>deletion: <code>d(n)=1</code> (constant),</li>
|
||||
is immediately after the point of insertion, <code>h(n)=log(n)</code> otherwise,</li>
|
||||
<li>deletion: <code>d(n)=1</code> (amortized constant),</li>
|
||||
<li>replacement: <code>r(n)=1</code> (constant) if the element position does not
|
||||
change, <code>r(n)=log(n)</code> otherwise,</li>
|
||||
<li>modifying: <code>m(n)=1</code> (constant) if the element position does not
|
||||
@@ -410,7 +427,7 @@ following types:
|
||||
<ul>
|
||||
<li><code>Value</code> from <code>multi_index_container</code>,</li>
|
||||
<li><code>Allocator</code> from <code>multi_index_container</code>,</li>
|
||||
<li><code>TagList</code> from the index specifier (if provided),</li>
|
||||
<li><code>TagList</code> from the index specifier (if provided, otherwise <code>tag<></code> is assumed),</li>
|
||||
<li><code>KeyFromValue</code> from the index specifier,</li>
|
||||
<li><code>Compare</code> from the index specifier.</li>
|
||||
</ul>
|
||||
@@ -444,6 +461,18 @@ objects to which <code>*this</code> and <code>x</code> belong, respectively.<br>
|
||||
<b>Returns:</b> <code>*this</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="iterators">Iterators</a></h4>
|
||||
|
||||
<code>iterator iterator_to(const value_type& x);<br>
|
||||
const_iterator iterator_to(const value_type& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>x</code> is a reference to an element of the container.<br>
|
||||
<b>Returns:</b> An iterator to <code>x</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="modifiers">Modifiers</a></h4>
|
||||
|
||||
<code>std::pair<iterator,bool> insert(const value_type& x);</code>
|
||||
@@ -469,7 +498,7 @@ one element can be causing insertion not to be allowed.<br>
|
||||
<code>iterator insert(iterator position,const value_type& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.</br>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.<br>
|
||||
<b>Effects:</b> Inserts <code>x</code> into the <code>multi_index_container</code> to which
|
||||
the index belongs if
|
||||
<ul>
|
||||
@@ -479,7 +508,8 @@ the index belongs if
|
||||
<code>multi_index_container</code>.</li>
|
||||
</ul>
|
||||
<code>position</code> is used as a hint to improve the efficiency of the
|
||||
operation.<br>
|
||||
operation. If succesful, insertion happens as close as possible to the
|
||||
location just prior to <code>position</code>.<br>
|
||||
<b>Returns:</b> On successful insertion, an iterator to the newly inserted
|
||||
element. Otherwise, an iterator to an element that caused the insertion to be
|
||||
banned. Note that more than one element can be causing insertion not to be
|
||||
@@ -498,7 +528,7 @@ void insert(InputIterator first,InputIterator last);</code>
|
||||
<code>value_type</code> or a type convertible to <code>value_type</code>.
|
||||
<code>first</code> and <code>last</code> are not iterators into any
|
||||
index of the <code>multi_index_container</code> to which this index belongs.
|
||||
<code>last</code> is reachable from <code>first</code>.</br>
|
||||
<code>last</code> is reachable from <code>first</code>.<br>
|
||||
<b>Effects:</b>
|
||||
<blockquote><pre>
|
||||
<span class=identifier>iterator</span> <span class=identifier>hint</span><span class=special>=</span><span class=identifier>end</span><span class=special>();</span>
|
||||
@@ -510,12 +540,15 @@ index of the <code>multi_index_container</code> to which this index belongs.
|
||||
<b>Exception safety:</b> Basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void erase(iterator position);</code>
|
||||
<code>iterator erase(iterator position);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
|
||||
of the index.</br>
|
||||
of the index.<br>
|
||||
<b>Effects:</b> Deletes the element pointed to by <code>position</code>.<br>
|
||||
<b>Returns:</b> An iterator pointing to the element immediately following
|
||||
the one that was deleted, or <code>end()</code>
|
||||
if no such element exists.<br>
|
||||
<b>Complexity:</b> <code>O(D(n))</code>.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
</blockquote>
|
||||
@@ -530,12 +563,13 @@ the number of elements deleted.<br>
|
||||
<b>Exception safety:</b> Basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void erase(iterator first,iterator last);</code>
|
||||
<code>iterator erase(iterator first,iterator last);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> [<code>first</code>,<code>last</code>) is a valid
|
||||
range of the index.<br>
|
||||
<b>Effects:</b> Deletes the elements in [<code>first</code>,<code>last</code>).<br>
|
||||
<b>Returns:</b> <code>last</code>.<br>
|
||||
<b>Complexity:</b> <code>O(log(n) + m*D(n))</code>, where <code>m</code> is
|
||||
the number of elements in [<code>first</code>,<code>last</code>).<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
@@ -545,7 +579,7 @@ the number of elements in [<code>first</code>,<code>last</code>).<br>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
|
||||
of the index.</br>
|
||||
of the index.<br>
|
||||
<b>Effects:</b> Assigns the value <code>x</code> to the element pointed
|
||||
to by <code>position</code> into the <code>multi_index_container</code> to which
|
||||
the index belongs if, for the value <code>x</code>
|
||||
@@ -556,7 +590,8 @@ the index belongs if, for the value <code>x</code>
|
||||
<code>multi_index_container</code>.</li>
|
||||
</ul>
|
||||
<b>Postconditions:</b> Validity of <code>position</code> is preserved
|
||||
in all cases.<br>
|
||||
in all cases. If the key of the new value is equivalent to that of the
|
||||
replaced value, the position of the element does not change.<br>
|
||||
<b>Returns:</b> <code>true</code> if the replacement took place,
|
||||
<code>false</code> otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(R(n))</code>.<br>
|
||||
@@ -573,7 +608,7 @@ belongs remains in its original state.
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>value_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index.</br>
|
||||
iterator of the index.<br>
|
||||
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
|
||||
pointed to by <code>position</code> and rearranges <code>*position</code> into
|
||||
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
|
||||
@@ -585,7 +620,8 @@ all the indices of the <code>multi_index_container</code>. Rearrangement is succ
|
||||
</ul>
|
||||
If the rearrangement fails, the element is erased.<br>
|
||||
<b>Postconditions:</b> Validity of <code>position</code> is preserved if the
|
||||
operation succeeds.<br>
|
||||
operation succeeds. If the key of the modified value is equivalent to that of the
|
||||
original value, the position of the element does not change.<br>
|
||||
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
|
||||
otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(M(n))</code>.<br>
|
||||
@@ -594,6 +630,43 @@ user-provided operation (except possibly <code>mod</code>), then
|
||||
the element pointed to by <code>position</code> is erased.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Modifier,typename Rollback><br>
|
||||
bool modify(iterator position,Modifier mod,Rollback back);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>value_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index. The sequence of operations <code>mod(e)</code>,
|
||||
<code>back(e)</code>, where <code>e</code> is the element
|
||||
pointed to by <code>position</code>, restores all keys of the element
|
||||
to their original state.<br>
|
||||
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
|
||||
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
|
||||
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
|
||||
<ul>
|
||||
<li>the index is non-unique OR no other element exists
|
||||
with equivalent key,</li>
|
||||
<li>AND rearrangement is allowed by all other indices of the
|
||||
<code>multi_index_container</code>.</li>
|
||||
</ul>
|
||||
If the rearrangement fails, <code>back(e)</code> is invoked and the
|
||||
element is kept at its original position in all indices.<br>
|
||||
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
|
||||
the element is erased under the conditions described below.
|
||||
If the key of the modified value is equivalent to that of the
|
||||
original value, the position of the element does not change.<br>
|
||||
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
|
||||
otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(M(n))</code>.<br>
|
||||
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
|
||||
exception, in which case the modified element is erased. If <code>back</code>
|
||||
throws inside the handling code executing after some other user-provided
|
||||
operation has thrown, it is the exception generated by <code>back</code> that
|
||||
is rethrown.
|
||||
</blockquote>
|
||||
|
||||
<a name="modify_key">
|
||||
<code>template<typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
|
||||
|
||||
@@ -604,27 +677,32 @@ from <code>value_type</code>. <code>Modifier</code> is a model of
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>key_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index.</br>
|
||||
<b>Effects:</b> Calls <code>mod(k)</code> where <code>k</code> is the key
|
||||
obtained by the internal <code>KeyFromValue</code> object of the index from
|
||||
the element pointed to by <code>position</code>, and rearranges
|
||||
<code>*position</code> into all the indices of the <code>multi_index_container</code>.
|
||||
Rearrangement is successful if
|
||||
<ul>
|
||||
<li>the index is non-unique OR no other element exists
|
||||
with equivalent key,</li>
|
||||
<li>AND rearrangement is allowed by all other indices of the
|
||||
<code>multi_index_container</code>.</li>
|
||||
</ul>
|
||||
If the rearrangement fails, the element is erased.<br>
|
||||
<b>Postconditions:</b>Validity of <code>position</code> is preserved if
|
||||
the operation succeeds.<br>
|
||||
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
|
||||
otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(M(n))</code>.<br>
|
||||
<b>Exception safety:</b> Basic. If an exception is thrown by some
|
||||
user-provided operation (except possibly <code>mod</code>), then
|
||||
the element pointed to by <code>position</code> is erased.
|
||||
iterator of the index.<br>
|
||||
<b>Effects:</b> Equivalent to <code>modify(position,mod')</code>,
|
||||
with <code>mod'</code> defined in such a way that
|
||||
<code>mod'(x)</code> is the same as <code>mod(key(x))</code>, where
|
||||
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Modifier,typename Rollback><br>
|
||||
bool modify_key(iterator position,Modifier mod,Rollback back);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>key_from_value</code> is a read/write
|
||||
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
|
||||
from <code>value_type</code>. <code>Modifier</code> and <code>Rollback</code>
|
||||
are models of <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>key_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index.
|
||||
The sequence of operations <code>mod(k)</code>,
|
||||
<code>back(k)</code>, where <code>k</code> is the key of the element
|
||||
pointed to by <code>position</code>, restores k to its original state.<br>
|
||||
<b>Effects:</b> Equivalent to <code>modify(position,mod',back')</code>,
|
||||
with <code>mod'</code> and <code>back</code> defined in such a way that
|
||||
<code>mod'(x)</code> is the same as <code>mod(key(x))</code> and
|
||||
<code>back'(x)</code> is the same as <code>back(key(x))</code>, where
|
||||
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="observers">Observers</a></h4>
|
||||
@@ -707,7 +785,7 @@ interpretations.
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
|
||||
<code>key_compare</code>.</br>
|
||||
<code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Returns a pointer to an element whose key is equivalent to
|
||||
<code>x</code>, or <code>end()</code> if such an element does not exist.<br>
|
||||
<b>Complexity:</b> <code>O(log(n))</code>.<br>
|
||||
@@ -719,7 +797,7 @@ iterator find(const CompatibleKey& x,const CompatibleCompare& comp)const
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
is a compatible extension of <code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Returns a pointer to an element whose key is equivalent to
|
||||
<code>x</code>, or <code>end()</code> if such an element does not exist.<br>
|
||||
<b>Complexity:</b> <code>O(log(n))</code>.<br>
|
||||
@@ -731,7 +809,7 @@ count(const CompatibleKey& x)const;
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
|
||||
<code>key_compare</code>.</br>
|
||||
<code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Returns the number of elements with key equivalent to <code>x</code>.<br>
|
||||
<b>Complexity:</b> <code>O(log(n) + count(x))</code>.<br>
|
||||
</blockquote>
|
||||
@@ -742,7 +820,7 @@ size_type count(const CompatibleKey& x,const CompatibleCompare& comp)con
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
is a compatible extension of <code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Returns the number of elements with key equivalent to <code>x</code>.<br>
|
||||
<b>Complexity:</b> <code>O(log(n) + count(x,comp))</code>.<br>
|
||||
</blockquote>
|
||||
@@ -753,7 +831,7 @@ iterator lower_bound(const CompatibleKey& x)const;
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
|
||||
<code>key_compare</code>.</br>
|
||||
<code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Returns an iterator pointing to the first element with
|
||||
key not less than <code>x</code>, or <code>end()</code> if such an element does
|
||||
not exist.<br>
|
||||
@@ -766,7 +844,7 @@ iterator lower_bound(const CompatibleKey& x,const CompatibleCompare& com
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
is a compatible extension of <code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Returns an iterator pointing to the first element with
|
||||
key not less than <code>x</code>, or <code>end()</code> if such an element does
|
||||
not exist.<br>
|
||||
@@ -779,7 +857,7 @@ iterator upper_bound(const CompatibleKey& x)const;
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
|
||||
<code>key_compare</code>.</br>
|
||||
<code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Returns an iterator pointing to the first element with
|
||||
key greater than <code>x</code>, or <code>end()</code> if such an element does
|
||||
not exist.<br>
|
||||
@@ -792,7 +870,7 @@ iterator upper_bound(const CompatibleKey& x,const CompatibleCompare& com
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
is a compatible extension of <code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Returns an iterator pointing to the first element with
|
||||
key greater than <code>x</code>, or <code>end()</code> if such an element does
|
||||
not exist.<br>
|
||||
@@ -806,19 +884,19 @@ std::pair<iterator,iterator> equal_range(<br>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
|
||||
<code>key_compare</code>.</br>
|
||||
<code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Equivalent to <code>make_pair(lower_bound(x),upper_bound(x))</code>.<br>
|
||||
<b>Complexity:</b> <code>O(log(n))</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
std::pair<iterator,iterator> equal_range(</br>
|
||||
std::pair<iterator,iterator> equal_range(<br>
|
||||
const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
is a compatible extension of <code>key_compare</code>.<br>
|
||||
<b>Effects:</b> Equivalent to
|
||||
<code>make_pair(lower_bound(x,comp),upper_bound(x,comp))</code>.<br>
|
||||
<b>Complexity:</b> <code>O(log(n))</code>.<br>
|
||||
@@ -870,7 +948,7 @@ std::pair<iterator,iterator> range(<br>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>LowerBounder</code> and <code>UpperBounder</code> are
|
||||
a lower and upper bounder of <code>key_compare</code>, respectively.</br>
|
||||
a lower and upper bounder of <code>key_compare</code>, respectively.<br>
|
||||
<b>Effects:</b> Returns a pair of iterators pointing to the beginning and one
|
||||
past the end of the subsequence of elements satisfying <code>lower</code> and
|
||||
<code>upper</code> simultaneously. If no such elements exist, the iterators
|
||||
@@ -946,9 +1024,9 @@ Hashed indices
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised February 7th 2005</p>
|
||||
<p>Revised December 21st 2009</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2009 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Sequenced indices reference</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="hash_indices.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="rnd_indices.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -17,8 +21,8 @@ Hashed indices
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex reference" border="0"><br>
|
||||
Boost.MultiIndex reference
|
||||
</a></div>
|
||||
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key extraction" border="0"><br>
|
||||
Key extraction
|
||||
<div class="next_link"><a href="rnd_indices.html"><img src="../next.gif" alt="random access indices" border="0"><br>
|
||||
Random access indices
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<hr>
|
||||
@@ -37,10 +41,11 @@ Key extraction
|
||||
<li><a href="#complexity_signature">Complexity signature</a></li>
|
||||
<li><a href="#instantiation_types">Instantiation types</a></li>
|
||||
<li><a href="#constructors">Constructors, copy and assignment</a></li>
|
||||
<li><a href="#iterators">Iterators</a></li>
|
||||
<li><a href="#capacity">Capacity operations</a></li>
|
||||
<li><a href="#modifiers">Modifiers</a></li>
|
||||
<li><a href="#list_operations">List operations</a></li>
|
||||
<li><a href="#special_list_operations">Special list operations</a></li>
|
||||
<li><a href="#rearrange_operations">Rearrange operations</a></li>
|
||||
<li><a href="#serialization">Serialization</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -145,7 +150,8 @@ like <code>std::list</code>. Elements in a sequenced index are by default
|
||||
sorted according to their order of insertion: this means that new elements
|
||||
inserted through a different index of the <code>multi_index_container</code> are appended
|
||||
to the end of the sequenced index. Additionally, the index allows for free
|
||||
reordering of elements in the same vein as <code>std::list</code> does.
|
||||
reordering of elements in the same vein as <code>std::list</code> does. Validity
|
||||
of iterators and references to elements is preserved in all operations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -170,7 +176,7 @@ of <a href="http://www.sgi.com/tech/stl/ReversibleContainer.html">
|
||||
<code>Front Insertion Sequence</code></a> and
|
||||
<a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">
|
||||
<code>Back Insertion Sequence</code></a>. We only provide descriptions
|
||||
of those types and operations that are that are either not present in the
|
||||
of those types and operations that are either not present in the
|
||||
concepts modeled or do not exactly conform to the requirements for these
|
||||
types of containers.
|
||||
</p>
|
||||
@@ -190,7 +196,8 @@ types of containers.
|
||||
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>node_type</span><span class=special>::</span><span class=identifier>value_type</span> <span class=identifier>value_type</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>tuples</span><span class=special>::</span><span class=identifier>null_type</span> <span class=identifier>ctor_args</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span> <span class=identifier>allocator_type</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>TagList</span> <span class=identifier>tag_list</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>Allocator</span> <span class=identifier>allocator_type</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>allocator_type</span><span class=special>::</span><span class=identifier>reference</span> <span class=identifier>reference</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>allocator_type</span><span class=special>::</span><span class=identifier>const_reference</span> <span class=identifier>const_reference</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>iterator</span><span class=special>;</span>
|
||||
@@ -224,6 +231,13 @@ types of containers.
|
||||
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
|
||||
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// capacity:</span>
|
||||
|
||||
@@ -255,6 +269,8 @@ types of containers.
|
||||
|
||||
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>></span>
|
||||
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
|
||||
@@ -282,10 +298,11 @@ types of containers.
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>reverse</span><span class=special>();</span>
|
||||
|
||||
<span class=comment>// relocate operations:</span>
|
||||
<span class=comment>// rearrange operations:</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>relocate</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>i</span><span class=special>);</span>
|
||||
<span class=keyword>void</span> <span class=identifier>relocate</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></span> <span class=keyword>void</span> <span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=comment>// index comparison:</span>
|
||||
@@ -376,7 +393,7 @@ index specifier. Instantiations are dependent on the following types:
|
||||
<ul>
|
||||
<li><code>Value</code> from <code>multi_index_container</code>,</li>
|
||||
<li><code>Allocator</code> from <code>multi_index_container</code>,</li>
|
||||
<li><code>TagList</code> from the index specifier (if provided).</li>
|
||||
<li><code>TagList</code> from the index specifier (if provided, otherwise <code>tag<></code> is assumed).</li>
|
||||
</ul>
|
||||
<code>TagList</code> must be an instantiation of
|
||||
<a href="indices.html#tag"><code>tag</code></a>.
|
||||
@@ -412,7 +429,7 @@ void assign(InputIterator first,InputIterator last);</code>
|
||||
<code>value_type</code> or a type convertible to <code>value_type</code>.
|
||||
<code>first</code> and <code>last</code> are not iterators into any
|
||||
index of the <code>multi_index_container</code> to which this index belongs.
|
||||
<code>last</code> is reachable from <code>first</code>.</br>
|
||||
<code>last</code> is reachable from <code>first</code>.<br>
|
||||
<b>Effects:</b>
|
||||
<blockquote><pre>
|
||||
<span class=identifier>clear</span><span class=special>();</span>
|
||||
@@ -430,6 +447,18 @@ index of the <code>multi_index_container</code> to which this index belongs.
|
||||
</pre></blockquote>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="iterators">Iterators</a></h4>
|
||||
|
||||
<code>iterator iterator_to(const value_type& x);<br>
|
||||
const_iterator iterator_to(const value_type& x)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>x</code> is a reference to an element of the container.<br>
|
||||
<b>Returns:</b> An iterator to <code>x</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="capacity">Capacity operations</a></h4>
|
||||
|
||||
<code>void resize(size_type n,const value_type& x=value_type());</code>
|
||||
@@ -438,7 +467,11 @@ index of the <code>multi_index_container</code> to which this index belongs.
|
||||
<b>Effects:</b>
|
||||
<blockquote><pre>
|
||||
<span class=keyword>if</span><span class=special>(</span><span class=identifier>n</span><span class=special>></span><span class=identifier>size</span><span class=special>())</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>n</span><span class=special>-</span><span class=identifier>size</span><span class=special>(),</span><span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>else</span> <span class=keyword>if</span><span class=special>(</span><span class=identifier>n</span><span class=special><</span><span class=identifier>size</span><span class=special>())</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>begin</span><span class=special>()+</span><span class=identifier>n</span><span class=special>,</span><span class=identifier>end</span><span class=special>());</span>
|
||||
<span class=keyword>else</span> <span class=keyword>if</span><span class=special>(</span><span class=identifier>n</span><span class=special><</span><span class=identifier>size</span><span class=special>()){</span>
|
||||
<span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span><span class=identifier>begin</span><span class=special>();</span>
|
||||
<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>n</span><span class=special>);</span>
|
||||
<span class=identifier>erase</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>end</span><span class=special>());</span>
|
||||
<span class=special>}</span>
|
||||
</pre></blockquote>
|
||||
<b>Note:</b> If an expansion is requested, the size of the index is not guaranteed
|
||||
to be <code>n</code> after this operation (other indices may ban insertions.)
|
||||
@@ -477,7 +510,7 @@ Note that more than one element can be causing insertion not to be allowed.<br>
|
||||
<code>std::pair<iterator,bool> insert(iterator position,const value_type& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.</br>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.<br>
|
||||
<b>Effects:</b> Inserts <code>x</code> before <code>position</code> if insertion
|
||||
is allowed by all other indices of the <code>multi_index_container</code>.<br>
|
||||
<b>Returns:</b> The return value is a pair <code>p</code>. <code>p.second</code>
|
||||
@@ -492,7 +525,7 @@ Note that more than one element can be causing insertion not to be allowed.<br>
|
||||
<code>void insert(iterator position,size_type n,const value_type& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.</br>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.<br>
|
||||
<b>Effects:</b>
|
||||
<blockquote><pre>
|
||||
<span class=keyword>for</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>i</span><span class=special>=</span><span class=number>0</span><span class=special>;</span><span class=identifier>i</span><span class=special><</span><span class=identifier>n</span><span class=special>;++</span><span class=identifier>i</span><span class=special>)</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>position</span><span class=special>,</span><span class=identifier>x</span><span class=special>);</span>
|
||||
@@ -510,7 +543,7 @@ void insert(iterator position,InputIterator first,InputIterator last);</code>
|
||||
<code>value_type</code> or a type convertible to <code>value_type</code>.
|
||||
<code>first</code> and <code>last</code> are not iterators into any
|
||||
index of the <code>multi_index_container</code> to which this index belongs.
|
||||
<code>last</code> is reachable from <code>first</code>.</br>
|
||||
<code>last</code> is reachable from <code>first</code>.<br>
|
||||
<b>Effects:</b>
|
||||
<blockquote><pre>
|
||||
<span class=keyword>while</span><span class=special>(</span><span class=identifier>first</span><span class=special>!=</span><span class=identifier>last</span><span class=special>)</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>position</span><span class=special>,*</span><span class=identifier>first</span><span class=special>++);</span>
|
||||
@@ -524,7 +557,7 @@ number of elements in [<code>first</code>,<code>last</code>).<br>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
|
||||
of the index.</br>
|
||||
of the index.<br>
|
||||
<b>Effects:</b> Deletes the element pointed to by <code>position</code>.<br>
|
||||
<b>Returns:</b> An iterator pointing to the element immediately following
|
||||
the one that was deleted, or <code>end()</code>
|
||||
@@ -549,7 +582,7 @@ the number of elements in [<code>first</code>,<code>last</code>).<br>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
|
||||
of the index.</br>
|
||||
of the index.<br>
|
||||
<b>Effects:</b> Assigns the value <code>x</code> to the element pointed
|
||||
to by <code>position</code> into the <code>multi_index_container</code> to which
|
||||
the index belongs if replacing is allowed by all other indices of the
|
||||
@@ -572,12 +605,12 @@ belongs remains in its original state.
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>value_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index.</br>
|
||||
iterator of the index.<br>
|
||||
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
|
||||
pointed to by <code>position</code> and rearranges <code>*position</code> into
|
||||
all the indices of the <code>multi_index_container</code>. Rearrangement on sequenced
|
||||
indices does not change the position of the element with respect to the index;
|
||||
rearrangement on other indices may or might not suceed. If the rearrangement
|
||||
rearrangement on other indices may or might not succeed. If the rearrangement
|
||||
fails, the element is erased.<br>
|
||||
<b>Postconditions:</b> Validity of <code>position</code> is preserved if the
|
||||
operation succeeds.<br>
|
||||
@@ -589,10 +622,41 @@ user-provided operation (except possibly <code>mod</code>), then
|
||||
the element pointed to by <code>position</code> is erased.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Modifier,typename Rollback><br>
|
||||
bool modify(iterator position,Modifier mod,Rollback back);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
|
||||
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
|
||||
<code>Unary Function</code></a> accepting arguments of type
|
||||
<code>value_type&</code>. <code>position</code> is a valid dereferenceable
|
||||
iterator of the index. The sequence of operations <code>mod(e)</code>,
|
||||
<code>back(e)</code>, where <code>e</code> is the element
|
||||
pointed to by <code>position</code>, restores all keys of the element
|
||||
to their original state.<br>
|
||||
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
|
||||
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
|
||||
all the indices of the <code>multi_index_container</code>. Rearrangement on sequenced
|
||||
indices does not change the position of the element with respect to the index;
|
||||
rearrangement on other indices may or might not succeed. If the rearrangement
|
||||
fails, <code>back(e)</code> is invoked and the
|
||||
element is kept at its original position in all indices.<br>
|
||||
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
|
||||
the element is erased under the conditions described below.<br>
|
||||
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
|
||||
otherwise.<br>
|
||||
<b>Complexity:</b> <code>O(M(n))</code>.<br>
|
||||
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
|
||||
exception, in which case the modified element is erased. If <code>back</code>
|
||||
throws inside the handling code executing after some other user-provided
|
||||
operation has thrown, it is the exception generated by <code>back</code> that
|
||||
is rethrown.
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="list_operations">List operations</a></h4>
|
||||
|
||||
<p>
|
||||
Sequenced indices provides the full set of list operations provided by
|
||||
Sequenced indices provide the full set of list operations found in
|
||||
<code>std::list</code>; the semantics of these member functions, however,
|
||||
differ from that of <code>std::list</code> in some cases as insertions
|
||||
might not succeed due to banning by other indices. Similarly, the complexity
|
||||
@@ -604,7 +668,7 @@ same <code>multi_index_container</code>.
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
|
||||
<code>&x!=this</code>.</br>
|
||||
<code>&x!=this</code>.<br>
|
||||
<b>Effects:</b> Inserts the contents of <code>x</code> before <code>position</code>,
|
||||
in the same order as they were in <code>x</code>. Those elements succesfully
|
||||
inserted are erased from <code>x</code>.<br>
|
||||
@@ -665,7 +729,7 @@ is the number of elements erased.<br>
|
||||
|
||||
<blockquote>
|
||||
<b>Effects:</b> Erases all elements <code>x</code> of the index for which
|
||||
<code>pred(x)</code> holds..<br>
|
||||
<code>pred(x)</code> holds.<br>
|
||||
<b>Complexity:</b> <code>O(n + m*D(n))</code>, where <code>m</code>
|
||||
is the number of elements erased.<br>
|
||||
<b>Exception safety:</b> Basic.
|
||||
@@ -779,14 +843,13 @@ not throw; otherwise, basic.
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="special_list_operations">Special list operations</a></h4>
|
||||
<h4><a name="rearrange_operations">Rearrange operations</a></h4>
|
||||
|
||||
<p>
|
||||
Sequenced indices provide some convenience member functions without
|
||||
counterparts in <code>std::list</code>. These operations are aimed at
|
||||
improving the usability of sequenced indices in points where
|
||||
the support offered by standard list operations is insufficient or
|
||||
difficult to use.
|
||||
These operations, without counterpart in <code>std::list</code>
|
||||
(although <code>splice</code> provides partially overlapping
|
||||
functionality), perform individual and global repositioning of elements
|
||||
inside the index.
|
||||
</p>
|
||||
|
||||
<code>void relocate(iterator position,iterator i);</code>
|
||||
@@ -816,6 +879,20 @@ is repositioned just before <code>position</code>.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<a name="rearrange"><code>template<typename InputIterator> void rearrange(InputIterator first);</code></a>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> The range [<code>first</code>,
|
||||
<code>std::advance(first,n)</code>),
|
||||
where <code>n</code> is the size of the index, is a
|
||||
<a href="indices.html#views">free view</a> of the index.<br>
|
||||
<b>Effects:</b> The elements are rearranged so as to match the
|
||||
order of the previously described view.<br>
|
||||
<b>Postconditions:</b> No iterator or reference is invalidated.<br>
|
||||
<b>Complexity:</b> <code>O(n)</code>.<br>
|
||||
<b>Exception safety:</b> Basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="serialization">Serialization</a></h4>
|
||||
|
||||
<p>
|
||||
@@ -872,15 +949,15 @@ Hashed indices
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex reference" border="0"><br>
|
||||
Boost.MultiIndex reference
|
||||
</a></div>
|
||||
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key extraction" border="0"><br>
|
||||
Key extraction
|
||||
<div class="next_link"><a href="rnd_indices.html"><img src="../next.gif" alt="random access indices" border="0"><br>
|
||||
Random access indices
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised February 7th 2005</p>
|
||||
<p>Revised July 21st 2009</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2009 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Release notes</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<link rel="start" href="index.html">
|
||||
<link rel="prev" href="future_work.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="acknowledgements.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -27,17 +31,302 @@ Acknowledgements
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#boost_1_49">Boost 1.49 release</a></li>
|
||||
<li><a href="#boost_1_48">Boost 1.48 release</a></li>
|
||||
<li><a href="#boost_1_47">Boost 1.47 release</a></li>
|
||||
<li><a href="#boost_1_44">Boost 1.44 release</a></li>
|
||||
<li><a href="#boost_1_43">Boost 1.43 release</a></li>
|
||||
<li><a href="#boost_1_42">Boost 1.42 release</a></li>
|
||||
<li><a href="#boost_1_41">Boost 1.41 release</a></li>
|
||||
<li><a href="#boost_1_38">Boost 1.38 release</a></li>
|
||||
<li><a href="#boost_1_37">Boost 1.37 release</a></li>
|
||||
<li><a href="#boost_1_36">Boost 1.36 release</a></li>
|
||||
<li><a href="#boost_1_35">Boost 1.35 release</a></li>
|
||||
<li><a href="#boost_1_34">Boost 1.34 release</a></li>
|
||||
<li><a href="#boost_1_33_1">Boost 1.33.1 release</a></li>
|
||||
<li><a href="#boost_1_33">Boost 1.33 release</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="boost_1_49">Boost 1.49 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Suppressed a potential narrow conversion warning described in
|
||||
ticket <a href="https://svn.boost.org/trac/boost/ticket/3365">#3365</a>.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_48">Boost 1.48 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Fixed a compatibility problem with
|
||||
<a href="../../../doc/html/foreach.html">Boost.Foreach</a>
|
||||
(ticket <a href="https://svn.boost.org/trac/boost/ticket/5741">#5741</a>).
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_47">Boost 1.47 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Fixed an ADL problem in
|
||||
<a href="reference/key_extraction.html#composite_key_compare"><code>composite_key_compare</code></a>
|
||||
related with <a href="../../../doc/html/ref.html">Boost.Ref</a>.
|
||||
</li>
|
||||
<li>Maintenance fixes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_44">Boost 1.44 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>
|
||||
Fixed a bug preventing the use of <code>modify_key</code> with
|
||||
rollback in <a href="reference/ord_indices.html#modify_key">ordered</a> and
|
||||
<a href="reference/hash_indices.html#modify_key">hashed</a> indices when
|
||||
<code>Modifier</code> and <code>Rollback</code> are different types
|
||||
(ticket <a href="https://svn.boost.org/trac/boost/ticket/4130">#4130</a>).
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_43">Boost 1.43 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="../../serialization/doc/serialization.html#constructors">Serialization
|
||||
of non default constructible values</a> is now properly supported
|
||||
through user-provided facilities <code>save_construct_data</code> and
|
||||
<code>load_construct_data</code>.
|
||||
<code>multi_index_container</code> serialization
|
||||
<a href="../../serialization/doc/tutorial.html#versioning">class version</a> has been
|
||||
bumped from 1 to 2.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_42">Boost 1.42 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Maintenance fixes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_41">Boost 1.41 release</a></h2>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Serialization now uses the portable
|
||||
<a href="../../serialization/doc/wrappers.html#collection_size_type"><code>collection_size_type</code></a>
|
||||
type instead of the original <code>std::size_t</code> (ticket
|
||||
<a href="https://svn.boost.org/trac/boost/ticket/3365">#3365</a>).
|
||||
<code>multi_index_container</code> serialization
|
||||
<a href="../../serialization/doc/tutorial.html#versioning">class version</a> has been
|
||||
bumped from 0 to 1.
|
||||
</li>
|
||||
<li>Fixed a concurrency bug in the implementation of
|
||||
<a href="tutorial/debug.html#safe_mode">safe mode</a>
|
||||
(ticket <a href="https://svn.boost.org/trac/boost/ticket/3462">#3462</a>).
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_38">Boost 1.38 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>These constructs are deprecated:
|
||||
<ul>
|
||||
<li><code>nth_index_iterator<MultiIndexContainer,N>::type</code>,</li>
|
||||
<li><code>multi_index_container<...>::nth_index_iterator<N>::type</code>,</li>
|
||||
<li><code>nth_index_const_iterator<MultiIndexContainer,N>::type</code>,</li>
|
||||
<li><code>multi_index_container<...>::nth_index_const_iterator<N>::type</code>,</li>
|
||||
<li><code>index_iterator<MultiIndexContainer,Tag>::type</code>,</li>
|
||||
<li><code>multi_index_container<...>::index_iterator<Tag>::type</code>,</li>
|
||||
<li><code>index_const_iterator<MultiIndexContainer,Tag>::type</code>,</li>
|
||||
<li><code>multi_index_container<...>::index_const_iterator<Tag>::type</code>.</li>
|
||||
</ul>
|
||||
Use the following instead:
|
||||
<ul>
|
||||
<li><code>nth_index<MultiIndexContainer,N>::type::iterator</code>,</li>
|
||||
<li><code>multi_index_container<...>::nth_index<N>::type::iterator</code>,</li>
|
||||
<li><code>nth_index<MultiIndexContainer,N>::type::const_iterator</code>,</li>
|
||||
<li><code>multi_index_container<...>::nth_index<N>::type::const_iterator</code>,</li>
|
||||
<li><code>index<MultiIndexContainer,Tag>::type::iterator</code>,</li>
|
||||
<li><code>multi_index_container<...>::index<Tag>::type::iterator</code>,</li>
|
||||
<li><code>index<MultiIndexContainer,Tag>::type::const_iterator</code>,</li>
|
||||
<li><code>multi_index_container<...>::index<Tag>::type::const_iterator</code>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Maintenance fixes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_37">Boost 1.37 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Maintenance fixes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_36">Boost 1.36 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li><a name="stable_update">On prior versions of the library, the <a href="tutorial/indices.html#hash_updating">update
|
||||
member functions</a> of hashed indices could alter the position of an element even if the
|
||||
associated key did not change with the update. This is legal but probably unexpected behavior.
|
||||
The functions have been rewritten to provide the additional guarantee that elements with
|
||||
unmodified key will not change position in hashed indices, just as always was the case with
|
||||
ordered indices. These guarantees are now documented in the reference.</a></li>
|
||||
<li>Added the constructor <code>multi_index_container::multi_index_container(const allocator_type&)</code>
|
||||
to mimic the equivalent interface in STL sequence containers.
|
||||
<li>Maintenance fixes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_35">Boost 1.35 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>New <a href="tutorial/key_extraction.html#global_fun"><code>global_fun</code></a>
|
||||
predefined key extractor.
|
||||
</li>
|
||||
<li>Added <a href="tutorial/indices.html#iterator_to"><code>iterator_to</code></a>
|
||||
facility.
|
||||
</li>
|
||||
<li>Included <a href="tutorial/creation.html#special_allocator">support for
|
||||
non-standard allocators</a> such as those of
|
||||
<a href="../../interprocess/index.html">Boost.Interprocess</a>, which makes
|
||||
<code>multi_index_container</code>s placeable in shared memory.
|
||||
</li>
|
||||
<li>New versions of <code>modify</code> and <code>modify_key</code> with
|
||||
rollback, as described in the
|
||||
<a href="tutorial/basics.html#ord_updating">tutorial</a>.
|
||||
</li>
|
||||
<li>Indices provide the new <code>cbegin</code>, <code>cend</code> and,
|
||||
when applicable, <code>crbegin</code> and <code>crend</code>
|
||||
member functions, in accordance with the latest drafts of the next
|
||||
revision of the C++ standard.
|
||||
</li>
|
||||
<li>Hinted insertion in ordered indices fully conforms to the resolutions of
|
||||
C++ Standard Library
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233">Defect
|
||||
Report 233</a>. The new requirement that the point of insertion
|
||||
be always as close as possible to the hint induces a different behavior than
|
||||
exhibited in former releases of Boost.MultiIndex, which can potentially cause
|
||||
backwards compatibility problems; in any case, the likelihood of these
|
||||
compatibility issues arising in a real scenario is very low.
|
||||
</li>
|
||||
<li>Sequenced and random access indices now follow the requirements of the
|
||||
C++ standard for sequence containers with respect to the operations
|
||||
<code>assign(f,l)</code> and <code>insert(p,f,l)</code> (23.1.1/9): if
|
||||
<code>f</code> and <code>l</code> are of the same integral type, the
|
||||
iterator-based overloads of these member functions are avoided:
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span><span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>sequenced_container</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=identifier>l</span><span class=special>(...);</span>
|
||||
<span class=identifier>sequenced_container</span> <span class=identifier>c</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// iterator-based overload of assign</span>
|
||||
<span class=identifier>c</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>l</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>l</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
|
||||
|
||||
<span class=comment>// The following is equivalent to
|
||||
// c.assign(
|
||||
// static_cast<sequenced_container::size_type>(10),100);
|
||||
// that is, "10" and "100" are not taken to be iterators as
|
||||
// in the previous expression.</span>
|
||||
<span class=identifier>c</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=number>10</span><span class=special>,</span><span class=number>100</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
</li>
|
||||
<li>The performance of ordered indices <code>range</code> and
|
||||
<code>equal_range</code> has been improved.
|
||||
</li>
|
||||
<li>Maintenance fixes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_34">Boost 1.34 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Added <a href="tutorial/indices.html#rnd_indices">random access
|
||||
indices</a>.
|
||||
</li>
|
||||
<li>Non key-based indices provide new
|
||||
<a href="tutorial/indices.html#rearrange">rearrange facilities</a>
|
||||
allowing for interaction with external mutating algorithms.
|
||||
</li>
|
||||
<li>All predefined Boost.MultiIndex key extractors
|
||||
instantiated for a given type <code>T</code> can handle objects of types
|
||||
derived from or convertible to <code>T</code> (and
|
||||
<a href="reference/key_extraction.html#chained_pointers">chained pointers</a>
|
||||
to those). Previously, only objects of the exact type specified (along with
|
||||
<code>reference_wrapper</code>s and chained pointers to them) were accepted.
|
||||
</li>
|
||||
<li><a href="reference/key_extraction.html#composite_key_compare"><code>composite_key_compare</code></a>
|
||||
and related classes accept operands not included in tuples as if they were passed
|
||||
in a tuple of length 1; this allows the user to omit tuple enclosing in
|
||||
lookup operations involving composite keys when only the first key is provided.
|
||||
</li>
|
||||
<li>The core algorithms of ordered indices have been optimized, yielding
|
||||
an estimated reduction of about 5% in insertion times.
|
||||
</li>
|
||||
<li>Size of ordered indices node headers have been reduced by 25% on
|
||||
most platforms, using a well known
|
||||
<a href="tutorial/indices.html#ordered_node_compression">optimization
|
||||
technique</a>.
|
||||
</li>
|
||||
<li>The tutorial has been restructured, new examples added.</li>
|
||||
<li>Maintenance fixes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_33_1">Boost 1.33.1 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>For ordered and hashed indices, <code>erase(it)</code> and
|
||||
<code>erase(first,last)</code> now return an iterator to the element
|
||||
following those being deleted (previously nothing was returned), in
|
||||
accordance with the C++ Standard Library
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#130">Defect
|
||||
Report 130</a> and issue 6.19 of TR1
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">Issues
|
||||
List</a>.
|
||||
</li>
|
||||
<li>Boost.MultiIndex offers the usual guarantees with respect to
|
||||
multithreading code provided by most STL implementations:
|
||||
<ol>
|
||||
<li>Concurrent access to different containers is safe.</li>
|
||||
<li>Concurrent read-only access to the same container is safe.</li>
|
||||
</ol>
|
||||
In previous versions of the library, the latter guarantee was not properly
|
||||
maintained if the <a href="tutorial/debug.html#safe_mode">safe
|
||||
mode</a> was set. This problem has been fixed now.
|
||||
</li>
|
||||
<li>Maintenance fixes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="boost_1_33">Boost 1.33 release</a></h2>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Added <a href="advanced_topics.html#hashed_indices">hashed indices</a>,
|
||||
<li>Added <a href="tutorial/indices.html#hashed_indices">hashed indices</a>,
|
||||
whose interface is based on the specification for unordered associative
|
||||
containers by the C++ Standard Library Technical Report (TR1).
|
||||
<li>Added <a href="advanced_topics.html#serialization">serialization support</a>
|
||||
</li>
|
||||
<li>Added <a href="tutorial/creation.html#serialization">serialization support</a>
|
||||
for <a href="../../serialization/index.html">Boost.Serialization</a>.
|
||||
</li>
|
||||
<li>Destruction of <code>multi_index_container</code>s and <code>clear</code>
|
||||
@@ -70,9 +359,9 @@ Acknowledgements
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised March 3rd 2005</p>
|
||||
<p>Revised November 24th 2011</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2011 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Tests</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<link rel="start" href="index.html">
|
||||
<link rel="prev" href="examples.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="future_work.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -45,8 +49,9 @@ with some of the least common features offered by Boost.MultiIndex.
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_capacity.cpp"><code>test_capacity.cpp</code></a></td>
|
||||
<td><code>empty</code>, <code>size</code> and (sequenced indices only)
|
||||
<code>resize</code>.</td>
|
||||
<td><code>empty</code>, <code>size</code>, <code>resize</code>
|
||||
(non key-based indices) and <code>reserve</code>/<code>capacity</code>
|
||||
(random access indices only).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../test/test_comparison.cpp"><code>test_comparison.cpp</code></a></td>
|
||||
@@ -63,7 +68,7 @@ with some of the least common features offered by Boost.MultiIndex.
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_copy_assignment.cpp"><code>test_copy_assignment.cpp</code></a></td>
|
||||
<td>Various forms of assignment: copy, <code>operator =</code>, insertion,
|
||||
(sequenced indices only) <code>assign</code> .
|
||||
(non key-based indices only) <code>assign</code> .
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../test/test_hash_ops.cpp"><code>test_hash_ops.cpp</code></a></td>
|
||||
@@ -79,7 +84,7 @@ with some of the least common features offered by Boost.MultiIndex.
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_list_ops.cpp"><code>test_list_ops.cpp</code></a></td>
|
||||
<td>List-like operations particular to sequenced indices.</td>
|
||||
<td>List-like operations particular to sequenced and random access indices.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../test/test_modifiers.cpp"><code>test_modifiers.cpp</code></a></td>
|
||||
@@ -102,22 +107,23 @@ with some of the least common features offered by Boost.MultiIndex.
|
||||
<td>Exercises the <code>range</code> facility (ordered indices only).</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_rearrange.cpp"><code>test_rearrange.cpp</code></a></td>
|
||||
<td>Rearrange functions of sequenced and random access indices.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../test/test_safe_mode.cpp"><code>test_safe_mode.cpp</code></a></td>
|
||||
<td>Comprehensive coverage of all conditions checked in safe mode.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../test/test_serialization.cpp"><code>test_serialization.cpp</code></a></td>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_serialization1.cpp"><code>test_serialization1.cpp</code></a><br>
|
||||
<a href="../test/test_serialization2.cpp"><code>test_serialization2.cpp</code></a><br>
|
||||
<a href="../test/test_serialization3.cpp"><code>test_serialization3.cpp</code></a></td>
|
||||
<td>Serialization support.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_set_ops.cpp"><code>test_set_ops.cpp</code></a></td>
|
||||
<td>Set-like operations particular to ordered indices.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../test/test_special_list_ops.cpp"><code>test_special_list_ops.cpp</code></a></td>
|
||||
<td>Convenience functions of sequenced indices not present in
|
||||
<code>std::list</code>.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_special_set_ops.cpp"><code>test_special_set_ops.cpp</code></a></td>
|
||||
<td>Checks special lookup operations using compatible sorting criteria.</td>
|
||||
@@ -144,9 +150,9 @@ Future work
|
||||
<br>
|
||||
|
||||
|
||||
<p>Revised July 27th 2005</p>
|
||||
<p>Revised July 11th 2007</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2007 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
||||
@@ -3,22 +3,26 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Tutorial</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<title>Boost.MultiIndex Documentation - Tutorial - Basics</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="index.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="indices.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Tutorial</h1>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Basics</h1>
|
||||
|
||||
<div class="prev_link"><a href="index.html"><img src="prev.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="advanced_topics.html"><img src="next.gif" alt="advanced topics" border="0"><br>
|
||||
Advanced topics
|
||||
<div class="next_link"><a href="indices.html"><img src="../next.gif" alt="index types" border="0"><br>
|
||||
Index types
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<hr>
|
||||
@@ -26,16 +30,15 @@ Advanced topics
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#rationale">Rationale</a></li>
|
||||
<li><a href="#namespace">Namespace</a></li>
|
||||
<li><a href="#intro">Introduction</a>
|
||||
<ul>
|
||||
<li><a href="#multipe_sort">Multiple sorts on a single set</a></li>
|
||||
<li><a href="#multiple_sort">Multiple sorts on a single set</a></li>
|
||||
<li><a href="#list_fast_lookup">A bidirectional list with fast lookup</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#index_spec">Index specification</a></li>
|
||||
<li><a href="#tagging">Tagging</a></li>
|
||||
<li><a href="#iterator_access">Iterator access</a></li>
|
||||
<li><a href="#index_types">Index types</a>
|
||||
<ul>
|
||||
<li><a href="#ord_indices">Ordered indices</a>
|
||||
@@ -62,78 +65,6 @@ Advanced topics
|
||||
<li><a href="#complexity">Complexity and exception safety</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="rationale">Rationale</a></h2>
|
||||
|
||||
<p>
|
||||
STL containers are designed around the concept that each container controls its
|
||||
own collection of elements, giving access to them in a manner specified by the
|
||||
container's type: so, an <code>std::set</code> maintains the elements ordered
|
||||
by a specified sorting criterium, <code>std::list</code> allows for free
|
||||
positioning of elements along a linear sequence, and so on.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sometimes, the necessity arises of having different access interfaces
|
||||
to the same underlying collection: for instance, some data might need to be
|
||||
sorted according to more than one comparison predicate, or a bidirectional list
|
||||
might benefit from a supplemental logarithmic lookup interface. In these
|
||||
situations, programmers typically resort to manual compositions of different
|
||||
containers, a solution that generally involves a fair amount of code
|
||||
devoted to preserve the synchronization of the different parts of
|
||||
the composition. Boost.MultiIndex allows for the specification of
|
||||
<code>multi_index_container</code>s comprised of one or more <i>indices</i> with
|
||||
different interfaces to the same collection of elements. The resulting constructs
|
||||
are conceptually cleaner than manual compositions, and often perform much better.
|
||||
An important design decision has been taken that the indices of a given
|
||||
<code>multi_index_container</code> instantiation be specified at compile time: this
|
||||
gives ample room for static type checking and code optimization.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex takes inspiration from basic concepts of indexing arising in the
|
||||
theory of relational databases, though it is not intended to provide a full-fledged
|
||||
relational database framework. <code>multi_index_container</code> integrates seamlessly
|
||||
into the STL container/algorithm design, and features some extra capabilities regarding
|
||||
lookup operations and element updating which are useful extensions even for
|
||||
single-indexed containers.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="multi_index_cont_example.png"
|
||||
alt="diagram of a multi_index_container with three indices"
|
||||
width="600" height="304"><br>
|
||||
<b>Fig. 1: Diagram of a <code>multi_index_container</code> with three indices.</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The figure above depicts a <code>multi_index_container</code> composed of three indices:
|
||||
the first two present a set-like interface to the elements sorted by
|
||||
shape and id, respectively, while the latter index provides the functionality
|
||||
of a bidirectional list in the spirit of <code>std::list</code>. These
|
||||
indices act as "views" to the internal collection of elements, but they do not only
|
||||
provide read access to the set: insertion/deletion methods are also implemented much
|
||||
as those of <code>std::set</code>s or <code>std::list</code>s. Insertion of an
|
||||
element through one given index will only succeed if the uniqueness constraints of all
|
||||
indices are met.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a name="namespace">Namespace</a>
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
All the types of Boost.MultiIndex reside in namespace <code>::boost::multi_index</code>.
|
||||
Additionaly, the main class template <code>multi_index_container</code> and global functions
|
||||
<code>get</code> and <code>project</code> are lifted to namespace <code>::boost</code>
|
||||
by means of <code>using</code> declarations. For brevity of exposition, the fragments
|
||||
of code in the documentation are written as if the following declarations were in effect:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>;</span>
|
||||
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h2><a name="intro">Introduction</a></h2>
|
||||
|
||||
<p>
|
||||
@@ -141,13 +72,13 @@ We introduce the main concepts of Boost.MultiIndex through the study of
|
||||
two typical use cases.
|
||||
</p>
|
||||
|
||||
<h3><a name="multipe_sort">Multiple sorts on a single set</a></h3>
|
||||
<h3><a name="multiple_sort">Multiple sorts on a single set</a></h3>
|
||||
|
||||
<p>
|
||||
STL sets and multisets are varying-length containers where elements are efficiently
|
||||
sorted according to a given comparison predicate. These container classes fall short
|
||||
of functionality when the programmer wishes to efficiently sort and look up the elements
|
||||
following a different sorting criterium. Consider for instance:
|
||||
following a different sorting criterion. Consider for instance:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
@@ -192,6 +123,11 @@ thus can be solved with Boost.MultiIndex as follows:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
|
||||
<span class=comment>// define a multiply indexed set with indices by id and name</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
@@ -217,12 +153,13 @@ thus can be solved with Boost.MultiIndex as follows:
|
||||
|
||||
<p>
|
||||
Instead of a single comparison predicate type, as it happens for STL associative
|
||||
containers, <code>multi_index_container</code> is passed a <i>typelist</i> of index
|
||||
containers, <code>multi_index_container</code> is passed a
|
||||
<a href="../reference/multi_index_container.html#multi_index_container">list</a> of index
|
||||
specifications (<code>indexed_by</code>), each one inducing the corresponding index.
|
||||
Indices are accessed via
|
||||
<a href="reference/multi_index_container.html#index_retrieval"><code>get</code></a><code><N>()</code>
|
||||
<a href="../reference/multi_index_container.html#index_retrieval"><code>get</code></a><code><N>()</code>
|
||||
where <i>N</i> ranges between 0 and the number of comparison
|
||||
predicates minus one. The functionality of index #0 can be accessed directly from an
|
||||
predicates minus one. The functionality of index #0 can be accessed directly from a
|
||||
<code>multi_index_container</code> object without using <code>get<0>()</code>: for instance,
|
||||
<code>es.begin()</code> is equivalent to <code>es.get<0>().begin()</code>.
|
||||
</p>
|
||||
@@ -302,6 +239,11 @@ does precisely this through the combination of sequenced and ordered indices:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>sequenced_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
|
||||
<span class=comment>// define a multi_index_container with a list-like index and an ordered index</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
|
||||
@@ -363,7 +305,7 @@ complexity. The programmer can use index #0 for accessing the text as with
|
||||
|
||||
<p>
|
||||
The indices of a <code>multi_index_container</code> instantiation are specified by
|
||||
means of the <a href="reference/indices.html#indexed_by">
|
||||
means of the <a href="../reference/indices.html#indexed_by">
|
||||
<code>indexed_by</code></a> construct. For instance, the instantiation
|
||||
</p>
|
||||
|
||||
@@ -397,7 +339,7 @@ we specifiy two indices, the first of <a href="#seq_indices">sequenced type</a>,
|
||||
the second a non-unique <a href="#ord_indices">ordered index</a>. In general, we
|
||||
can specify an arbitrary number of indices: each of the arguments of
|
||||
<code>indexed_by</code> is called an
|
||||
<a href="reference/indices.html#index_specification"><i>index specifier</i></a>.
|
||||
<a href="../reference/indices.html#index_specification"><i>index specifier</i></a>.
|
||||
Depending on the type of index being specified, the corresponding specifier
|
||||
will need additional information: for instance, the specifiers <code>ordered_unique</code>
|
||||
and <code>ordered_non_unique</code> are provided with a
|
||||
@@ -455,9 +397,9 @@ first parameter of the corresponding index specifier. The following is a revised
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Tags have to be passed inside the <code>tag</code> construct. Any type can be
|
||||
used as a tag for an index, although in general one will choose names that are
|
||||
descriptive of the index they are associated with. The tagging mechanism allows
|
||||
Tags have to be passed inside the <a href="../reference/indices.html#tag"><code>tag</code></a>
|
||||
construct. Any type can be used as a tag for an index, although in general one will choose
|
||||
names that are descriptive of the index they are associated with. The tagging mechanism allows
|
||||
us to write expressions like</p>
|
||||
|
||||
<blockquote><pre>
|
||||
@@ -507,6 +449,31 @@ in the previous example can be rewritten to hold two different tags
|
||||
<span class=special>></span> <span class=identifier>employee_set</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h2><a name="iterator_access">Iterator access</a></h2>
|
||||
|
||||
<p>
|
||||
Each index of a <code>multi_index_container</code> uses its own
|
||||
iterator types, which are different from those of another indices. As is
|
||||
the rule with STL containers, these iterators are defined as nested
|
||||
types of the index:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>1</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span>
|
||||
<span class=identifier>es</span><span class=special>.</span><span class=identifier>get</span><span class=special><</span><span class=number>1</span><span class=special>>().</span><span class=identifier>find</span><span class=special>(</span><span class=string>"Judy Smith"</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
This kind of expressions can be rendered more readable by
|
||||
means of user-defined <code>typedef</code>s:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>1</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>employee_set_by_name</span><span class=special>;</span>
|
||||
<span class=identifier>employee_set_by_name</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span>
|
||||
<span class=identifier>es</span><span class=special>.</span><span class=identifier>get</span><span class=special><</span><span class=number>1</span><span class=special>>().</span><span class=identifier>find</span><span class=special>(</span><span class=string>"Judy Smith"</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h2>
|
||||
<a name="index_types">Index types</a>
|
||||
</h2>
|
||||
@@ -518,19 +485,22 @@ Currently, Boost.MultiIndex provides the following index types:
|
||||
provide a similar interface. There are <i>unique</i> and <i>non-unique</i>
|
||||
variants: the former do not allow for duplicates, while the latter permit
|
||||
them (like <code>std::multiset</code>.)</li>
|
||||
<li>Sequenced indices are modeled after the semantics and interface of
|
||||
<code>std::list</code>: they arrange the elements as if in a bidirectional
|
||||
list.</li>
|
||||
<li>Hashed indices provide fast access to the elements through hashing
|
||||
tecnhiques, in a similar way as non-standard <code>hash_set</code>s provided
|
||||
by some vendors. Recently, <i>unordered associative containers</i> have been
|
||||
proposed as part of an extension of the C++ standard library known
|
||||
in the standardization commitee as TR1. Hashed indices closely model this
|
||||
proposal.</li>
|
||||
<li>Sequenced indices are modeled after the semantics and interface of
|
||||
<code>std::list</code>: they arrange the elements as if in a bidirectional
|
||||
list.</li>
|
||||
<li>Random access indices provide an interface similar to that of
|
||||
sequenced indices, and additionally feature random access iterators
|
||||
and positional access to the elements.</li>
|
||||
</ul>
|
||||
The examples in the <a href="#intro">introduction</a> exercise ordered and sequenced
|
||||
indices, which are the most commonly used; hashed indices are presented in the
|
||||
<a href="advanced_topics.html#hashed_indices">advanced topics</a> section.
|
||||
indices, which are the most commonly used; the other kinds of indices are presented
|
||||
in the <a href="indices.html">index types</a> section of the tutorial.
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
@@ -654,13 +624,13 @@ the sorting is performed. In most cases, one of the following two situations ari
|
||||
<ul>
|
||||
<li>The whole element serves as the key, as is the case of the first index
|
||||
in <code>employee_set</code>. The predefined
|
||||
<a href="reference/key_extraction.html#identity"><code>identity</code></a> predicate
|
||||
<a href="key_extraction.html#identity"><code>identity</code></a> predicate
|
||||
can be used here as a key extractor; <code>identity</code> returns as the key the
|
||||
same object passed as argument.</li>
|
||||
<li>The comparison is performed on a particular data member of the element; this
|
||||
closely follows the specification of indices on a column of a table in relational
|
||||
databases. Boost.MultiIndex provides
|
||||
<a href="reference/key_extraction.html#member"><code>member</code></a>, which returns
|
||||
<a href="key_extraction.html#member"><code>member</code></a>, which returns
|
||||
as the key a member of the element specified by a given pointer.</li>
|
||||
</ul>
|
||||
As an example, consider again the definition of <code>employee_set</code>. The
|
||||
@@ -688,78 +658,11 @@ we use <code>member</code> to extract the <code>name</code> part of the
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Another common situation arises when the sorting is performed on the result
|
||||
of a particular member function. This resembles the notion of
|
||||
<i>calculated indices</i> supported by some relational databases.
|
||||
In these cases, the key is not a data member of the element, but rather it is
|
||||
a value returned by a particular member function. Boost.MultiIndex supports this
|
||||
kind of key extraction through
|
||||
<a href="reference/key_extraction.html#const_mem_fun"><code>const_mem_fun</code></a>.
|
||||
Consider the following extension of our example where sorting on the third index
|
||||
is based upon the length of the name field:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>struct</span> <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=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
|
||||
|
||||
<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>&</span> <span class=identifier>name</span><span class=special>):</span><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=keyword>bool</span> <span class=keyword>operator</span><span class=special><(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&</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><</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
|
||||
|
||||
<span class=comment>// returns the length of the name field</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>name_length</span><span class=special>()</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>name</span><span class=special>.</span><span class=identifier>size</span><span class=special>();}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=comment>// sort by employee::operator<</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>employee</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<string> on name</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<int> on name_length()</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span>
|
||||
<span class=identifier>const_mem_fun</span><span class=special><</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span><span class=special>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name_length</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_set</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p><a href="examples.html#example2">Example 2</a> in the examples section
|
||||
provides a complete program showing how to use <code>const_mem_fun</code>.
|
||||
Almost always you will want to use a <code>const</code> member function,
|
||||
since elements in a <code>multi_index_container</code> are treated as constant, much
|
||||
as elements of an <code>std::set</code>. However, a
|
||||
<a href="reference/key_extraction.html#mem_fun"><code>mem_fun</code></a>
|
||||
counterpart is provided for use with non-constant member functions, whose
|
||||
applicability is discussed on the paragraph on
|
||||
<a href="advanced_topics.html#advanced_key_extractors">advanced features
|
||||
of Boost.MultiIndex key extractors</a> in the advanced topics section.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
More complex scenarios may require the use of
|
||||
<i>composite keys</i> combining the results of several key extractors.
|
||||
Composite keys are supported by Boost.MultiIndex through the
|
||||
<a href="advanced_topics.html#composite_keys"><code>composite_key</code></a>
|
||||
construct.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>identity</code>, <code>member</code> and <code>const_mem_fun</code>
|
||||
(occasionally combined with <code>composite_key</code>) serve
|
||||
most common situations in the design of a <code>multi_index_container</code>. However, the
|
||||
user is free to provide her own key extractors in more exotic situations, as long as
|
||||
these conform to the <a href="reference/key_extraction.html#key_extractors"><code>Key
|
||||
Extractor</code></a> concept. For instance,
|
||||
<a href="examples.html#example6">example 6</a> implements several key
|
||||
extraction techniques called for when elements and/or keys are accessed via
|
||||
pointers.
|
||||
Apart from <code>identity</code> and <code>member</code>, Boost.MultiIndex provides
|
||||
several other predefined key extractors and powerful ways to combine them.
|
||||
Key extractors can also be defined by the user.
|
||||
Consult the <a href="key_extraction.html">key extraction section</a> of
|
||||
the tutorial for a more detailed exposition of this topic.
|
||||
</p>
|
||||
|
||||
<h4><a name="comparison_predicates">Comparison predicates</a></h4>
|
||||
@@ -848,7 +751,7 @@ comparison predicate
|
||||
Here we are not only passing IDs instead of <code>employee</code> objects:
|
||||
an alternative comparison predicate is passed as well. In general, lookup operations
|
||||
of ordered indices are overloaded to accept
|
||||
<a href="reference/ord_indices.html#set_operations"><i>compatible sorting
|
||||
<a href="../reference/ord_indices.html#set_operations"><i>compatible sorting
|
||||
criteria</i></a>. The somewhat cumbersone definition of compatibility in this context
|
||||
is given in the reference, but roughly speaking we say that a comparison predicate
|
||||
<code>C1</code> is compatible with <code>C2</code> if any sequence sorted by
|
||||
@@ -923,9 +826,9 @@ and error prone task.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="reference/ord_indices.html#range_operations"><code>range</code></a>
|
||||
The <a href="../reference/ord_indices.html#range_operations"><code>range</code></a>
|
||||
member function, often in combination with
|
||||
<a href="../../../libs/lambda/index.html">Boost.Lambda</a> expressions, can
|
||||
<a href="../../../../libs/lambda/index.html">Boost.Lambda</a> expressions, can
|
||||
greatly help alleviate this situation:
|
||||
</p>
|
||||
|
||||
@@ -961,7 +864,7 @@ One or both bounds can be omitted with the special <code>unbounded</code> marker
|
||||
<h4><a name="ord_updating">Updating</a></h4>
|
||||
|
||||
<p>
|
||||
The <a href="reference/ord_indices.html#replace"><code>replace</code></a> member function
|
||||
The <a href="../reference/ord_indices.html#replace"><code>replace</code></a> member function
|
||||
performs in-place replacement of a given element as the following example shows:
|
||||
</p>
|
||||
|
||||
@@ -997,7 +900,7 @@ the updating (when retrieving it and inside <code>replace</code>). If elements
|
||||
are expensive to copy, this may be quite a computational cost for the modification
|
||||
of just a tiny part of the object. To cope with this situation, Boost.MultiIndex
|
||||
provides an alternative updating mechanism called
|
||||
<a href="reference/ord_indices.html#modify"><code>modify</code></a>:
|
||||
<a href="../reference/ord_indices.html#modify"><code>modify</code></a>:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
@@ -1034,18 +937,69 @@ original value is kept and the method returns without altering the container, bu
|
||||
leaves no trace of the previous value of the element. Integrity constraints
|
||||
thus lead to the following policy: when a collision happens in the
|
||||
process of calling <code>modify</code>, the element is erased and the method returns
|
||||
<code>false</code>. This difference in behavior between <code>replace</code> and
|
||||
<code>modify</code> has to be considered by the programmer on a case-by-case basis.
|
||||
<code>false</code>. There is a further version of <code>modify</code> which
|
||||
accepts a <i>rollback</i> functor to undo the changes in case of collision:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>struct</span> <span class=identifier>change_id</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>change_id</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>new_id</span><span class=special>):</span><span class=identifier>new_id</span><span class=special>(</span><span class=identifier>new_id</span><span class=special>){}</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>employee</span><span class=special>&</span> <span class=identifier>e</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>=</span><span class=identifier>new_id</span><span class=special>;</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>private</span><span class=special>:</span>
|
||||
<span class=keyword>int</span> <span class=identifier>new_id</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
<span class=special>...</span>
|
||||
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=...</span>
|
||||
|
||||
<span class=keyword>int</span> <span class=identifier>old_id</span><span class=special>=</span><span class=identifier>it</span><span class=special>-></span><span class=identifier>id</span><span class=special>;</span> <span class=comment>// keep the original id
|
||||
|
||||
// try to modify the id, restore it in case of collisions</span>
|
||||
<span class=identifier>es</span><span class=special>.</span><span class=identifier>modify</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>change_id</span><span class=special>(</span><span class=number>321</span><span class=special>),</span><span class=identifier>change_id</span><span class=special>(</span><span class=identifier>old_id</span><span class=special>));</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>In the example, <code>change_id(old_id)</code> is invoked to restore the original
|
||||
conditions when the modification results in collisions with some other element.
|
||||
The differences in behavior between <code>replace</code>, <code>modify</code> and
|
||||
<code>modify</code> with rollback have to be considered by the programmer on a
|
||||
case-by-case basis to determine the best updating mechanism.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<caption><b>Behavior of the different updating mechanisms.</b></caption>
|
||||
<tr>
|
||||
<th align="center">updating function</th>
|
||||
<th>If there is a collision...</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><code>replace(it,x)</code></td>
|
||||
<td>replacement does not take place.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td align="center"><code>modify(it,mod)</code></td>
|
||||
<td>the element is erased.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><code>modify(it,mod,back)</code></td>
|
||||
<td><code>back</code> is used to restore the original conditions.
|
||||
(If <code>back</code> throws, the element is erased.)
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
A key-based version of <code>modify</code>, named
|
||||
<a href="reference/ord_indices.html#modify_key"><code>modify_key</code></a>, is
|
||||
provided as well. In this case, the modifying functor is passed a reference to
|
||||
the <code>key_value</code> part of the element instead of the whole object. Note
|
||||
that <code>modify_key</code> cannot be used for key extractors which return calculated
|
||||
values instead of references to data members of the elements, such
|
||||
as <code>const_mem_fun</code>.
|
||||
Key-based versions of <code>modify</code>, named
|
||||
<a href="../reference/ord_indices.html#modify_key"><code>modify_key</code></a>, are
|
||||
provided as well. In this case, the modifying functors are passed a reference to
|
||||
the <code>key_type</code> part of the element instead of the whole object.
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
@@ -1071,10 +1025,10 @@ as <code>const_mem_fun</code>.
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Just as <code>modify</code> does, <code>modify_key</code> erases the element if
|
||||
the modification results in collisions in some index. <code>modify</code> and
|
||||
Like <code>modify</code>, there are versions of <code>modify_key</code> with and
|
||||
without rollback. <code>modify</code> and
|
||||
<code>modify_key</code> are particularly well suited to use in conjunction to
|
||||
<a href="../../../libs/lambda/index.html">Boost.Lambda</a>
|
||||
<a href="../../../../libs/lambda/index.html">Boost.Lambda</a>
|
||||
for defining the modifying functors:
|
||||
</p>
|
||||
|
||||
@@ -1088,6 +1042,13 @@ for defining the modifying functors:
|
||||
<span class=identifier>name_index</span><span class=special>.</span><span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>_1</span><span class=special>=</span><span class=string>"Anna Smith"</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>modify_key</code> requires that the key extractor be of
|
||||
a special type called
|
||||
<a href="key_extraction.html#read_write_key_extractors">read/write</a>:
|
||||
this is usually, but not always, the case.
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
<a name="seq_indices">Sequenced indices</a>
|
||||
</h3>
|
||||
@@ -1108,10 +1069,10 @@ indices with respect to <code>std::list</code>s, namely that elements of an
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>s</span><span class=special>;</span> <span class=comment>// list-like container</span>
|
||||
<span class=special>></span> <span class=identifier>s</span><span class=special>;</span> <span class=comment>// list-like container</span>
|
||||
|
||||
<span class=identifier>s</span><span class=special>.</span><span class=identifier>push_front</span><span class=special>(</span><span class=number>0</span><span class=special>);</span>
|
||||
<span class=special>*(</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>begin</span><span class=special>())==</span><span class=number>1</span><span class=special>;</span> <span class=comment>// ERROR: the element cannot be changed</span>
|
||||
<span class=special>*(</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>begin</span><span class=special>())=</span><span class=number>1</span><span class=special>;</span> <span class=comment>// ERROR: the element cannot be changed</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
@@ -1178,15 +1139,15 @@ do not always coincide with those of the standard container. Differences
|
||||
result mainly from the fact that insertions into a sequenced index are not
|
||||
guaranteed to succeed, due to the possible banning by other indices
|
||||
of the <code>multi_index_container</code>. Consult the
|
||||
<a href="reference/seq_indices.html">reference</a> for further details.
|
||||
<a href="../reference/seq_indices.html">reference</a> for further details.
|
||||
</p>
|
||||
|
||||
<h4><a name="seq_updating">Updating</a></h4>
|
||||
|
||||
<p>
|
||||
Like ordered indices, sequenced indices provide
|
||||
<a href="reference/seq_indices.html#replace"><code>replace</code></a> and
|
||||
<a href="reference/seq_indices.html#modify"><code>modify</code></a>
|
||||
<a href="../reference/seq_indices.html#replace"><code>replace</code></a> and
|
||||
<a href="../reference/seq_indices.html#modify"><code>modify</code></a>
|
||||
operations, with identical functionality. There is however no analogous
|
||||
<code>modify_key</code>, since sequenced indices are not key-based.
|
||||
</p>
|
||||
@@ -1195,7 +1156,7 @@ operations, with identical functionality. There is however no analogous
|
||||
|
||||
<p>
|
||||
Given indices <code>i1</code> and <code>i2</code> on the same <code>multi_index_container</code>,
|
||||
<a href="reference/multi_index_container.html#projection"><code>project</code></a> can be used to
|
||||
<a href="../reference/multi_index_container.html#projection"><code>project</code></a> can be used to
|
||||
retrieve an <code>i2</code>-iterator from an <code>i1</code>-iterator, both of them
|
||||
pointing to the same element of the container. This functionality allows the programmer to
|
||||
move between different indices of the same <code>multi_index_container</code> when performing
|
||||
@@ -1228,7 +1189,7 @@ A slightly more interesting example:
|
||||
|
||||
<span class=comment>// prepend "older" to all occurrences of "sister"</span>
|
||||
|
||||
<span class=identifier>text_container</span><span class=special>::</span><span class=identifier>nth_index_iterator</span><span class=special><</span><span class=number>1</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>it1</span><span class=special>=</span>
|
||||
<span class=identifier>text_container</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>1</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it1</span><span class=special>=</span>
|
||||
<span class=identifier>sorted_index</span><span class=special>.</span><span class=identifier>lower_bound</span><span class=special>(</span><span class=string>"sister"</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>while</span><span class=special>(</span><span class=identifier>it1</span><span class=special>!=</span><span class=identifier>sorted_index</span><span class=special>.</span><span class=identifier>end</span><span class=special>()&&*</span><span class=identifier>it1</span><span class=special>==</span><span class=string>"sister"</span><span class=special>){</span>
|
||||
@@ -1257,33 +1218,33 @@ is preserved in the face of insertions, even for replace and modify operations.
|
||||
Appropriate instantiations of <code>multi_index_container</code> can in fact simulate
|
||||
<code>std::set</code>, <code>std::multiset</code> and (with more limitations)
|
||||
<code>std::list</code>, as shown in the
|
||||
<a href="advanced_topics.html#simulate_std_containers">advanced topics</a>
|
||||
<a href="techniques.html#emulate_std_containers">techniques</a>
|
||||
section. These simulations are as nearly as efficient as the original STL
|
||||
containers; consult the <a href="reference/index.html">reference</a> for further
|
||||
containers; consult the <a href="../reference/index.html">reference</a> for further
|
||||
information on complexity guarantees and the
|
||||
<a href="performance.html">performance section</a> for practical measurements of
|
||||
<a href="../performance.html">performance section</a> for practical measurements of
|
||||
efficiency.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="index.html"><img src="prev.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="tutorial" border="0"><br>
|
||||
Boost.MultiIndex Tutorial
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="advanced_topics.html"><img src="next.gif" alt="advanced topics" border="0"><br>
|
||||
Advanced topics
|
||||
<div class="next_link"><a href="indices.html"><img src="../next.gif" alt="index types" border="0"><br>
|
||||
Index types
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised March 31st 2005</p>
|
||||
<p>Revised November 7th 2008</p>
|
||||
|
||||
<p>© Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2008 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
@@ -0,0 +1,353 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Tutorial - Container creation</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="key_extraction.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="debug.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Container creation</h1>
|
||||
|
||||
<div class="prev_link"><a href="key_extraction.html"><img src="../prev.gif" alt="key extraction" border="0"><br>
|
||||
Key extraction
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="debug.html"><img src="../next.gif" alt="debugging support" border="0"><br>
|
||||
Debugging support
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#value_semantics">Value semantics</a></li>
|
||||
<li><a href="#ctor_args_list">Use of <code>ctor_args_list</code></a></li>
|
||||
<li><a href="#special_allocator">Special allocator support</a></li>
|
||||
<li><a href="#serialization">Serialization</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="value_semantics">Value semantics</a></h2>
|
||||
|
||||
<p>
|
||||
<code>multi_index_container</code>s have the usual value semantics associated
|
||||
to copy construction and assignment, i.e. copies of the elements from the source
|
||||
container are created and inserted into the destination container.
|
||||
More interestingly, copying also recreates the original order in which
|
||||
elements are arranged for <i>every index</i> of the container.
|
||||
This implies that equality of all indices is preserved under copying
|
||||
or assignment, for those index types where equality is defined. This behavior
|
||||
can be regarded as a natural extension to the general rule on copy semantics
|
||||
stating that if <code>y</code> is a copy of <code>x</code>, then
|
||||
<code>y==x</code>.
|
||||
</p>
|
||||
|
||||
<h2><a name="ctor_args_list">Use of <code>ctor_args_list</code></a></h2>
|
||||
|
||||
<p>
|
||||
Although in most cases <code>multi_index_container</code>s will be default constructed
|
||||
(or copied from a preexisting <code>multi_index_container</code>), sometimes it is
|
||||
necessary to specify particular values for the internal objects used (key extractors,
|
||||
comparison predicates, allocator), for instance if some of these objects do not have
|
||||
a default constructor. The same situation can arise with standard STL containers,
|
||||
which allow for the optional specification of such objects:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// example of non-default constructed std::set</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>IntegralType</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>modulo_less</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>modulo_less</span><span class=special>(</span><span class=identifier>IntegralType</span> <span class=identifier>m</span><span class=special>):</span><span class=identifier>modulo</span><span class=special>(</span><span class=identifier>m</span><span class=special>){}</span>
|
||||
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>IntegralType</span> <span class=identifier>x</span><span class=special>,</span><span class=identifier>IntegralType</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=special>(</span><span class=identifier>x</span><span class=special>%</span><span class=identifier>modulo</span><span class=special>)<(</span><span class=identifier>y</span><span class=special>%</span><span class=identifier>modulo</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>private</span><span class=special>:</span>
|
||||
<span class=identifier>IntegralType</span> <span class=identifier>modulo</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>,</span><span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>></span> <span class=identifier>modulo_set</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>modulo_set</span> <span class=identifier>m</span><span class=special>(</span><span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>(</span><span class=number>10</span><span class=special>));</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>multi_index_container</code> does also provide this functionality, though in a
|
||||
considerably more complex fashion, due to the fact that the constructor
|
||||
of a <code>multi_index_container</code> has to accept values for all the internal
|
||||
objects of its indices. The full form of <code>multi_index_container</code> constructor
|
||||
is
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>explicit</span> <span class=identifier>multi_index_container</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>ctor_args_list</span><span class=special>&</span> <span class=identifier>args_list</span><span class=special>=</span><span class=identifier>ctor_args_list</span><span class=special>(),</span>
|
||||
<span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&</span> <span class=identifier>al</span><span class=special>=</span><span class=identifier>allocator_type</span><span class=special>());</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The specification of the allocator object poses no particular problems;
|
||||
as for the <code>ctor_args_list</code>, this object is designed so as to hold
|
||||
the necessary construction values for every index in the <code>multi_index_container</code>.
|
||||
From the point of view of the user, <code>ctor_args_list</code> is equivalent
|
||||
to the type
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special><</span><span class=identifier>C<sub>0</sub></span><span class=special>,...,</span><span class=identifier>C<sub>I-1</sub></span><span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
where <code>I</code> is the number of indices, and <code>C<sub>i</sub></code> is
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>nth_index</span><span class=special><</span><span class=identifier>i</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>ctor_args</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
that is, the nested type <code>ctor_args</code> of the <code>i</code>-th index. Each
|
||||
<code>ctor_args</code> type is in turn a tuple holding values for constructor
|
||||
arguments of the associated index: so, ordered indices demand a key extractor object
|
||||
and a comparison predicate, hashed indices take an initial number of buckets,
|
||||
a key extractor, a hash function and an equality predicate; while sequenced
|
||||
and random access indices do not need any construction argument. For instance,
|
||||
given the definition
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>hashed_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>,</span> <span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>sequenced</span><span class=special><>,</span>
|
||||
<span class=identifier>random_access</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>modulo_indexed_set</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
the corresponding <code>ctor_args_list</code> type is equivalent to
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special><</span>
|
||||
<span class=comment>// ctr_args of index #0</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special><</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span><span class=special>,</span> <span class=comment>// initial number of buckets; 0 if unspecified</span>
|
||||
<span class=identifier>identity</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>,</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>,</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// ctr_args of index #1</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special><</span>
|
||||
<span class=identifier>identity</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>,</span>
|
||||
<span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sequenced indices do not have any construction argument</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special><>,</span>
|
||||
|
||||
<span class=comment>// neither do random access indices</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Such a <code>modulo_indexed_set</code> cannot be default constructed, because
|
||||
<code>modulo_less</code> does not provide a default constructor. The following shows
|
||||
how the construction can be done:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>modulo_indexed_set</span><span class=special>::</span><span class=identifier>ctor_args_list</span> <span class=identifier>args_list</span><span class=special>=</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span>
|
||||
<span class=comment>// ctor_args for index #0 is default constructible</span>
|
||||
<span class=identifier>modulo_indexed_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>0</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>ctor_args</span><span class=special>(),</span>
|
||||
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>(),</span><span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>(</span><span class=number>10</span><span class=special>)),</span>
|
||||
|
||||
<span class=comment>// these are also default constructible (actually, empty tuples)</span>
|
||||
<span class=identifier>modulo_indexed_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>2</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>ctor_args</span><span class=special>(),</span>
|
||||
<span class=identifier>modulo_indexed_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>3</span><span class=special>>::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>ctor_args</span><span class=special>()</span>
|
||||
<span class=special>);</span>
|
||||
|
||||
<span class=identifier>modulo_indexed_set</span> <span class=identifier>m</span><span class=special>(</span><span class=identifier>args_list</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
A program is provided in the <a href="../examples.html#example3">examples section</a> that
|
||||
puts in practise these concepts.
|
||||
</p>
|
||||
|
||||
<h2><a name="special_allocator">Special allocator support</a></h2>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex allows for a slightly more general class of allocators
|
||||
than strictly required by the C++ standard, as explained in detail in the
|
||||
<a href="../reference/multi_index_container.html#instantiation_types">reference</a>.
|
||||
An important type of non-standard allocators supported are those provided by the
|
||||
<a href="../../../interprocess/index.html">Boost Interprocess Library</a>;
|
||||
this opens up the possibility of placing <code>multi_index_container</code>s
|
||||
in shared memory.
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>interprocess</span><span class=special>/</span><span class=identifier>allocators</span><span class=special>/</span><span class=identifier>allocator</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>interprocess</span><span class=special>/</span><span class=identifier>managed_shared_memory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
|
||||
<span class=keyword>namespace</span> <span class=identifier>bip</span><span class=special>=</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>interprocess</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// a shared memory compatible allocator of ints</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>bip</span><span class=special>::</span><span class=identifier>allocator</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span><span class=identifier>bip</span><span class=special>::</span><span class=identifier>managed_shared_memory</span><span class=special>::</span><span class=identifier>segment_manager</span>
|
||||
<span class=special>></span> <span class=identifier>shared_int_allocator</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// define a shared memory compatible multi_index_container
|
||||
// using shared_int_allocator</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>sequenced</span><span class=special><>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>shared_int_allocator</span>
|
||||
<span class=special>></span> <span class=identifier>unique_int_list</span><span class=special>;</span>
|
||||
|
||||
<span class=special>...</span>
|
||||
|
||||
<span class=comment>// create a managed memory segment</span>
|
||||
<span class=identifier>bip</span><span class=special>::</span><span class=identifier>managed_shared_memory</span> <span class=identifier>seg</span><span class=special>(</span>
|
||||
<span class=identifier>bip</span><span class=special>::</span><span class=identifier>create_only</span><span class=special>,</span><span class=string>"SharedMemoryID"</span><span class=special>,</span><span class=number>65536</span><span class=special>);</span>
|
||||
|
||||
<span class=comment>// construct a unique_int_list into the segment</span>
|
||||
<span class=identifier>unique_int_list</span><span class=special>*</span> <span class=identifier>puil</span><span class=special>=</span><span class=identifier>seg</span><span class=special>.</span><span class=identifier>construct</span><span class=special><</span><span class=identifier>unique_int_list</span><span class=special>></span>
|
||||
<span class=special>(</span><span class=string>"UniqueIntListID"</span><span class=special>)</span> <span class=comment>// object identifier within the segment
|
||||
// Construction args: first a ctor arg list, then a
|
||||
// shared memory allocator obtained from the segment object.</span>
|
||||
<span class=special>(</span><span class=identifier>unique_int_list</span><span class=special>::</span><span class=identifier>ctor_args_list</span><span class=special>(),</span>
|
||||
<span class=identifier>unique_int_list</span><span class=special>::</span><span class=identifier>allocator_type</span><span class=special>(</span><span class=identifier>seg</span><span class=special>.</span><span class=identifier>get_segment_manager</span><span class=special>()));</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The examples section includes a <a href="../examples.html#example12">program</a>
|
||||
that further explores this capability.
|
||||
</p>
|
||||
|
||||
<h2><a name="serialization">Serialization</a></h2>
|
||||
|
||||
<p>
|
||||
<code>multi_index_container</code>s can be archived and retrieved by means of the
|
||||
<a href="../../../serialization/index.html">Boost Serialization Library</a>. Both regular
|
||||
and XML archives are supported. The usage is straightforward and does not
|
||||
differ from that of any other serializable type. For instance:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>archive</span><span class=special>/</span><span class=identifier>text_oarchive</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>archive</span><span class=special>/</span><span class=identifier>text_iarchive</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>fstream</span><span class=special>></span>
|
||||
|
||||
<span class=special>...</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>save</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>employee_set</span><span class=special>&</span> <span class=identifier>es</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>ofstream</span> <span class=identifier>ofs</span><span class=special>(</span><span class=string>"data"</span><span class=special>);</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>archive</span><span class=special>::</span><span class=identifier>text_oarchive</span> <span class=identifier>oa</span><span class=special>(</span><span class=identifier>ofs</span><span class=special>);</span>
|
||||
<span class=identifier>oa</span><span class=special><<</span><span class=identifier>es</span><span class=special>;</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>load</span><span class=special>(</span><span class=identifier>employee_set</span><span class=special>&</span> <span class=identifier>es</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>ifstream</span> <span class=identifier>ifs</span><span class=special>(</span><span class=string>"data"</span><span class=special>);</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>archive</span><span class=special>::</span><span class=identifier>text_iarchive</span> <span class=identifier>ia</span><span class=special>(</span><span class=identifier>ifs</span><span class=special>);</span>
|
||||
<span class=identifier>ia</span><span class=special>>></span><span class=identifier>es</span><span class=special>;</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=special>...</span>
|
||||
|
||||
<span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
|
||||
<span class=special>...</span> <span class=comment>// fill it with data</span>
|
||||
<span class=identifier>save</span><span class=special>(</span><span class=identifier>es</span><span class=special>);</span>
|
||||
|
||||
<span class=special>...</span>
|
||||
|
||||
<span class=identifier>employee_set</span> <span class=identifier>restored_es</span><span class=special>;</span>
|
||||
<span class=identifier>load</span><span class=special>(</span><span class=identifier>restored_es</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Serialization capabilities are automatically provided by just linking with
|
||||
the appropriate Boost.Serialization library module: it is not necessary
|
||||
to explicitly include any header from Boost.Serialization,
|
||||
apart from those declaring the type of archive used in the process. If not used,
|
||||
however, serialization support can be disabled by globally defining the macro
|
||||
<code>BOOST_MULTI_INDEX_DISABLE_SERIALIZATION</code>. Disabling serialization
|
||||
for Boost.MultiIndex can yield a small improvement in build times, and may
|
||||
be necessary in those defective compilers that fail to correctly process
|
||||
Boost.Serialization headers.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In accordance with Boost.MultiIndex
|
||||
<a href="#value_semantics">value semantics</a>, retrieving an
|
||||
archived <code>multi_index_container</code> restores not only
|
||||
the elements, but also the order they were arranged into for
|
||||
every index of the container. There is an exception to this rule,
|
||||
though: for <a href="indices.html#hashed_indices">hashed
|
||||
indices</a>, no guarantee is made about the order in which elements will
|
||||
be iterated in the restored container; in general, it is unwise to rely on
|
||||
the ordering of elements of a hashed index, since it can change in arbitrary
|
||||
ways during insertion or rehashing --this is precisely the reason why
|
||||
hashed indices and TR1 unordered associative containers do not define
|
||||
an equality operator.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Iterators to indices of a <code>multi_index_container</code> can also be
|
||||
serialized. Serialization of iterators must be done only after serializing
|
||||
their corresponding container.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="../examples.html#example9">Example 9</a> in the examples section shows
|
||||
the serialization capabilities of Boost.MultiIndex.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="key_extraction.html"><img src="../prev.gif" alt="key extraction" border="0"><br>
|
||||
Key extraction
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="debug.html"><img src="../next.gif" alt="debugging support" border="0"><br>
|
||||
Debugging support
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised July 17th 2007</p>
|
||||
|
||||
<p>© Copyright 2003-2007 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,252 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Tutorial -Debugging support</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="creation.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="techniques.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Debugging support</h1>
|
||||
|
||||
<div class="prev_link"><a href="creation.html"><img src="../prev.gif" alt="container creation" border="0"><br>
|
||||
Container creation
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br>
|
||||
Techniques
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#debugging_support">Debugging support</a></li>
|
||||
<li><a href="#safe_mode">Safe mode</a>
|
||||
<ul>
|
||||
<li><a href="#serialization_and_safe_mode">Serialization and safe mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#invariant_check">Invariant-checking mode</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="debugging_support">Debugging support</a></h2>
|
||||
|
||||
<p>
|
||||
The concept of <i>Design by Contract</i>, originally developed as part
|
||||
of Bertrand Meyer's <a href="http://www.eiffel.com">Eiffel</a> language,
|
||||
revolves around the formulation of a <i>contract</i> between the user
|
||||
of a library and the implementor, by which the first is required to
|
||||
respect some <i>preconditions</i> on the values passed when invoking
|
||||
methods of the library, and the implementor guarantees in return
|
||||
that certain constraints on the results are met (<i>postconditions</i>),
|
||||
as well as the honoring of specified internal consistency rules, called
|
||||
<i>invariants</i>. Eiffel natively supports the three parts of the
|
||||
contract just described by means of constructs <code>require</code>,
|
||||
<code>ensure</code> and <code>invariant</code>, respectively.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
C++ does not enjoy direct support for Design by Contract techniques: these
|
||||
are customarily implemented as assertion code, often turned off in
|
||||
release mode for performance reasons. Following this approach,
|
||||
Boost.MultiIndex provides two distinct debugging modes:
|
||||
<ul>
|
||||
<li><i>Safe mode</i> checks preconditions on the invocations to the
|
||||
facilities of the library,</li>
|
||||
<li><i>invariant-checking mode</i> performs post-execution checks aimed
|
||||
at ensuring that the internal consistency of the library is preserved.</li>
|
||||
</ul>
|
||||
These two modes are independent of each other and can be set on or off
|
||||
individually. It is important to note that errors detected by safe mode are
|
||||
due in principle to faulty code in the user's program, while
|
||||
invariant-checking mode detects potential <i>internal</i> bugs in the
|
||||
implementation of Boost.MultiIndex.
|
||||
</p>
|
||||
|
||||
<h2><a name="safe_mode">Safe mode</a></h2>
|
||||
|
||||
<p>
|
||||
The idea of adding precondition checking facilities to STL as a debugging aid
|
||||
was first introduced by Cay S. Horstmann in his
|
||||
<a href="http://www.horstmann.com/safestl.html">Safe STL</a> library and later
|
||||
adopted by <a href="http://www.stlport.com/doc/debug_mode.html">STLport Debug
|
||||
Mode</a>. Similarly, Boost.MultiIndex features the so-called <i>safe mode</i>
|
||||
in which all sorts of preconditions are checked when dealing with iterators
|
||||
and functions of the library.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex safe mode is set by globally defining the macro
|
||||
<code>BOOST_MULTI_INDEX_ENABLE_SAFE_MODE</code>. Error conditions
|
||||
are checked via the macro <code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, which
|
||||
by default resolves to a call to <a href="../../../../libs/utility/assert.html">
|
||||
<code>BOOST_ASSERT</code></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If the user decides to define her own version of
|
||||
<code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, it has to take the form
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</span><span class=special>(</span><span class=identifier>expr</span><span class=special>,</span><span class=identifier>error_code</span><span class=special>)</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
where <code>expr</code> is the condition checked and <code>error_code</code>
|
||||
is one value of the <code>safe_mode::error_code</code> enumeration:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
|
||||
|
||||
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
|
||||
|
||||
<span class=keyword>namespace</span> <span class=identifier>safe_mode</span><span class=special>{</span>
|
||||
|
||||
<span class=keyword>enum</span> <span class=identifier>error_code</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>invalid_iterator</span><span class=special>,</span> <span class=comment>// vg. default cted or pointing to erased element</span>
|
||||
<span class=identifier>not_dereferenceable_iterator</span><span class=special>,</span> <span class=comment>// iterator is not dereferenceable</span>
|
||||
<span class=identifier>not_incrementable_iterator</span><span class=special>,</span> <span class=comment>// iterator points to end of sequence</span>
|
||||
<span class=identifier>not_decrementable_iterator</span><span class=special>,</span> <span class=comment>// iterator points to beginning of sequence</span>
|
||||
<span class=identifier>not_owner</span><span class=special>,</span> <span class=comment>// iterator does not belong to the container</span>
|
||||
<span class=identifier>not_same_owner</span><span class=special>,</span> <span class=comment>// iterators belong to different containers</span>
|
||||
<span class=identifier>invalid_range</span><span class=special>,</span> <span class=comment>// last not reachable from first</span>
|
||||
<span class=identifier>inside_range</span><span class=special>,</span> <span class=comment>// iterator lies within a range (and it mustn't)</span>
|
||||
<span class=identifier>out_of_bounds</span><span class=special>,</span> <span class=comment>// move attempted beyond container limits</span>
|
||||
<span class=identifier>same_container</span> <span class=comment>// containers ought to be different</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=special>}</span> <span class=comment>// namespace multi_index::safe_mode</span>
|
||||
|
||||
<span class=special>}</span> <span class=comment>// namespace multi_index</span>
|
||||
|
||||
<span class=special>}</span> <span class=comment>// namespace boost</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
For instance, the following replacement of
|
||||
<code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code> throws an exception instead of
|
||||
asserting:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>/</span><span class=identifier>safe_mode_errors</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
|
||||
<span class=keyword>struct</span> <span class=identifier>safe_mode_exception</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>safe_mode_exception</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>safe_mode</span><span class=special>::</span><span class=identifier>error_code</span> <span class=identifier>error_code</span><span class=special>):</span>
|
||||
<span class=identifier>error_code</span><span class=special>(</span><span class=identifier>error_code</span><span class=special>)</span>
|
||||
<span class=special>{}</span>
|
||||
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>safe_mode</span><span class=special>::</span><span class=identifier>error_code</span> <span class=identifier>error_code</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=preprocessor>#define</span> <span class=identifier>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</span><span class=special>(</span><span class=identifier>expr</span><span class=special>,</span><span class=identifier>error_code</span><span class=special>)</span> <span class=special>\</span>
|
||||
<span class=keyword>if</span><span class=special>(!(</span><span class=identifier>expr</span><span class=special>)){</span><span class=keyword>throw</span> <span class=identifier>safe_mode_exception</span><span class=special>(</span><span class=identifier>error_code</span><span class=special>);}</span>
|
||||
|
||||
<span class=comment>// This has to go before the inclusion of any header from Boost.MultiIndex,
|
||||
// except possibly safe_error_codes.hpp.</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Other possibilites, like outputting to a log or firing some kind of alert, are
|
||||
also implementable.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Warning:</b> Safe mode adds a very important overhead to the program
|
||||
both in terms of space and time used, so in general it should not be set for
|
||||
<code>NDEBUG</code> builds. Also, this mode is intended solely as a debugging aid,
|
||||
and programs must not rely on it as part of their normal execution flow: in
|
||||
particular, no guarantee is made that all possible precondition errors are diagnosed,
|
||||
or that the checks remain stable across different versions of the library.
|
||||
</p>
|
||||
|
||||
<h3><a name="serialization_and_safe_mode">Serialization and safe mode</a></h3>
|
||||
|
||||
<p>
|
||||
Iterators restored from an archive are not subject to safe mode checks. This is
|
||||
so because it is not possible to automatically know the associated
|
||||
<code>multi_index_container</code> of an iterator from the serialization
|
||||
information alone. However, if desired, a restored iterator can be converted to a
|
||||
checked value by using the following workaround:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
|
||||
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>1</span><span class=special>>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// restore es and it from an archive ar</span>
|
||||
<span class=identifier>ar</span><span class=special>>></span><span class=identifier>es</span><span class=special>;</span>
|
||||
<span class=identifier>ar</span><span class=special>>></span><span class=identifier>it</span><span class=special>;</span> <span class=comment>// it won't benefit from safe mode checks
|
||||
|
||||
// Turn it into a checked value by providing Boost.MultiIndex
|
||||
// with info about the associated container.
|
||||
// This statement has virtually zero cost if safe mode is turned off.</span>
|
||||
<span class=identifier>it</span><span class=special>=</span><span class=identifier>es</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=number>1</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h2><a name="invariant_check">Invariant-checking mode</a></h2>
|
||||
|
||||
<p>
|
||||
The so called <i>invariant-checking mode</i> of Boost.MultiIndex can be
|
||||
set by globally defining the macro
|
||||
<code>BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING</code>.
|
||||
When this mode is in effect, all public functions of Boost.MultiIndex
|
||||
will perform post-execution tests aimed at ensuring that the basic
|
||||
internal invariants of the data structures managed are preserved.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If an invariant test fails, Boost.MultiIndex will indicate the failure
|
||||
by means of the unary macro <code>BOOST_MULTI_INDEX_INVARIANT_ASSERT</code>.
|
||||
Unless the user provides a definition for this macro, it defaults to
|
||||
<a href="../../../../libs/utility/assert.html">
|
||||
<code>BOOST_ASSERT</code></a>. Any assertion of this kind should
|
||||
be regarded in principle as a bug in the library. Please report such
|
||||
problems, along with as much contextual information as possible, to the
|
||||
maintainer of the library.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is recommended that users of Boost.MultiIndex always set the
|
||||
invariant-checking mode in debug builds.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="creation.html"><img src="../prev.gif" alt="container creation" border="0"><br>
|
||||
Container creation
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br>
|
||||
Techniques
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised February 6th 2006</p>
|
||||
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,139 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Tutorial</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="../index.html">
|
||||
<link rel="up" href="../index.html">
|
||||
<link rel="next" href="basics.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Tutorial</h1>
|
||||
|
||||
<div class="prev_link"><a href="../index.html"><img src="../prev.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
</a></div>
|
||||
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
</a></div>
|
||||
<div class="next_link"><a href="basics.html"><img src="../next.gif" alt="basics" border="0"><br>
|
||||
Basics
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#rationale">Rationale</a></li>
|
||||
<li><a href="#namespace">Namespace</a></li>
|
||||
<li><a href="basics.html">Basics</a></li>
|
||||
<li><a href="indices.html">Index types</a></li>
|
||||
<li><a href="key_extraction.html">Key extraction</a></li>
|
||||
<li><a href="creation.html">Container creation</a></li>
|
||||
<li><a href="debug.html">Debugging support</a></li>
|
||||
<li><a href="techniques.html">Techniques</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="rationale">Rationale</a></h2>
|
||||
|
||||
<p>
|
||||
STL containers are designed around the concept that each container controls its
|
||||
own collection of elements, giving access to them in a manner specified by the
|
||||
container's type: so, an <code>std::set</code> maintains the elements ordered
|
||||
by a specified sorting criterion, <code>std::list</code> allows for free
|
||||
positioning of elements along a linear sequence, and so on.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sometimes, the necessity arises of having different access interfaces
|
||||
to the same underlying collection: for instance, some data might need to be
|
||||
sorted according to more than one comparison predicate, or a bidirectional list
|
||||
might benefit from a supplemental logarithmic lookup interface. In these
|
||||
situations, programmers typically resort to manual compositions of different
|
||||
containers, a solution that generally involves a fair amount of code
|
||||
devoted to preserve the synchronization of the different parts of
|
||||
the composition. Boost.MultiIndex allows for the specification of
|
||||
<code>multi_index_container</code>s comprised of one or more <i>indices</i> with
|
||||
different interfaces to the same collection of elements. The resulting constructs
|
||||
are conceptually cleaner than manual compositions, and often perform much better.
|
||||
An important design decision has been taken that the indices of a given
|
||||
<code>multi_index_container</code> instantiation be specified at compile time: this
|
||||
gives ample room for static type checking and code optimization.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex takes inspiration from basic concepts of indexing arising in the
|
||||
theory of relational databases, though it is not intended to provide a full-fledged
|
||||
relational database framework. <code>multi_index_container</code> integrates seamlessly
|
||||
into the STL container/algorithm design, and features some extra capabilities regarding
|
||||
lookup operations and element updating which are useful extensions even for
|
||||
single-indexed containers.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="multi_index_cont_example.png"
|
||||
alt="diagram of a multi_index_container with three indices"
|
||||
width="600" height="304"><br>
|
||||
<b>Fig. 1: Diagram of a <code>multi_index_container</code> with three indices.</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The figure above depicts a <code>multi_index_container</code> composed of three indices:
|
||||
the first two present a set-like interface to the elements sorted by
|
||||
shape and id, respectively, while the latter index provides the functionality
|
||||
of a bidirectional list in the spirit of <code>std::list</code>. These
|
||||
indices act as "views" to the internal collection of elements, but they do not only
|
||||
provide read access to the set: insertion/deletion methods are also implemented much
|
||||
as those of <code>std::set</code>s or <code>std::list</code>s. Insertion of an
|
||||
element through one given index will only succeed if the uniqueness constraints of all
|
||||
indices are met.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a name="namespace">Namespace</a>
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
All the public types of Boost.MultiIndex reside in namespace <code>::boost::multi_index</code>.
|
||||
Additionaly, the main class template <code>multi_index_container</code> and global functions
|
||||
<code>get</code> and <code>project</code> are lifted to namespace <code>::boost</code>
|
||||
by means of <code>using</code> declarations. For brevity of exposition, the fragments
|
||||
of code in the documentation are written as if the following declarations were in effect:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>;</span>
|
||||
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="../index.html"><img src="../prev.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
</a></div>
|
||||
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
|
||||
Index
|
||||
</a></div>
|
||||
<div class="next_link"><a href="basics.html"><img src="../next.gif" alt="basics" border="0"><br>
|
||||
Basics
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised February 21st 2006</p>
|
||||
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,731 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Tutorial - Index types</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="basics.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="key_extraction.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Index types</h1>
|
||||
|
||||
<div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
|
||||
Basics
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key estraction" border="0"><br>
|
||||
Key extraction
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#classification">Classification</a>
|
||||
<li><a href="#hashed_indices">Hashed indices</a>
|
||||
<ul>
|
||||
<li><a href="#hash_unique_non_unique">Unique and non-unique variants</a></li>
|
||||
<li><a href="#hash_spec">Specification</a></li>
|
||||
<li><a href="#hash_lookup">Lookup</a></li>
|
||||
<li><a href="#hash_updating">Updating</a></li>
|
||||
<li><a href="#guarantees">Guarantees on iterator validity and exception safety</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#rnd_indices">Random access indices</a>
|
||||
<ul>
|
||||
<li><a href="#rnd_spec">Specification</a></li>
|
||||
<li><a href="#rnd_interface">Interface</a></li>
|
||||
<li><a href="#rnd_vs_vector">Comparison with <code>std::vector</code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#rearrange">Index rearranging</a></li>
|
||||
<li><a href="#iterator_to"><code>iterator_to</code></a></li>
|
||||
<li><a href="#ordered_node_compression">Ordered indices node compression</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="classification">Classification</a></h2>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex provides six different index types, which can be classified as
|
||||
shown in the table below. <a href="basics.html#ord_indices">Ordered</a> and
|
||||
<a href="basics.html#seq_indices">sequenced</a> indices,
|
||||
which are the most commonly used, have been explained in the basics section;
|
||||
the rest of index types can be regarded as variations of the former providing
|
||||
some added benefits, functionally or in the area of performance.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<caption><b>Boost.MultiIndex indices.</b></caption>
|
||||
<tr>
|
||||
<th align="center"colspan="2">type</th>
|
||||
<th align="center">specifier</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" rowspan="4"> key-based </td>
|
||||
<td align="center" rowspan="2"> ordered </td>
|
||||
<td align="center"> <code>ordered_unique</code> </td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td align="center"> <code>ordered_non_unique</code> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" rowspan="2"> hashed </td>
|
||||
<td align="center"> <code>hashed_unique</code> </td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td align="center"> <code>hashed_non_unique</code> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" rowspan="2" colspan="2"> non key-based </td>
|
||||
<td align="center"><code> sequenced </code></td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td align="center"><code> random_access </code></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Key-based indices, of which ordered indices are the usual example, provide
|
||||
efficient lookup of elements based on some piece of information called the
|
||||
<i>element key</i>: there is an extensive suite of
|
||||
<a href="key_extraction.html">key extraction</a>
|
||||
utility classes allowing for the specification of such keys. Fast lookup
|
||||
imposes an internally managed order on these indices that the user is not
|
||||
allowed to modify; non key-based indices, on the other hand, can be freely
|
||||
rearranged at the expense of lacking lookup facilities. Sequenced indices,
|
||||
modeled after the interface of <code>std::list</code>, are the customary
|
||||
example of a non key-based index.
|
||||
</p>
|
||||
|
||||
<h2><a name="hashed_indices">Hashed indices</a></h2>
|
||||
|
||||
<p>
|
||||
Hashed indices constitute a trade-off with respect to ordered indices: if correctly used,
|
||||
they provide much faster lookup of elements, at the expense of losing sorting
|
||||
information.
|
||||
Let us revisit our <code>employee_set</code> example: suppose a field for storing
|
||||
the Social Security number is added, with the requisite that lookup by this
|
||||
number should be as fast as possible. Instead of the usual ordered index, a
|
||||
hashed index can be resorted to:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
|
||||
<span class=keyword>struct</span> <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=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
|
||||
<span class=keyword>int</span> <span class=identifier>ssnumber</span><span class=special>;</span>
|
||||
|
||||
<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>&</span> <span class=identifier>name</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>ssnumber</span><span class=special>):</span>
|
||||
<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>
|
||||
|
||||
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special><(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&</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><</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=comment>// sort by employee::operator<</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>employee</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<string> on name</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// hashed on ssnumber</span>
|
||||
<span class=identifier>hashed_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>employee</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>ssnumber</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_set</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Note that the hashed index does not guarantee any particular ordering of the
|
||||
elements: so, for instance, we cannot efficiently query the employees whose SSN is
|
||||
greater than a given number. Usually, you must consider these restrictions when
|
||||
determining whether a hashed index is preferred over an ordered one.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you are familiar with non-standard <code>hash_set</code>s provided
|
||||
by some compiler vendors, then learning to use hashed indices should be straightforward.
|
||||
However, the interface of hashed indices is modeled after the specification
|
||||
for unordered associative containers by the
|
||||
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1836.pdf">C++ Standard
|
||||
Library Technical Report</a> (TR1),
|
||||
which differs in some significant aspects from existing pre-standard
|
||||
implementations:
|
||||
<ul>
|
||||
<li>As there is no notion of ordering between keys, the <a href="#hash_lookup">lookup
|
||||
interface</a> does not offer <code>lower_bound</code> or <code>upper_bound</code>
|
||||
member functions (unlike Dinkumware's solution.)</li>
|
||||
<li>A set of member functions is provided for handling the internal
|
||||
bucket structure on which hashed indices rely. This includes facilities
|
||||
for <a href="../reference/hash_indices.html#hash_policy">rehashing</a>,
|
||||
control of the load factor (number of elements divided by number of buckets),
|
||||
and inspection of the buckets contents. Pre-standard implementations
|
||||
do not have such an extensive functionality.</li>
|
||||
</ul>
|
||||
Check the <a href="../reference/hash_indices.html">reference</a> for a
|
||||
complete specification of the interface of hashed indices,
|
||||
and <a href="../examples.html#example8">example 8</a> and
|
||||
<a href="../examples.html#example9">example 9</a> for practical applications.
|
||||
</p>
|
||||
|
||||
</p>
|
||||
|
||||
<h3><a name="hash_unique_non_unique">Unique and non-unique variants</a></h3>
|
||||
|
||||
<p>
|
||||
Just like ordered indices, hashed indices have unique and non-unique variants, selected
|
||||
with the specifiers <code>hashed_unique</code> and <code>hashed_non_unique</code>,
|
||||
respectively. In the latter case, elements with equivalent keys are kept together and can
|
||||
be jointly retrieved by means of the <code>equal_range</code> member function.
|
||||
</p>
|
||||
|
||||
<h3><a name="hash_spec">Specification</a></h3>
|
||||
|
||||
<p>
|
||||
Hashed indices specifiers have two alternative syntaxes, depending on whether
|
||||
<a href="basics.html#tagging">tags</a> are provided or not:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<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><span class=special><[</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>]]]]></span>
|
||||
|
||||
<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>
|
||||
<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>]]]></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The key extractor parameter works in exactly the same way as for
|
||||
<a href="basics.html#key_extraction">ordered indices</a>; lookup, insertion,
|
||||
etc., are based on the key returned by the extractor rather than the whole
|
||||
element.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The hash function is the very core of the fast lookup capabilities of this type of
|
||||
indices: a hasher
|
||||
is just a <a href="http://www.sgi.com/tech/stl/UnaryFunction.html"><code>Unary
|
||||
Function</code></a> returning an <code>std::size_t</code> value for any given
|
||||
key. In general, it is impossible that every key map to a different hash value, for
|
||||
the space of keys can be greater than the number of permissible hash codes: what
|
||||
makes for a good hasher is that the probability of a collision (two different
|
||||
keys with the same hash value) is as close to zero as possible. This is a statistical
|
||||
property depending on the typical distribution of keys in a given application, so
|
||||
it is not feasible to have a general-purpose hash function with excellent results
|
||||
in <i>every</i> possible scenario; the default value for this parameter uses
|
||||
<a href="../../../functional/hash/index.html">Boost.Hash</a>, which often provides good
|
||||
enough results.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The equality predicate is used to determine whether two keys are to be treated
|
||||
as the same. The default
|
||||
value <code>std::equal_to<KeyFromValue::result_type></code> is in most
|
||||
cases exactly what is needed, so very rarely will you have to provide
|
||||
your own predicate. Note that hashed indices require that two
|
||||
equivalent keys have the same hash value, which
|
||||
in practice greatly reduces the freedom in choosing an equality predicate.
|
||||
</p>
|
||||
|
||||
<h3><a name="hash_lookup">Lookup</a></h3>
|
||||
|
||||
<p>
|
||||
The lookup interface of hashed indices consists in member functions
|
||||
<code>find</code>, <code>count</code> and <code>equal_range</code>.
|
||||
Note that <code>lower_bound</code> and <code>upper_bound</code> are not
|
||||
provided, as there is no intrinsic ordering of keys in this type of indices.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Just as with ordered indices, these member functions take keys
|
||||
as their search arguments, rather than entire objects. Remember that
|
||||
ordered indices lookup operations are further augmented to accept
|
||||
<i>compatible keys</i>, which can roughly be regarded as "subkeys".
|
||||
For hashed indices, a concept of
|
||||
<a href="../reference/hash_indices.html#lookup">compatible key</a> is also
|
||||
supported, though its usefulness is much more limited: basically,
|
||||
a compatible key is an object which is entirely equivalent to
|
||||
a native object of <code>key_type</code> value, though maybe with
|
||||
a different internal representation:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// US SSN numbering scheme</span>
|
||||
<span class=keyword>struct</span> <span class=identifier>ssn</span>
|
||||
<span class=special>{</span>
|
||||
<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>
|
||||
<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>
|
||||
<span class=special>{}</span>
|
||||
|
||||
<span class=keyword>int</span> <span class=identifier>to_int</span><span class=special>()</span><span class=keyword>const</span>
|
||||
<span class=special>{</span>
|
||||
<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>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>private</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>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=comment>// interoperability with SSNs in raw int form</span>
|
||||
|
||||
<span class=keyword>struct</span> <span class=identifier>ssn_equal</span>
|
||||
<span class=special>{</span>
|
||||
<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>&</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>
|
||||
<span class=special>{</span>
|
||||
<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>
|
||||
<span class=special>}</span>
|
||||
|
||||
<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>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span>
|
||||
<span class=special>{</span>
|
||||
<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>
|
||||
<span class=special>}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>struct</span> <span class=identifier>ssn_hash</span>
|
||||
<span class=special>{</span>
|
||||
<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>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special><</span><span class=keyword>int</span><span class=special>>()(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>to_int</span><span class=special>());</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<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>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special><</span><span class=keyword>int</span><span class=special>>()(</span><span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>2</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>employee_set_by_ssn</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
|
||||
<span class=identifier>employee_set_by_ssn</span><span class=special>&</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><</span><span class=number>2</span><span class=special>>();</span>
|
||||
<span class=special>...</span>
|
||||
<span class=comment>// find an employee by ssn</span>
|
||||
<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>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
In the example, we provided a hash functor <code>ssn_hash</code> and an
|
||||
equality predicate <code>ssn_equal</code> allowing for interoperability
|
||||
between <code>ssn</code> objects and the raw <code>int</code>s stored as
|
||||
<code>SSN</code>s in <code>employee_set</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
By far, the most useful application of compatible keys in the context
|
||||
of hashed indices lies in the fact that they allow for seamless usage of
|
||||
<a href="key_extraction.html#composite_keys">composite keys</a>.
|
||||
</p>
|
||||
|
||||
<h3><a name="hash_updating">Updating</a></h3>
|
||||
|
||||
<p>
|
||||
Hashed indices have
|
||||
<a href="../reference/hash_indices.html#replace"><code>replace</code></a>,
|
||||
<a href="../reference/hash_indices.html#modify"><code>modify</code></a> and
|
||||
<a href="../reference/hash_indices.html#modify_key"><code>modify_key</code></a>
|
||||
member functions, with the same functionality as in ordered indices.
|
||||
</p>
|
||||
|
||||
<h3><a name="guarantees">Guarantees on iterator validity and exception safety</a></h3>
|
||||
|
||||
<p>
|
||||
Due to the internal constraints imposed by the Boost.MultiIndex framework,
|
||||
hashed indices provide guarantees on iterator validity and
|
||||
exception safety that are actually stronger than required by the
|
||||
C++ Standard Library Technical Report (TR1) with respect
|
||||
to unordered associative containers:
|
||||
<ul>
|
||||
<li>Iterator validity is preserved in any case during insertion or rehashing:
|
||||
TR1 allows for iterator invalidation when a rehash (implicit or explicit)
|
||||
is performed.</li>
|
||||
<li>Erasing an element or range of elements via iterators does not throw ever,
|
||||
as the internal hash function and equality predicate objects are not actually
|
||||
invoked.</li>
|
||||
<li><code>rehash</code> provides the strong exception safety guarantee
|
||||
unconditionally. TR1 only warrants it if the internal hash function and
|
||||
equality predicate objects do not throw. The somewhat surprising consequence
|
||||
is that a TR1-compliant unordered associative container might erase
|
||||
elements if an exception is thrown during rehashing!</li>
|
||||
</ul>
|
||||
In general, these stronger guarantees play in favor of the user's convenience,
|
||||
specially that which refers to iterator stability. A (hopefully minimal)
|
||||
degradation in performance might result in exchange for these commodities,
|
||||
though.
|
||||
</p>
|
||||
|
||||
<h2><a name="rnd_indices">Random access indices</a></h2>
|
||||
|
||||
<p>
|
||||
Random access indices offer the same kind of functionality as
|
||||
<a href="basics.html#seq_indices">sequenced indices</a>, with the extra advantages
|
||||
that their iterators are random access, and <code>operator[]</code>
|
||||
and <code>at()</code> are provided for accessing
|
||||
elements based on their position in the index. Let us rewrite a
|
||||
container used in a previous <a href="basics.html#list_fast_lookup">example</a>,
|
||||
using random access instead of sequenced indices:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
|
||||
<span class=comment>// text container with fast lookup based on a random access index</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>random_access</span><span class=special><>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>text_container</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// global text container object</span>
|
||||
<span class=identifier>text_container</span> <span class=identifier>tc</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Random access capabilities allow us to efficiently write code
|
||||
like the following:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<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>
|
||||
<span class=special>{</span>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<span class=comment>// note random access iterators can be added offsets</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>copy</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>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>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream_iterator</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>));</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>print_random_word</span><span class=special>()</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</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>
|
||||
<span class=special>}</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
This added flexibility comes at a price: insertions and deletions at positions
|
||||
other than the end of the index have linear complexity, whereas these operations
|
||||
are constant time for sequenced indices. This situation is reminiscent of the
|
||||
differences in complexity behavior between <code>std::list</code> and
|
||||
<code>std::vector</code>: in the case of random access indices, however,
|
||||
insertions and deletions never incur any element copying, so the actual
|
||||
performance of these operations can be acceptable, despite the theoretical
|
||||
disadvantage with respect to sequenced indices.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="../examples.html#example10">Example 10</a> and
|
||||
<a href="../examples.html#example11">example 11</a> in the examples section put
|
||||
random access indices in practice.
|
||||
</p>
|
||||
|
||||
<h3><a name="rnd_spec">Specification</a></h3>
|
||||
|
||||
<p>
|
||||
Random access indices are specified with the <code>random_access</code> construct,
|
||||
where the <a href="basics.html#tagging">tag</a> parameter is, as usual, optional:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>random_access</span><span class=special><[</span><i>(tag)</i><span class=special>]></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h3><a name="rnd_interface">Interface</a></h3>
|
||||
|
||||
<p>
|
||||
All public functions offered by sequenced indices are also provided
|
||||
by random access indices, so that the latter can act as a drop-in replacement
|
||||
of the former (save with respect to their complexity bounds, as explained above).
|
||||
Besides, random access
|
||||
indices have <code>operator[]</code> and <code>at()</code> for positional
|
||||
access to the elements, and member functions
|
||||
<a href="../reference/rnd_indices.html#capacity_memfun"><code>capacity</code></a> and
|
||||
<a href="../reference/rnd_indices.html#reserve"><code>reserve</code></a>
|
||||
that control internal reallocation in a similar manner as the homonym
|
||||
facilities in <code>std::vector</code>. Check the
|
||||
<a href="../reference/rnd_indices.html">reference</a> for details.
|
||||
</p>
|
||||
|
||||
<h3><a name="rnd_vs_vector">Comparison with <code>std::vector</code></a></h3>
|
||||
|
||||
<p>
|
||||
It is tempting to see random access indices as an analogue of <code>std::vector</code>
|
||||
for use in Boost.MultiIndex, but this metaphor can be misleading, as both constructs,
|
||||
though similar in many respects, show important semantic differences. An
|
||||
advantage of random access indices is that their iterators, as well as references
|
||||
to their elements, are <i>stable</i>, that is, they remain valid after any insertions
|
||||
or deletions. On the other hand, random access indices have several disadvantages with
|
||||
respect to <code>std::vector</code>s:
|
||||
<ul>
|
||||
<li>They do not provide <i>memory contiguity</i>, a property
|
||||
of <code>std::vector</code>s by which elements are stored adjacent to one
|
||||
another in a single block of memory.
|
||||
</li>
|
||||
<li>As usual in Boost.MultiIndex, elements of random access indices are immutable
|
||||
and can only be modified through member functions
|
||||
<a href="../reference/rnd_indices.html#replace"><code>replace</code></a> and
|
||||
<a href="../reference/rnd_indices.html#modify"><code>modify</code></a>.
|
||||
This precludes the usage of many mutating
|
||||
algorithms that are nonetheless applicable to <code>std::vector</code>s.
|
||||
</li>
|
||||
</ul>
|
||||
The latter shortcoming can be partially remedied by means of the
|
||||
<a href="#rearrange">rearranging interface</a> these indices provide.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In general, it is more instructive to regard random access indices as
|
||||
a variation of sequenced indices providing random access semantics, instead
|
||||
of insisting on the <code>std::vector</code> analogy.
|
||||
</p>
|
||||
|
||||
<h2><a name="rearrange">Index rearranging</a></h2>
|
||||
|
||||
<p>
|
||||
By design, index elements are immutable, i.e. iterators only grant
|
||||
<code>const</code> access to them, and only through the provided
|
||||
updating interface (<code>replace</code>, <code>modify</code> and
|
||||
<code>modify_key</code>) can the elements be modified. This restriction
|
||||
is set up so that the internal invariants of key-based indices are
|
||||
not broken (for instance, ascending order traversal in ordered
|
||||
indices), but induces important limitations in non key-based indices:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>random_access</span><span class=special><>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>container</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>container</span> <span class=identifier>c</span><span class=special>;</span>
|
||||
<span class=special>...</span>
|
||||
<span class=comment>// compiler error: assignment to read-only objects</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>random_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>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
What is unfortunate about the previous example is that the operation
|
||||
performed by <code>std::random_shuffle</code> is potentially compatible
|
||||
with <code>multi_index_container</code> invariants, as its result can be
|
||||
described by a permutation of the elements in the random access index
|
||||
with no actual modifications to the elements themselves. There are many
|
||||
more examples of such compatible algorithms in the C++ standard library,
|
||||
like for instance all sorting and partition functions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sequenced and random access indices provide a means to take advantage
|
||||
of such external algorithms. In order to introduce this facility we need
|
||||
a preliminary concept: a <i>view</i> of an index is defined as
|
||||
some iterator range [<code>first</code>,<code>last</code>) over the
|
||||
elements of the index such that all its elements are contained in the
|
||||
range exactly once. Continuing with our example, we can apply
|
||||
<code>std::random_suffle</code> on an ad hoc view obtained from the
|
||||
container:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// note that the elements of the view are not copies of the elements
|
||||
// in c, but references to them</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=keyword>int</span><span class=special>></span> <span class=special>></span> <span class=identifier>v</span><span class=special>;</span>
|
||||
<span class=identifier>BOOST_FOREACH</span><span class=special>(</span><span class=keyword>const</span> <span class=keyword>int</span><span class=special>&</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>
|
||||
|
||||
<span class=comment>// this compiles OK, as reference_wrappers are assignable</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>random_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>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Elements of <code>v</code> are <code>reference_wrapper</code>s (from
|
||||
<a href="../../../../doc/html/ref.html">Boost.Ref</a>) to the actual elements
|
||||
in the multi-index container. These objects still do not allow modification
|
||||
of the referenced entities, but they are
|
||||
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>,
|
||||
which is the only requirement <code>std::random_suffle</code> imposes. Once
|
||||
we have our desired rearrange stored in the view, we can transfer it to
|
||||
the container with
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<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>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>rearrange</code> accepts an input iterator signaling the beginning
|
||||
of the external view (and end iterator is not needed since the length of
|
||||
the view is the same as that of the index) and internally relocates the
|
||||
elements of the index so that their traversal order matches the view.
|
||||
Albeit with some circumventions, <code>rearrange</code> allows for the
|
||||
application of a varied range of algorithms to non key-based indices.
|
||||
Please note that the view concept is very general, and in no way tied
|
||||
to the particular implementation example shown above. For instance, indices
|
||||
of a <code>multi_index_container</code> are indeed views with respect to
|
||||
its non key-based indices:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// rearrange as index #1 (ascending order)</span>
|
||||
<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><</span><span class=number>1</span><span class=special>>().</span><span class=identifier>begin</span><span class=special>());</span>
|
||||
|
||||
<span class=comment>// rearrange in descending order</span>
|
||||
<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><</span><span class=number>1</span><span class=special>>().</span><span class=identifier>rbegin</span><span class=special>());</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The only important requirement imposed on views is that they must be
|
||||
<i>free</i>, i.e. they are not affected by relocations on the base index:
|
||||
thus, <code>rearrange</code> does not accept the following:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// undefined behavior: [rbegin(),rend()) is not free with respect
|
||||
// to the base index</span>
|
||||
<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>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The view concept is defined in detail in the
|
||||
<a href="../reference/indices.html#views">reference</a>.
|
||||
See <a href="../examples.html#example11">example 11</a> in the examples section
|
||||
for a demonstration of use of <code>rearrange</code>.
|
||||
</p>
|
||||
|
||||
<h2><a name="iterator_to"><code>iterator_to</code></a></h2>
|
||||
|
||||
<p>
|
||||
All indices of Boost.MultiIndex provide a member function called <code>iterator_to</code>
|
||||
which returns an iterator to a given element of the container:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>c</span><span class=special>;</span>
|
||||
<span class=special>...</span>
|
||||
<span class=comment>// convoluted way to do c.pop_back()</span>
|
||||
<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>
|
||||
|
||||
<span class=comment>// The following, though similar to the previous code,
|
||||
// does not work: iterator_to accepts a reference to
|
||||
// the element in the container, not a copy.</span>
|
||||
<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>
|
||||
<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>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>iterator_to</code> provides a way to retrieve an iterator to an element
|
||||
from a pointer to the element, thus making iterators and pointers interchangeable
|
||||
for the purposes of element pointing (not so for traversal) in many situations.
|
||||
This notwithstanding, it is not the aim of <code>iterator_to</code> to
|
||||
promote the usage of pointers as substitutes for real iterators: the latter are
|
||||
specifically designed for handling the elements of a container,
|
||||
and not only benefit from the iterator orientation of container interfaces,
|
||||
but are also capable of exposing many more programming bugs than raw pointers, both
|
||||
at compile and run time. <code>iterator_to</code> is thus meant to be used
|
||||
in scenarios where access via iterators is not suitable or desireable:
|
||||
<ul>
|
||||
<li>Interoperability with preexisting APIs based on pointers or references.</li>
|
||||
<li>Publication of pointer-based interfaces (for instance, when
|
||||
designing a C-compatible library).
|
||||
</li>
|
||||
<li>The exposure of pointers in place of iterators can act as a <i>type
|
||||
erasure</i> barrier effectively decoupling the user of the code
|
||||
from the implementation detail of which particular container is being
|
||||
used. Similar techniques, like the famous Pimpl idiom, are used
|
||||
in large projects to reduce dependencies and build times.
|
||||
</li>
|
||||
<li>Self-referencing contexts where an element acts upon its owner
|
||||
container and no iterator to itself is available.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2><a name="ordered_node_compression">Ordered indices node compression</a></h2>
|
||||
|
||||
<p>
|
||||
Ordered indices are implemented by means of a data structure
|
||||
known as a <i>red-black tree</i>. Nodes of a red-back tree contain pointers
|
||||
to the parent and the two children nodes, plus a 1-bit field referred to as
|
||||
the <i>node color</i> (hence the name of the structure). Due to alignment
|
||||
issues, on most architectures the color field occupies one entire word, that is,
|
||||
4 bytes in 32-bit systems and 8 bytes in 64-bit environments. This waste
|
||||
of space can be avoided by embedding the color bit inside one of the
|
||||
node pointers, provided not all the bits of the pointer representation contain
|
||||
useful information: this is precisely the case in many architectures where
|
||||
such nodes are aligned to even addresses, which implies that the least
|
||||
significant bit of the address must always be zero.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex ordered indices implement this type of node compression
|
||||
whenever applicable. As compared with common implementations of the STL
|
||||
container <code>std::set</code>, node compression can
|
||||
result in a reduction of header overload by 25% (from 16 to 12 bytes on
|
||||
typical 32-bit architectures, and from 32 to 24 bytes on 64-bit systems).
|
||||
The impact on performance of this optimization has been checked to be negligible
|
||||
for moderately sized containers, whereas containers with many elements (hundreds
|
||||
of thousands or more) perform faster with this optimization, most likely due to
|
||||
L1 and L2 cache effects.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Node compression can be disabled by globally setting the macro
|
||||
<code>BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES</code>.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
|
||||
Basics
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key estraction" border="0"><br>
|
||||
Key extraction
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised October 15th 2007</p>
|
||||
|
||||
<p>© Copyright 2003-2007 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,968 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Tutorial - Key extraction</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="indices.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="creation.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Key extraction</h1>
|
||||
|
||||
<div class="prev_link"><a href="indices.html"><img src="../prev.gif" alt="index types" border="0"><br>
|
||||
Index types
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="creation.html"><img src="../next.gif" alt="container creation" border="0"><br>
|
||||
Container creation
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#intro">Introduction</a>
|
||||
<ul>
|
||||
<li><a href="#read_write_key_extractors">Read/write key extractors</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#predefined_key_extractors">Predefined key extractors</a>
|
||||
<ul>
|
||||
<li><a href="#identity"><code>identity</code></a></li>
|
||||
<li><a href="#member"><code>member</code></a></li>
|
||||
<li><a href="#const_mem_fun"><code>const_mem_fun</code>
|
||||
and <code>mem_fun</code></a></li>
|
||||
<li><a href="#global_fun"><code>global_fun</code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#user_defined_key_extractors">User-defined key extractors</a></li>
|
||||
<li><a href="#composite_keys">Composite keys</a>
|
||||
<ul>
|
||||
<li><a href="#composite_keys_hash">Composite keys and hashed indices</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#advanced_key_extractors">Advanced features of Boost.MultiIndex key
|
||||
extractors</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="intro">Introduction</a></h2>
|
||||
|
||||
<p>
|
||||
STL associative containers have a notion of key, albeit in a somewhat incipient
|
||||
form. So, the keys of such containers are identified by a nested type
|
||||
<code>key_type</code>; for <code>std::set</code>s and <code>std::multiset</code>s,
|
||||
<code>key_type</code> coincides with <code>value_type</code>, i.e. the key is the
|
||||
element itself. <code>std::map</code> and <code>std::multimap</code> manage
|
||||
elements of type <code>std::pair<const Key,T></code>, where the first
|
||||
member is the key. In either case, the process of obtaining the key from a
|
||||
given element is implicitly fixed and cannot be customized by the user.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Fixed key extraction mechanisms like those performed by STL associative
|
||||
containers do not scale well in the context of Boost.MultiIndex, where
|
||||
several indices share their <code>value_type</code> definition but
|
||||
might feature completely different lookup semantics. For this reason,
|
||||
Boost.MultiIndex formalizes the concept of a
|
||||
<a href="../reference/key_extraction.html#key_extractors"><code>Key
|
||||
Extractor</code></a> in order to make it explicit and controllable
|
||||
in the definition of key-based indices.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Intuitively speaking, a key extractor is a function object that accepts
|
||||
a reference to an element and returns its associated key. The formal
|
||||
concept also imposes some reasonable constraints about the stability
|
||||
of the process, in the sense that extractors are assumed to
|
||||
return the same key when passed the same element: this is in consonance
|
||||
with the informal understanding that keys are actually some "part"
|
||||
of the element and do not depend on external data.
|
||||
</p>
|
||||
|
||||
<h3><a name="read_write_key_extractors">Read/write key extractors</a></h3>
|
||||
|
||||
<p>
|
||||
A key extractor is called <i>read/write</i> if it returns a non-constant reference
|
||||
to the key when passed a non-constant element, and it is called <i>read-only</i>
|
||||
otherwise. Boost.MultiIndex requires that the key extractor be read/write
|
||||
when using the <code>modify_key</code> member function of ordered and hashed
|
||||
indices. In all other situations, read-only extractors suffice.
|
||||
The section on <a href="#advanced_key_extractors">advanced features
|
||||
of Boost.MultiIndex key extractors</a> details which of the predefined
|
||||
key extractors are read/write.
|
||||
</p>
|
||||
|
||||
<h2><a name="predefined_key_extractors">Predefined key extractors</a></h2>
|
||||
|
||||
<h3><a name="identity"><code>identity</code></a></h3>
|
||||
|
||||
<p>
|
||||
The <a href="../reference/key_extraction.html#identity"><code>identity</code></a>
|
||||
key extractor returns the entire base object as the associated key:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span>
|
||||
<span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=comment>// the key is the entire element</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>cont</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h3><a name="member"><code>member</code></a></h3>
|
||||
|
||||
<p>
|
||||
<a href="../reference/key_extraction.html#member"><code>member</code></a>
|
||||
key extractors return a reference to a specified
|
||||
data field of the base object. For instance, in the following version of our
|
||||
familiar employee container:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>employee</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>employee</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>ssnumber</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_set</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
the second and third indices use <code>member</code> extractors on
|
||||
<code>employee::name</code> and <code>employee::ssnumber</code>, respectively.
|
||||
The specification of an instantiation of <code>member</code> is simple
|
||||
yet a little contrived:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier><i>(base type)</i></span><span class=special>,</span><span class=identifier><i>(key type)</i></span><span class=special>,</span><span class=identifier><i>(pointer to member)</i></span><span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
It might seem that the first and second parameters are superfluous,
|
||||
since the type of the base object and of the associated data field are
|
||||
already implicit in the pointer to member argument: unfortunately, it is
|
||||
not possible to extract this information with current C++ mechanisms,
|
||||
which makes the syntax of <code>member</code> a little too verbose.
|
||||
</p>
|
||||
|
||||
<h3><a name="const_mem_fun"><code>const_mem_fun</code> and <code>mem_fun</code></a></h3>
|
||||
|
||||
<p>
|
||||
Sometimes, the key of an index is not a concrete data member of the element,
|
||||
but rather it is a value returned by a particular member function.
|
||||
This resembles the notion of <i>calculated indices</i> supported by some
|
||||
relational databases. Boost.MultiIndex supports this
|
||||
kind of key extraction through
|
||||
<a href="../reference/key_extraction.html#const_mem_fun"><code>const_mem_fun</code></a>.
|
||||
Consider the following container where sorting on the third index
|
||||
is based upon the length of the name field:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>mem_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
|
||||
<span class=keyword>struct</span> <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=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
|
||||
|
||||
<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>&</span> <span class=identifier>name</span><span class=special>):</span><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=keyword>bool</span> <span class=keyword>operator</span><span class=special><(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&</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><</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
|
||||
|
||||
<span class=comment>// returns the length of the name field</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>name_length</span><span class=special>()</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>name</span><span class=special>.</span><span class=identifier>size</span><span class=special>();}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=comment>// sort by employee::operator<</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>employee</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<string> on name</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<int> on name_length()</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span>
|
||||
<span class=identifier>const_mem_fun</span><span class=special><</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span><span class=special>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name_length</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_set</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>const_mem_fun</code> usage syntax is similar to that of
|
||||
<a href="#member"><code>member</code></a>:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>const_mem_fun</span><span class=special><</span><span class=identifier><i>(base type)</i></span><span class=special>,</span><span class=identifier><i>(key type)</i></span><span class=special>,</span><span class=identifier><i>(pointer to member function)</i></span><span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The member function referred to must be <code>const</code>, take no arguments and return
|
||||
a value of the specified key type.
|
||||
Almost always you will want to use a <code>const</code> member function,
|
||||
since elements in a <code>multi_index_container</code> are treated as constant, much
|
||||
as elements of an <code>std::set</code>. However, a
|
||||
<a href="../reference/key_extraction.html#mem_fun"><code>mem_fun</code></a>
|
||||
counterpart is provided for use with non-constant member functions, whose
|
||||
applicability is discussed on the paragraph on
|
||||
<a href="#advanced_key_extractors">advanced features
|
||||
of Boost.MultiIndex key extractors</a>.
|
||||
</p>
|
||||
|
||||
<p><a href="../examples.html#example2">Example 2</a> in the examples section
|
||||
provides a complete program showing how to use <code>const_mem_fun</code>.
|
||||
<p>
|
||||
|
||||
<h3><a name="global_fun"><code>global_fun</code></a></h3>
|
||||
|
||||
<p>
|
||||
Whereas <code>const_mem_fun</code> and <code>mem_fun</code> are based on a
|
||||
given member function of the base type from where the key is extracted,
|
||||
<a href="../reference/key_extraction.html#global_fun"><code>global_fun</code></a>
|
||||
takes a global function (or static member function) accepting the base
|
||||
type as its parameter and returning the key:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
|
||||
<span class=keyword>struct</span> <span class=identifier>rectangle</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>int</span> <span class=identifier>x0</span><span class=special>,</span><span class=identifier>y0</span><span class=special>;</span>
|
||||
<span class=keyword>int</span> <span class=identifier>x1</span><span class=special>,</span><span class=identifier>y1</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>unsigned</span> <span class=keyword>long</span> <span class=identifier>area</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>rectangle</span><span class=special>&</span> <span class=identifier>r</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=special>(</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>)(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x0</span><span class=special>)*(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x0</span><span class=special>)+</span>
|
||||
<span class=special>(</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>)(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y0</span><span class=special>)*(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y0</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>rectangle</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=comment>// sort by increasing area</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>global_fun</span><span class=special><</span><span class=keyword>const</span> <span class=identifier>rectangle</span><span class=special>&,</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>,&</span><span class=identifier>area</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>rectangle_container</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The specification of <code>global_fun</code> obeys the following syntax:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>global_fun</span><span class=special><</span><span class=identifier><i>(argument type)</i></span><span class=special>,</span><span class=identifier><i>(key type)</i></span><span class=special>,</span><span class=identifier><i>(pointer to function)</i></span><span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
where the argument type and key type must match <i>exactly</i> those in the
|
||||
signature of the function used; for instance, in the example above the argument
|
||||
type is <code>const rectangle&</code>, without omitting the "<code>const</code>"
|
||||
and "<code>&</code>" parts. So, although most of the time the base type will be
|
||||
accepted by constant reference, <code>global_fun</code> is also prepared to take
|
||||
functions accepting their argument by value or by non-constant reference: this
|
||||
latter case cannot generally be used directly in the specification of
|
||||
<code>multi_index_container</code>s as their elements are treated as constant,
|
||||
but the section on <a href="#advanced_key_extractors">advanced features
|
||||
of Boost.MultiIndex key extractors</a> describes valid use cases of
|
||||
key extraction based on such functions with a non-constant reference argument.
|
||||
</p>
|
||||
|
||||
<p><a href="../examples.html#example2">Example 2</a> in the examples section
|
||||
uses <code>gobal_fun</code>.
|
||||
<p>
|
||||
|
||||
<h2><a name="user_defined_key_extractors">User-defined key extractors</a></h2>
|
||||
|
||||
<p>
|
||||
Although the <a href="#predefined_key_extractors">predefined key extractors</a>
|
||||
provided by Boost.MultiIndex are intended to serve most cases,
|
||||
the user can also provide her own key extractors in more exotic situations,
|
||||
as long as these conform to the
|
||||
<a href="../reference/key_extraction.html#key_extractors"><code>Key
|
||||
Extractor</code></a> concept.
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// some record class</span>
|
||||
<span class=keyword>struct</span> <span class=identifier>record</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>gregorian</span><span class=special>::</span><span class=identifier>date</span> <span class=identifier>d</span><span class=special>;</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>str</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=comment>// extracts a record's year</span>
|
||||
<span class=keyword>struct</span> <span class=identifier>record_year</span>
|
||||
<span class=special>{</span>
|
||||
<span class=comment>// result_type typedef required by Key Extractor concept</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>gregorian</span><span class=special>::</span><span class=identifier>greg_year</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>result_type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>record</span><span class=special>&</span> <span class=identifier>r</span><span class=special>)</span><span class=keyword>const</span> <span class=comment>// operator() must be const</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>r</span><span class=special>.</span><span class=identifier>d</span><span class=special>.</span><span class=identifier>year</span><span class=special>();</span>
|
||||
<span class=special>}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=comment>// example of use of the previous key extractor</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>record</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>record_year</span><span class=special>></span> <span class=comment>// sorted by record's year</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>record_log</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<a href="../examples.html#example6">Example 6</a> in the examples section
|
||||
applies some user-defined key extractors in a complex scenario where
|
||||
keys are accessed via pointers.
|
||||
</p>
|
||||
|
||||
<h2><a name="composite_keys">Composite keys</a></h2>
|
||||
|
||||
<p>
|
||||
In relational databases, composite keys depend on two or more fields of a given table.
|
||||
The analogous concept in Boost.MultiIndex is modeled by means of
|
||||
<a href="../reference/key_extraction.html#composite_key">
|
||||
<code>composite_key</code></a>, as shown in the example:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</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>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>composite_key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
|
||||
<span class=keyword>struct</span> <span class=identifier>phonebook_entry</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>family_name</span><span class=special>;</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>given_name</span><span class=special>;</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>phone_number</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>phonebook_entry</span><span class=special>(</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>family_name</span><span class=special>,</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>given_name</span><span class=special>,</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>phone_number</span><span class=special>):</span>
|
||||
<span class=identifier>family_name</span><span class=special>(</span><span class=identifier>family_name</span><span class=special>),</span><span class=identifier>given_name</span><span class=special>(</span><span class=identifier>given_name</span><span class=special>),</span><span class=identifier>phone_number</span><span class=special>(</span><span class=identifier>phone_number</span><span class=special>)</span>
|
||||
<span class=special>{}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=comment>// define a multi_index_container with a composite key on
|
||||
// (family_name,given_name)</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>phonebook_entry</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=comment>//non-unique as some subscribers might have more than one number</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span>
|
||||
<span class=identifier>composite_key</span><span class=special><</span>
|
||||
<span class=identifier>phonebook_entry</span><span class=special>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>family_name</span><span class=special>>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>given_name</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span> <span class=comment>// unique as numbers belong to only one subscriber</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>phone_number</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>phonebook</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>composite_key</code> accepts two or more key extractors on the same
|
||||
value (here, <code>phonebook_entry</code>). Lookup operations on a composite
|
||||
key are accomplished by passing tuples with the values searched:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>phonebook</span> <span class=identifier>pb</span><span class=special>;</span>
|
||||
<span class=special>...</span>
|
||||
<span class=comment>// search for Dorothea White's number</span>
|
||||
<span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span><span class=identifier>pb</span><span class=special>.</span><span class=identifier>find</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=string>"White"</span><span class=special>,</span><span class=string>"Dorothea"</span><span class=special>));</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>number</span><span class=special>=</span><span class=identifier>it</span><span class=special>-></span><span class=identifier>phone_number</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Composite keys are sorted by lexicographical order, i.e. sorting is performed
|
||||
by the first key, then the second key if the first one is equal, etc. This
|
||||
order allows for partial searches where only the first keys are specified:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>phonebook</span> <span class=identifier>pb</span><span class=special>;</span>
|
||||
<span class=special>...</span>
|
||||
<span class=comment>// look for all Whites</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>></span> <span class=identifier>p</span><span class=special>=</span>
|
||||
<span class=identifier>pb</span><span class=special>.</span><span class=identifier>equal_range</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=string>"White"</span><span class=special>));</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
As a notational convenience, when only the first key is specified it is possible
|
||||
to pass the argument directly without including it into a tuple:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>phonebook</span> <span class=identifier>pb</span><span class=special>;</span>
|
||||
<span class=special>...</span>
|
||||
<span class=comment>// look for all Whites</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>></span> <span class=identifier>p</span><span class=special>=</span><span class=identifier>pb</span><span class=special>.</span><span class=identifier>equal_range</span><span class=special>(</span><span class=string>"White"</span><span class=special>);</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
On the other hand, partial searches without specifying the first keys are not
|
||||
allowed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
By default, the corresponding <code>std::less</code> predicate is used
|
||||
for each subkey of a composite key. Alternate comparison predicates can
|
||||
be specified with <a href="../reference/key_extraction.html#composite_key_compare">
|
||||
<code>composite_key_compare</code></a>:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// phonebook with given names in reverse order</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>phonebook_entry</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span>
|
||||
<span class=identifier>composite_key</span><span class=special><</span>
|
||||
<span class=identifier>phonebook_entry</span><span class=special>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>family_name</span><span class=special>>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>given_name</span><span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>composite_key_compare</span><span class=special><</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>,</span> <span class=comment>// family names sorted as by default</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>greater</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=comment>// given names reversed</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>phone_number</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>phonebook</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
See <a href="../examples.html#example7">example 7</a> in the examples section
|
||||
for an application of <code>composite_key</code>.
|
||||
</p>
|
||||
|
||||
<h3><a name="composite_keys_hash">Composite keys and hashed indices</a></h3>
|
||||
|
||||
<p>
|
||||
Composite keys can also be used with hashed indices in a straightforward manner:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>struct</span> <span class=identifier>street_entry</span>
|
||||
<span class=special>{</span>
|
||||
<span class=comment>// quadrant coordinates</span>
|
||||
<span class=keyword>int</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=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>street_entry</span><span class=special>(</span><span class=keyword>int</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> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&</span> <span class=identifier>name</span><span class=special>):</span><span class=identifier>x</span><span class=special>(</span><span class=identifier>x</span><span class=special>),</span><span class=identifier>y</span><span class=special>(</span><span class=identifier>y</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=special>};</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>street_entry</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>hashed_non_unique</span><span class=special><</span> <span class=comment>// indexed by quadrant coordinates</span>
|
||||
<span class=identifier>composite_key</span><span class=special><</span>
|
||||
<span class=identifier>street_entry</span><span class=special>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>x</span><span class=special>>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>y</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>hashed_non_unique</span><span class=special><</span> <span class=comment>// indexed by street name</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>street_locator</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>street_locator</span> <span class=identifier>sl</span><span class=special>;</span>
|
||||
<span class=special>...</span>
|
||||
<span class=keyword>void</span> <span class=identifier>streets_in_quadrant</span><span class=special>(</span><span class=keyword>int</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=special>{</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>street_locator</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>street_locator</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>></span> <span class=identifier>p</span><span class=special>=</span>
|
||||
<span class=identifier>sl</span><span class=special>.</span><span class=identifier>equal_range</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>x</span><span class=special>,</span><span class=identifier>y</span><span class=special>));</span>
|
||||
|
||||
<span class=keyword>while</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>!=</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>second</span><span class=special>){</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>-></span><span class=identifier>name</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
|
||||
<span class=special>++</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>;</span>
|
||||
<span class=special>}</span>
|
||||
<span class=special>}</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Note that hashing is automatically taken care of: <code>boost::hash</code> is
|
||||
specialized to hash a composite key as a function of the <code>boost::hash</code>
|
||||
values of its elements. Should we need to specify different hash functions for the
|
||||
elements of a composite key, we can explicitly do so by using the
|
||||
<a href="../reference/key_extraction.html#composite_key_hash"><code>composite_key_hash</code></a>
|
||||
utility:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>struct</span> <span class=identifier>tuned_int_hash</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>int</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=special>{</span>
|
||||
<span class=comment>// specially tuned hash for this application</span>
|
||||
<span class=special>}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>street_entry</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>hashed_non_unique</span><span class=special><</span> <span class=comment>// indexed by quadrant coordinates</span>
|
||||
<span class=identifier>composite_key</span><span class=special><</span>
|
||||
<span class=identifier>street_entry</span><span class=special>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>x</span><span class=special>>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>y</span><span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>composite_key_hash</span><span class=special><</span>
|
||||
<span class=identifier>tuned_int_hash</span><span class=special>,</span>
|
||||
<span class=identifier>tuned_int_hash</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>hashed_non_unique</span><span class=special><</span> <span class=comment>// indexed by street name</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>street_locator</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Also, equality of composite keys can be tuned with
|
||||
<a href="../reference/key_extraction.html#composite_key_equal_to"><code>composite_key_equal_to</code></a>,
|
||||
though in most cases the default equality predicate (relying on
|
||||
the <code>std::equal_to</code> instantiations for the element types)
|
||||
will be the right choice.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unlike with ordered indices, we cannot perform partial searches specifying
|
||||
only the first elements of a composite key:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// try to locate streets in quadrants with x==0
|
||||
// compile-time error: hashed indices do not allow such operations</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>street_locator</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>street_locator</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>></span> <span class=identifier>p</span><span class=special>=</span>
|
||||
<span class=identifier>sl</span><span class=special>.</span><span class=identifier>equal_range</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=number>0</span><span class=special>));</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The reason for this limitation is quite logical: as the hash value of a composite
|
||||
key depends on all of its elements, it is impossible to calculate it from
|
||||
partial information.
|
||||
</p>
|
||||
|
||||
<h2><a name="advanced_key_extractors">Advanced features of Boost.MultiIndex key
|
||||
extractors</a></h2>
|
||||
|
||||
<p>
|
||||
The <a href="../reference/key_extraction.html#key_extractors"><code>Key Extractor</code></a>
|
||||
concept allows the same object to extract keys from several different types,
|
||||
possibly through suitably defined overloads of <code>operator()</code>:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// example of a name extractor from employee and employee *</span>
|
||||
<span class=keyword>struct</span> <span class=identifier>name_extractor</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>result_type</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>const</span> <span class=identifier>result_type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&</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>e</span><span class=special>.</span><span class=identifier>name</span><span class=special>;}</span>
|
||||
<span class=identifier>result_type</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>employee</span><span class=special>*</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>e</span><span class=special>-></span><span class=identifier>name</span><span class=special>;}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=comment>// name_extractor can handle elements of type employee...</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>name_extractor</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_set</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// ...as well as elements of type employee *</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>*,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>name_extractor</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_ptr_set</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
This possibility is fully exploited by predefined key extractors provided
|
||||
by Boost.MultiIndex, making it simpler to define <code>multi_index_container</code>s
|
||||
where elements are pointers or references to the actual objects. The following
|
||||
specifies a <code>multi_index_container</code> of pointers to employees sorted by their
|
||||
names.
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span> <span class=special>*,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_set</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Note that this is specified in exactly the same manner as a <code>multi_index_container</code>
|
||||
of actual <code>employee</code> objects: <code>member</code> takes care of the
|
||||
extra dereferencing needed to gain access to <code>employee::name</code>. A similar
|
||||
functionality is provided for interoperability with reference wrappers from
|
||||
<a href="../../../../doc/html/ref.html">Boost.Ref</a>:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_set</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
In fact, support for pointers is further extended to accept what we call
|
||||
<i>chained pointers</i>. Such a chained pointer is defined by induction as a raw or
|
||||
smart pointer or iterator to the actual element, to a reference wrapper of the
|
||||
element or <i>to another chained pointer</i>; that is, chained pointers are arbitrary
|
||||
compositions of pointer-like types ultimately dereferencing
|
||||
to the element from where the key is to be extracted. Examples of chained
|
||||
pointers to <code>employee</code> are:
|
||||
<ul>
|
||||
<li><code>employee *</code>,</li>
|
||||
<li><code>const employee *</code>,</li>
|
||||
<li><code>std::auto_ptr<employee></code>,</li>
|
||||
<li><code>std::list<boost::reference_wrapper<employee> >::iterator</code>,</li>
|
||||
<li><code>employee **</code>,</li>
|
||||
<li><code>boost::shared_ptr<const employee *></code>.</li>
|
||||
</ul>
|
||||
In general, chained pointers with dereferencing distance greater than 1 are not
|
||||
likely to be used in a normal program, but they can arise in frameworks
|
||||
which construct "views" as <code>multi_index_container</code>s from preexisting
|
||||
<code>multi_index_container</code>s.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In order to present a short summary of the different usages of Boost.MultiIndex
|
||||
key extractors in the presence of reference wrappers and pointers, consider the
|
||||
following final type:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>struct</span> <span class=identifier>T</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>int</span> <span class=identifier>i</span><span class=special>;</span>
|
||||
<span class=keyword>const</span> <span class=keyword>int</span> <span class=identifier>j</span><span class=special>;</span>
|
||||
<span class=keyword>int</span> <span class=identifier>f</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=keyword>int</span> <span class=identifier>g</span><span class=special>();</span>
|
||||
<span class=keyword>static</span> <span class=keyword>int</span> <span class=identifier>gf</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T</span><span class=special>&);</span>
|
||||
<span class=keyword>static</span> <span class=keyword>int</span> <span class=identifier>gg</span><span class=special>(</span><span class=identifier>T</span><span class=special>&);</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The table below lists the appropriate key extractors to be used for
|
||||
different pointer and reference wrapper types based on <code>T</code>, for
|
||||
each of its members.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<table cellspacing="0">
|
||||
<caption><b>Use cases for Boost.MultiIndex key extractors.</b></caption>
|
||||
<tr>
|
||||
<th>element type</th>
|
||||
<th> key </th>
|
||||
<th>key extractor</th>
|
||||
<th>applicable to<br><code>const</code> elements?</th>
|
||||
<th>read/write?</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" rowspan="6"><code>T</code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,int,&T::i></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>j</code></td>
|
||||
<td><code>member<T,const int,&T::j></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>f()</code></td>
|
||||
<td><code>const_mem_fun<T,int,&T::f></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>g()</code></td>
|
||||
<td><code>mem_fun<T,int,&T::g></code></td>
|
||||
<td align="center">no</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>gf()</code></td>
|
||||
<td><code>global_fun<const T&,int,&T::gf></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>gg()</code></td>
|
||||
<td><code>global_fun<T&,int,&T::gg></code></td>
|
||||
<td align="center">no</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
|
||||
<tr class="odd_tr">
|
||||
<td align="center" rowspan="6"><code>reference_wrapper<T></code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,int,&T::i></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">yes</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>j</code></td>
|
||||
<td><code>member<T,const int,&T::j></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>f()</code></td>
|
||||
<td><code>const_mem_fun<T,int,&T::f></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>g()</code></td>
|
||||
<td><code>mem_fun<T,int,&T::g></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>gf()</code></td>
|
||||
<td><code>global_fun<const T&,int,&T::gf></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>gg()</code></td>
|
||||
<td><code>global_fun<T&,int,&T::gg></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td align="center" rowspan="6"><code>reference_wrapper<const T></code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,const int,&T::i></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>j</code></td>
|
||||
<td><code>member<T,const int,&T::j></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>f()</code></td>
|
||||
<td><code>const_mem_fun<T,int,&T::f></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>g()</code></td>
|
||||
<td colspan="3"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>gf()</code></td>
|
||||
<td><code>global_fun<const T&,int,&T::gf></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>gg()</code></td>
|
||||
<td colspan="3"> </td>
|
||||
</tr>
|
||||
|
||||
<tr class="odd_tr">
|
||||
<td align="center" rowspan="6">chained pointer to <code>T</code><br>
|
||||
or to <code>reference_wrapper<T></code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,int,&T::i></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">yes</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>j</code></td>
|
||||
<td><code>member<T,const int,&T::j></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>f()</code></td>
|
||||
<td><code>const_mem_fun<T,int,&T::f></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>g()</code></td>
|
||||
<td><code>mem_fun<T,int,&T::g></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>gf()</code></td>
|
||||
<td><code>global_fun<const T&,int,&T::gf></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><code>gg()</code></td>
|
||||
<td><code>global_fun<T&,int,&T::gg></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td align="center" rowspan="6">chained pointer to <code>const T</code><br>
|
||||
or to <code>reference_wrapper<const T></code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,const int,&T::i></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>j</code></td>
|
||||
<td><code>member<T,const int,&T::j></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>f()</code></td>
|
||||
<td><code>const_mem_fun<T,int,&T::f></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>g()</code></td>
|
||||
<td colspan="3"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>gf()</code></td>
|
||||
<td><code>global_fun<const T&,int,&T::gf></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>gg()</code></td>
|
||||
<td colspan="3"> </td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The column "applicable to <code>const</code> elements?" states whether the
|
||||
corresponding key extractor can be used when passed constant elements (this
|
||||
relates to the elements specified in the first column, not the referenced
|
||||
<code>T</code> objects). The only negative cases are for <code>T::g</code> and
|
||||
<code>T:gg</code> when the elements are raw <code>T</code> objects, which make sense
|
||||
as we are dealing with a non-constant member function (<code>T::g</code>)
|
||||
and a function taking <code>T</code> by
|
||||
non-constant reference: this also implies that <code>multi_index_container</code>s
|
||||
of elements of <code>T</code> cannot be sorted by <code>T::g</code> or <code>T::gg</code>, because
|
||||
elements contained within a <code>multi_index_container</code> are treated as constant.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The column "read/write?" shows which combinations yield
|
||||
<a href="#read_write_key_extractors">read/write key extractors</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Some care has to be taken to preserve <code>const</code>-correctness in the
|
||||
specification of <code>member</code> key extractors: in some sense, the <code>const</code>
|
||||
qualifier is carried along to the member part, even if that particular
|
||||
member is not defined as <code>const</code>. For instance, if the elements
|
||||
are of type <code>const T *</code>, sorting by <code>T::i</code> is <i>not</i>
|
||||
specified as <code>member<const T,int,&T::i></code>, but rather as
|
||||
<code>member<T,const int,&T::i></code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For practical demonstrations of use of these key extractors, refer to
|
||||
<a href="../examples.html#example2">example 2</a> and
|
||||
<a href="../examples.html#example6">example 6</a> in the examples section.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="indices.html"><img src="../prev.gif" alt="index types" border="0"><br>
|
||||
Index types
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="creation.html"><img src="../next.gif" alt="container creation" border="0"><br>
|
||||
Container creation
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised June 11th 2007</p>
|
||||
|
||||
<p>© Copyright 2003-2007 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
@@ -0,0 +1,405 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Boost.MultiIndex Documentation - Tutorial - Techniques</title>
|
||||
<link rel="stylesheet" href="../style.css" type="text/css">
|
||||
<link rel="start" href="../index.html">
|
||||
<link rel="prev" href="debug.html">
|
||||
<link rel="up" href="index.html">
|
||||
<link rel="next" href="../reference/index.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Techniques</h1>
|
||||
|
||||
<div class="prev_link"><a href="debug.html"><img src="../prev.gif" alt="debugging support" border="0"><br>
|
||||
Debugging support
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="../reference/index.html"><img src="../next.gif" alt="Boost.MultiIndex reference" border="0"><br>
|
||||
Boost.MultiIndex reference
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#emulate_std_containers">Emulating standard containers with
|
||||
<code>multi_index_container</code></a>
|
||||
<ul>
|
||||
<li><a href="#emulate_assoc_containers">Emulation of associative
|
||||
containers</a></li>
|
||||
<li><a href="#emulate_std_list">Emulation of <code>std::list</code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#metaprogrammming">Metaprogramming and <code>multi_index_container</code></a>
|
||||
<ul>
|
||||
<li><a href="#mpl_analysis">MPL analysis</a></li>
|
||||
<li><a href="#mpl_synthesis">MPL synthesis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="emulate_std_containers">Emulating standard containers with
|
||||
<code>multi_index_container</code></a></h2>
|
||||
|
||||
<h3><a name="emulate_assoc_containers">Emulation of associative
|
||||
containers</a></h3>
|
||||
|
||||
<p>
|
||||
Academic movitations aside, there is a practical interest in emulating standard
|
||||
associative containers by means of <code>multi_index_container</code>, namely to take
|
||||
advantage of extended functionalities provided by <code>multi_index_container</code> for
|
||||
lookup, range querying and updating.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In order to emulate a <code>std::set</code> one can follow the substitution
|
||||
rule:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Key</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>Key</span><span class=special>>,</span><span class=identifier>Compare</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
In the default case where <code>Compare=std::less<Key></code> and
|
||||
<code>Allocator=std::allocator<Key></code>, the substitution rule is
|
||||
simplified as
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>-></span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Key</span><span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The substitution of <code>multi_index_container</code> for <code>std::set</code> keeps
|
||||
the whole set of functionality provided by <code>std::set</code>, so in
|
||||
principle it is a drop-in replacement needing no further adjustments.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>std::multiset</code> can be emulated in a similar manner, according to the
|
||||
following rule:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Key</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>Key</span><span class=special>>,</span><span class=identifier>Compare</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
When default values are taken into consideration, the rule takes the form
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Key</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The emulation of <code>std::multiset</code>s with <code>multi_index_container</code>
|
||||
results in a slight difference with respect to the interface offered: the member
|
||||
function <code>insert(const value_type&)</code> does not return an
|
||||
<code>iterator</code> as in <code>std::multiset</code>s, but rather a
|
||||
<code>std::pair<iterator,bool></code> in the spirit of <code>std::set</code>s.
|
||||
In this particular case, however, the <code>bool</code> member of the returned
|
||||
pair is always <code>true</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The case of <code>std::map</code>s and <code>std::multimap</code>s does not lend
|
||||
itself to such a direct emulation by means of <code>multi_index_container</code>. The main
|
||||
problem lies in the fact that elements of a <code>multi_index_container</code> are treated
|
||||
as constant, while the <code>std::map</code> and <code>std::multimap</code> handle
|
||||
objects of type <code>std::pair<const Key,T></code>, thus allowing for free
|
||||
modification of the value part. To overcome this difficulty we need to create an ad
|
||||
hoc pair class:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>template</span> <span class=special><</span><span class=keyword>typename</span> <span class=identifier>T1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>T2</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>mutable_pair</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>T1</span> <span class=identifier>first_type</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>T2</span> <span class=identifier>second_type</span><span class=special>;</span>
|
||||
|
||||
<span class=identifier>mutable_pair</span><span class=special>():</span><span class=identifier>first</span><span class=special>(</span><span class=identifier>T1</span><span class=special>()),</span><span class=identifier>second</span><span class=special>(</span><span class=identifier>T2</span><span class=special>()){}</span>
|
||||
<span class=identifier>mutable_pair</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T1</span><span class=special>&</span> <span class=identifier>f</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>T2</span><span class=special>&</span> <span class=identifier>s</span><span class=special>):</span><span class=identifier>first</span><span class=special>(</span><span class=identifier>f</span><span class=special>),</span><span class=identifier>second</span><span class=special>(</span><span class=identifier>s</span><span class=special>){}</span>
|
||||
<span class=identifier>mutable_pair</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>T1</span><span class=special>,</span><span class=identifier>T2</span><span class=special>>&</span> <span class=identifier>p</span><span class=special>):</span><span class=identifier>first</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>),</span><span class=identifier>second</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>second</span><span class=special>){}</span>
|
||||
|
||||
<span class=identifier>T1</span> <span class=identifier>first</span><span class=special>;</span>
|
||||
<span class=keyword>mutable</span> <span class=identifier>T2</span> <span class=identifier>second</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
and so the substitution rules are:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>map</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>>,</span><span class=identifier>Compare</span><span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=keyword>template</span> <span class=identifier>rebind</span><span class=special><</span><span class=identifier>Element</span><span class=special>>::</span><span class=identifier>other</span>
|
||||
<span class=special>></span>
|
||||
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multimap</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>>,</span><span class=identifier>Compare</span><span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=keyword>template</span> <span class=identifier>rebind</span><span class=special><</span><span class=identifier>Element</span><span class=special>>::</span><span class=identifier>other</span>
|
||||
<span class=special>></span>
|
||||
|
||||
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_pair</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>></span>)
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
If default values are considered, the rules take the form:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>map</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,
|
||||
</span><span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multimap</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,
|
||||
</span><span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
|
||||
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_pair</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>></span>)
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Unlike as with standard sets, the interface of these <code>multi_index_container</code>-emulated
|
||||
maps does not exactly conform to that of <code>std::map</code>s and
|
||||
<code>std::multimap</code>s. The most obvious difference is the lack of
|
||||
<code>operator []</code>, either in read or write mode; this, however, can be
|
||||
emulated with appropriate use of <code>find</code> and <code>insert</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These emulations of standard associative containers with <code>multi_index_container</code>
|
||||
are comparable to the original constructs in terms of space and time efficiency.
|
||||
See the <a href="../performance.html">performance section</a> for further details.
|
||||
</p>
|
||||
|
||||
<h3><a name="emulate_std_list">Emulation of <code>std::list</code></a></h3>
|
||||
|
||||
<p>
|
||||
Unlike the case of associative containers, emulating <code>std::list</code>
|
||||
in Boost.MultiIndex does not add any significant functionality, so the following
|
||||
is presented merely for completeness sake.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Much as with standard maps, the main difficulty to overcome when emulating
|
||||
<code>std::list</code> derives from the constant nature of elements of a
|
||||
<code>multi_index_container</code>. Again, some sort of adaption class is needed, like
|
||||
for instance the following:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>template</span> <span class=special><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>mutable_value</span>
|
||||
<span class=special>{</span>
|
||||
<span class=identifier>mutable_value</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T</span><span class=special>&</span> <span class=identifier>t</span><span class=special>):</span><span class=identifier>t</span><span class=special>(</span><span class=identifier>t</span><span class=special>){}</span>
|
||||
<span class=keyword>operator</span> <span class=identifier>T</span><span class=special>&()</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>t</span><span class=special>;}</span>
|
||||
|
||||
<span class=keyword>private</span><span class=special>:</span>
|
||||
<span class=keyword>mutable</span> <span class=identifier>T</span> <span class=identifier>t</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
which allows us to use the substitution rule:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special><</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=keyword>template</span> <span class=identifier>rebind</span><span class=special><</span><span class=identifier>Element</span><span class=special>>::</span><span class=identifier>other</span>
|
||||
<span class=special>></span>
|
||||
|
||||
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_value</span><span class=special><</span><span class=identifier>T</span><span class=special>></span>)
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
or, if the default value <code>Allocator=std::allocator<T></code> is used:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special><</span><span class=identifier>T</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>mutable_value</span><span class=special><</span><span class=identifier>T</span><span class=special>>,</span><span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>></span> <span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<h2><a name="metaprogrammming">Metaprogramming and <code>multi_index_container</code></a></h2>
|
||||
|
||||
<p>
|
||||
Boost.MultiIndex provides a number of facilities intended to allow the analysis and
|
||||
synthesis of <code>multi_index_container</code> instantiations by
|
||||
<a href="../../../../libs/mpl/doc/index.html">MPL</a> metaprograms.
|
||||
</p>
|
||||
|
||||
<h3><a name="mpl_analysis">MPL analysis</a></h3>
|
||||
|
||||
<p>
|
||||
Given a <code>multi_index_container</code> instantiation, the following nested types are
|
||||
provided for compile-time inspection of the various types occurring in the
|
||||
definition of the <code>multi_index_container</code>:
|
||||
<ul>
|
||||
<li><code>index_specifier_type_list</code>,</li>
|
||||
<li><code>index_type_list</code>,</li>
|
||||
<li><code>iterator_type_list</code>,</li>
|
||||
<li><code>const_iterator_type_list</code>.</li>
|
||||
</ul>
|
||||
Each of these types is an MPL sequence with as many elements as indices
|
||||
comprise the <code>multi_index_container</code>: for instance, the <code>n</code>-th
|
||||
element of <code>iterator_type_list</code> is the same as
|
||||
<code>nth_index<n>::type::iterator</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A subtle but important distinction exists between
|
||||
<code>index_specifier_type_list</code> and <code>index_type_list</code>:
|
||||
the former typelist holds the index <i>specifiers</i>
|
||||
with which the <code>multi_index_container</code> instantiation was defined,
|
||||
while the latter gives access to the actual implementation classes
|
||||
corresponding to each specifier. An example will help to clarify
|
||||
this distinction. Given the instantiation:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>sequenced</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>indexed_t</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>indexed_t::index_specifier_type_list</code> is a type list with
|
||||
elements
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=identifier>sequenced</span><span class=special><></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
while <code>indexed_t::index_type_list</code> holds the types
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>multi_index_container</span><span class=special>::</span><span class=identifier>nth_type</span><span class=special><</span><span class=number>0</span><span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special>::</span><span class=identifier>nth_type</span><span class=special><</span><span class=number>1</span><span class=special>>::</span><span class=identifier>type</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
so the typelists are radically different. Check the
|
||||
<a href="../reference/multi_index_container.html#types">reference</a>
|
||||
for the exact MPL sequence concepts modeled by these type lists.
|
||||
</p>
|
||||
|
||||
<h3><a name="mpl_synthesis">MPL synthesis</a></h3>
|
||||
|
||||
<p>
|
||||
Although typically indices are specified by means of the
|
||||
<code>indexed_by</code> construct, actually any MPL sequence of
|
||||
index specifiers can be provided instead:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=keyword>typedef</span> <span class=identifier>mpl</span><span class=special>::</span><span class=identifier>vector</span><span class=special><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>></span> <span class=identifier>index_list_t</span><span class=special>;</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>index_list_t</span>
|
||||
<span class=special>></span> <span class=identifier>indexed_t</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
This possibility enables the synthesis of instantiations of
|
||||
<code>multi_index_container</code> through MPL metaprograms, as the following
|
||||
example shows:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=comment>// original multi_index_container instantiation</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>indexed_t1</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// we take its index list and add an index</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>push_front</span><span class=special><</span>
|
||||
<span class=identifier>indexed_t1</span><span class=special>::</span><span class=identifier>index_specifier_type_list</span><span class=special>,</span>
|
||||
<span class=identifier>sequenced</span><span class=special><></span>
|
||||
<span class=special>>::</span><span class=identifier>type</span> <span class=identifier>index_list_t</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// augmented multi_index_container</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>index_list_t</span>
|
||||
<span class=special>></span> <span class=identifier>indexed_t2</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="prev_link"><a href="debug.html"><img src="../prev.gif" alt="debugging support" border="0"><br>
|
||||
Debugging support
|
||||
</a></div>
|
||||
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
||||
Boost.MultiIndex tutorial
|
||||
</a></div>
|
||||
<div class="next_link"><a href="../reference/index.html"><img src="../next.gif" alt="Boost.MultiIndex reference" border="0"><br>
|
||||
Boost.MultiIndex reference
|
||||
</a></div><br clear="all" style="clear: all;">
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised November 7th 2008</p>
|
||||
|
||||
<p>© Copyright 2003-2008 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +1,12 @@
|
||||
# Boost.MultiIndex examples Jamfile
|
||||
#
|
||||
# Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
# Copyright 2003-2007 Joaquín M López Muñoz.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# See http://www.boost.org/libs/multi_index for library home page.
|
||||
|
||||
subproject libs/multi_index/example ;
|
||||
|
||||
exe basic
|
||||
: basic.cpp
|
||||
: <include>$(BOOST_ROOT)
|
||||
@@ -29,14 +27,19 @@ exe composite_keys
|
||||
: <include>$(BOOST_ROOT)
|
||||
;
|
||||
|
||||
exe fun_key
|
||||
: fun_key.cpp
|
||||
: <include>$(BOOST_ROOT)
|
||||
;
|
||||
|
||||
exe hashed
|
||||
: hashed.cpp
|
||||
: <include>$(BOOST_ROOT)
|
||||
;
|
||||
|
||||
exe memfun_key
|
||||
: memfun_key.cpp
|
||||
: <include>$(BOOST_ROOT)
|
||||
exe ip_allocator
|
||||
: ip_allocator.cpp
|
||||
: <include>$(BOOST_ROOT) <threading>multi
|
||||
;
|
||||
|
||||
exe non_default_ctor
|
||||
@@ -44,6 +47,16 @@ exe non_default_ctor
|
||||
: <include>$(BOOST_ROOT)
|
||||
;
|
||||
|
||||
exe random_access
|
||||
: random_access.cpp
|
||||
: <include>$(BOOST_ROOT)
|
||||
;
|
||||
|
||||
exe rearrange
|
||||
: rearrange.cpp
|
||||
: <include>$(BOOST_ROOT)
|
||||
;
|
||||
|
||||
exe sequenced
|
||||
: sequenced.cpp
|
||||
: <include>$(BOOST_ROOT)
|
||||
@@ -51,7 +64,6 @@ exe sequenced
|
||||
|
||||
exe serialization
|
||||
: serialization.cpp
|
||||
<lib>../../serialization/build/boost_serialization
|
||||
/boost/serialization//boost_serialization
|
||||
: <include>$(BOOST_ROOT)
|
||||
std::locale-support
|
||||
;
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex basic example.
|
||||
*
|
||||
* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex example of a bidirectional map.
|
||||
*
|
||||
* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Copyright 2003-2009 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
using boost::multi_index_container;
|
||||
using namespace boost::multi_index;
|
||||
@@ -35,7 +34,15 @@ struct to{};
|
||||
template<typename FromType,typename ToType>
|
||||
struct bidirectional_map
|
||||
{
|
||||
typedef std::pair<FromType,ToType> value_type;
|
||||
struct value_type
|
||||
{
|
||||
value_type(const FromType& first_,const ToType& second_):
|
||||
first(first_),second(second_)
|
||||
{}
|
||||
|
||||
FromType first;
|
||||
ToType second;
|
||||
};
|
||||
|
||||
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\
|
||||
defined(BOOST_MSVC)&&(BOOST_MSVC<1300) ||\
|
||||
@@ -108,7 +115,7 @@ int main()
|
||||
std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
|
||||
}
|
||||
else{
|
||||
nth_index_iterator<dictionary,1>::type it2=get<1>(d).find(word);
|
||||
nth_index<dictionary,1>::type::iterator it2=get<1>(d).find(word);
|
||||
if(it2!=get<1>(d).end()){
|
||||
std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
|
||||
}
|
||||
@@ -129,7 +136,7 @@ int main()
|
||||
else{
|
||||
/* word not found in Spanish, try our luck in English */
|
||||
|
||||
dictionary::index_iterator<to>::type it2=d.get<to>().find(word);
|
||||
dictionary::index<to>::type::iterator it2=d.get<to>().find(word);
|
||||
if(it2!=d.get<to>().end()){
|
||||
std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex example: complex searches and foreign keys.
|
||||
*
|
||||
* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -245,7 +245,7 @@ int main()
|
||||
|
||||
/* find all the cars for the manufacturer given */
|
||||
|
||||
index_iterator<car_table,manufacturer>::type ic0,ic1;
|
||||
boost::multi_index::index<car_table,manufacturer>::type::iterator ic0,ic1;
|
||||
boost::tuples::tie(ic0,ic1)=get<manufacturer>(ct).equal_range(cm);
|
||||
|
||||
/* construct a view (indexed by price) with these */
|
||||
@@ -280,7 +280,7 @@ int main()
|
||||
|
||||
/* find the cars in the range given */
|
||||
|
||||
index_iterator<car_table,price>::type ic0,ic1;
|
||||
boost::multi_index::index<car_table,price>::type::iterator ic0,ic1;
|
||||
ic0=get<price>(ct).lower_bound(min_price);
|
||||
ic1=get<price>(ct).upper_bound(max_price);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex example of composite keys.
|
||||
*
|
||||
* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@@ -287,7 +288,7 @@ int main()
|
||||
continue;
|
||||
}
|
||||
|
||||
it->second->execute(++tok.begin(),tok.end());
|
||||
it->second->execute(boost::next(tok.begin()),tok.end());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex example of member functions used as key extractors.
|
||||
/* Boost.MultiIndex example of functions used as key extractors.
|
||||
*
|
||||
* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,6 +14,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/global_fun.hpp>
|
||||
#include <boost/multi_index/mem_fun.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <iostream>
|
||||
@@ -29,8 +30,8 @@ using namespace boost::multi_index;
|
||||
|
||||
struct name_record
|
||||
{
|
||||
name_record(std::string given_name,std::string family_name):
|
||||
given_name(given_name),family_name(family_name)
|
||||
name_record(std::string given_name_,std::string family_name_):
|
||||
given_name(given_name_),family_name(family_name_)
|
||||
{}
|
||||
|
||||
std::string name()const
|
||||
@@ -46,7 +47,13 @@ private:
|
||||
std::string family_name;
|
||||
};
|
||||
|
||||
/* multi_index_container with only one index based on name_record::name().
|
||||
std::string::size_type name_record_length(const name_record& r)
|
||||
{
|
||||
return r.name().size();
|
||||
}
|
||||
|
||||
/* multi_index_container with indices based on name_record::name()
|
||||
* and name_record_length().
|
||||
* See Compiler specifics: Use of const_mem_fun_explicit and
|
||||
* mem_fun_explicit for info on BOOST_MULTI_INDEX_CONST_MEM_FUN.
|
||||
*/
|
||||
@@ -56,6 +63,9 @@ typedef multi_index_container<
|
||||
indexed_by<
|
||||
ordered_unique<
|
||||
BOOST_MULTI_INDEX_CONST_MEM_FUN(name_record,std::string,name)
|
||||
>,
|
||||
ordered_non_unique<
|
||||
global_fun<const name_record&,std::string::size_type,name_record_length>
|
||||
>
|
||||
>
|
||||
> name_record_set;
|
||||
@@ -71,9 +81,20 @@ int main()
|
||||
|
||||
/* list the names in ns in phonebook order */
|
||||
|
||||
std::cout<<"Phonenook order\n"
|
||||
<<"---------------"<<std::endl;
|
||||
for(name_record_set::iterator it=ns.begin();it!=ns.end();++it){
|
||||
std::cout<<it->name()<<std::endl;
|
||||
}
|
||||
|
||||
/* list the names in ns according to their length*/
|
||||
|
||||
std::cout<<"\nLength order\n"
|
||||
<< "------------"<<std::endl;
|
||||
for(nth_index<name_record_set,1>::type::iterator it1=get<1>(ns).begin();
|
||||
it1!=get<1>(ns).end();++it1){
|
||||
std::cout<<it1->name()<<std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex example of use of hashed indices.
|
||||
*
|
||||
* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -66,6 +66,8 @@ typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
|
||||
|
||||
int main()
|
||||
{
|
||||
/* boostinspect:noascii */
|
||||
|
||||
std::string text=
|
||||
"En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha "
|
||||
"mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga "
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
/* Boost.MultiIndex example of use of Boost.Interprocess allocators.
|
||||
*
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
|
||||
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/interprocess/allocators/allocator.hpp>
|
||||
#include <boost/interprocess/containers/string.hpp>
|
||||
#include <boost/interprocess/managed_mapped_file.hpp>
|
||||
#include <boost/interprocess/sync/named_mutex.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using boost::multi_index_container;
|
||||
using namespace boost::multi_index;
|
||||
namespace bip=boost::interprocess;
|
||||
|
||||
/* shared_string is a string type placeable in shared memory,
|
||||
* courtesy of Boost.Interprocess.
|
||||
*/
|
||||
|
||||
typedef bip::basic_string<
|
||||
char,std::char_traits<char>,
|
||||
bip::allocator<char,bip::managed_mapped_file::segment_manager>
|
||||
> shared_string;
|
||||
|
||||
/* Book record. All its members can be placed in shared memory,
|
||||
* hence the structure itself can too.
|
||||
*/
|
||||
|
||||
struct book
|
||||
{
|
||||
shared_string name;
|
||||
shared_string author;
|
||||
unsigned pages;
|
||||
unsigned prize;
|
||||
|
||||
book(const shared_string::allocator_type& al):
|
||||
name(al),author(al),pages(0),prize(0)
|
||||
{}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os,const book& b)
|
||||
{
|
||||
os<<b.author<<": \""<<b.name<<"\", $"<<b.prize<<", "<<b.pages<<" pages\n";
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
/* partial_str_less allows for partial searches taking into account
|
||||
* only the first n chars of the strings compared against. See
|
||||
* Tutorial: Basics: Special lookup operations for more info on this
|
||||
* type of comparison functors.
|
||||
*/
|
||||
|
||||
/* partial_string is a mere string holder used to differentiate from
|
||||
* a plain string.
|
||||
*/
|
||||
|
||||
struct partial_string
|
||||
{
|
||||
partial_string(const shared_string& str):str(str){}
|
||||
shared_string str;
|
||||
};
|
||||
|
||||
struct partial_str_less
|
||||
{
|
||||
bool operator()(const shared_string& x,const shared_string& y)const
|
||||
{
|
||||
return x<y;
|
||||
}
|
||||
|
||||
bool operator()(const shared_string& x,const partial_string& y)const
|
||||
{
|
||||
return x.substr(0,y.str.size())<y.str;
|
||||
}
|
||||
|
||||
bool operator()(const partial_string& x,const shared_string& y)const
|
||||
{
|
||||
return x.str<y.substr(0,x.str.size());
|
||||
}
|
||||
};
|
||||
|
||||
/* Define a multi_index_container of book records with indices on
|
||||
* author, name and prize. The index on names allows for partial
|
||||
* searches. This container can be placed in shared memory because:
|
||||
* * book can be placed in shared memory.
|
||||
* * We are using a Boost.Interprocess specific allocator.
|
||||
*/
|
||||
|
||||
/* see Compiler specifics: Use of member_offset for info on
|
||||
* BOOST_MULTI_INDEX_MEMBER
|
||||
*/
|
||||
|
||||
typedef multi_index_container<
|
||||
book,
|
||||
indexed_by<
|
||||
ordered_non_unique<
|
||||
BOOST_MULTI_INDEX_MEMBER(book,shared_string,author)
|
||||
>,
|
||||
ordered_non_unique<
|
||||
BOOST_MULTI_INDEX_MEMBER(book,shared_string,name),
|
||||
partial_str_less
|
||||
>,
|
||||
ordered_non_unique<
|
||||
BOOST_MULTI_INDEX_MEMBER(book,unsigned,prize)
|
||||
>
|
||||
>,
|
||||
bip::allocator<book,bip::managed_mapped_file::segment_manager>
|
||||
> book_container;
|
||||
|
||||
/* A small utility to get data entered via std::cin */
|
||||
|
||||
template<typename T>
|
||||
void enter(const char* msg,T& t)
|
||||
{
|
||||
std::cout<<msg;
|
||||
std::string str;
|
||||
std::getline(std::cin,str);
|
||||
std::istringstream iss(str);
|
||||
iss>>t;
|
||||
}
|
||||
|
||||
void enter(const char* msg,std::string& str)
|
||||
{
|
||||
std::cout<<msg;
|
||||
std::getline(std::cin,str);
|
||||
}
|
||||
|
||||
void enter(const char* msg,shared_string& str)
|
||||
{
|
||||
std::cout<<msg;
|
||||
std::string stdstr;
|
||||
std::getline(std::cin,stdstr);
|
||||
str=stdstr.c_str();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
/* Create (or open) the memory mapped file where the book container
|
||||
* is stored, along with a mutex for synchronized access.
|
||||
*/
|
||||
|
||||
bip::managed_mapped_file seg(
|
||||
bip::open_or_create,"./book_container.db",
|
||||
65536);
|
||||
bip::named_mutex mutex(
|
||||
bip::open_or_create,"7FD6D7E8-320B-11DC-82CF-F0B655D89593");
|
||||
|
||||
/* create or open the book container in shared memory */
|
||||
|
||||
book_container* pbc=seg.find_or_construct<book_container>("book container")(
|
||||
book_container::ctor_args_list(),
|
||||
book_container::allocator_type(seg.get_segment_manager()));
|
||||
|
||||
std::string command_info=
|
||||
"1. list books by author\n"
|
||||
"2. list all books by prize\n"
|
||||
"3. insert a book\n"
|
||||
"4. delete a book\n"
|
||||
"0. exit\n";
|
||||
|
||||
std::cout<<command_info;
|
||||
|
||||
/* main loop */
|
||||
|
||||
for(bool exit=false;!exit;){
|
||||
int command=-1;
|
||||
enter("command: ",command);
|
||||
|
||||
switch(command){
|
||||
case 0:{ /* exit */
|
||||
exit=true;
|
||||
break;
|
||||
}
|
||||
case 1:{ /* list books by author */
|
||||
std::string author;
|
||||
enter("author (empty=all authors): ",author);
|
||||
|
||||
/* operations with the container must be mutex protected */
|
||||
|
||||
bip::scoped_lock<bip::named_mutex> lock(mutex);
|
||||
|
||||
std::pair<book_container::iterator,book_container::iterator> rng;
|
||||
if(author.empty()){
|
||||
rng=std::make_pair(pbc->begin(),pbc->end());
|
||||
}
|
||||
else{
|
||||
rng=pbc->equal_range(
|
||||
shared_string(
|
||||
author.c_str(),
|
||||
shared_string::allocator_type(seg.get_segment_manager())));
|
||||
}
|
||||
|
||||
if(rng.first==rng.second){
|
||||
std::cout<<"no entries\n";
|
||||
}
|
||||
else{
|
||||
std::copy(
|
||||
rng.first,rng.second,std::ostream_iterator<book>(std::cout));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:{ /* list all books by prize */
|
||||
bip::scoped_lock<bip::named_mutex> lock(mutex);
|
||||
|
||||
std::copy(
|
||||
get<2>(*pbc).begin(),get<2>(*pbc).end(),
|
||||
std::ostream_iterator<book>(std::cout));
|
||||
break;
|
||||
}
|
||||
case 3:{ /* insert a book */
|
||||
book b(shared_string::allocator_type(seg.get_segment_manager()));
|
||||
|
||||
enter("author: ",b.author);
|
||||
enter("name: " ,b.name);
|
||||
enter("prize: " ,b.prize);
|
||||
enter("pages: " ,b.pages);
|
||||
|
||||
std::cout<<"insert the following?\n"<<b<<"(y/n): ";
|
||||
char yn='n';
|
||||
enter("",yn);
|
||||
if(yn=='y'||yn=='Y'){
|
||||
bip::scoped_lock<bip::named_mutex> lock(mutex);
|
||||
pbc->insert(b);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 4:{ /* delete a book */
|
||||
shared_string name(
|
||||
shared_string::allocator_type(seg.get_segment_manager()));
|
||||
enter(
|
||||
"name of the book (you can enter\nonly the first few characters): ",
|
||||
name);
|
||||
|
||||
typedef nth_index<book_container,1>::type index_by_name;
|
||||
index_by_name& idx=get<1>(*pbc);
|
||||
index_by_name::iterator it;
|
||||
book b(shared_string::allocator_type(seg.get_segment_manager()));
|
||||
|
||||
{
|
||||
/* Look for a book whose title begins with name. Note that we
|
||||
* are unlocking after doing the search so as to not leave the
|
||||
* container blocked during user prompting. That is also why a
|
||||
* local copy of the book is done.
|
||||
*/
|
||||
|
||||
bip::scoped_lock<bip::named_mutex> lock(mutex);
|
||||
|
||||
it=idx.find(partial_string(name));
|
||||
if(it==idx.end()){
|
||||
std::cout<<"no such book found\n";
|
||||
break;
|
||||
}
|
||||
b=*it;
|
||||
}
|
||||
|
||||
std::cout<<"delete the following?\n"<<b<<"(y/n): ";
|
||||
char yn='n';
|
||||
enter("",yn);
|
||||
if(yn=='y'||yn=='Y'){
|
||||
bip::scoped_lock<bip::named_mutex> lock(mutex);
|
||||
idx.erase(it);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
std::cout<<"select one option:\n"<<command_info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex example of use of multi_index_container::ctor_args_list.
|
||||
*
|
||||
* Copyright 2003-2004 Joaqu匤 M L�ez Mu�z.
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/* Boost.MultiIndex example of use of random access indices.
|
||||
*
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
|
||||
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
|
||||
#endif
|
||||
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/identity.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index/random_access_index.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
using boost::multi_index_container;
|
||||
using namespace boost::multi_index;
|
||||
|
||||
/* text_container holds words as inserted and also keep them indexed
|
||||
* by dictionary order.
|
||||
*/
|
||||
|
||||
typedef multi_index_container<
|
||||
std::string,
|
||||
indexed_by<
|
||||
random_access<>,
|
||||
ordered_non_unique<identity<std::string> >
|
||||
>
|
||||
> text_container;
|
||||
|
||||
/* ordered index */
|
||||
|
||||
typedef nth_index<text_container,1>::type ordered_text;
|
||||
|
||||
/* Helper function for obtaining the position of an element in the
|
||||
* container.
|
||||
*/
|
||||
|
||||
template<typename IndexIterator>
|
||||
text_container::size_type text_position(
|
||||
const text_container& tc,IndexIterator it)
|
||||
{
|
||||
/* project to the base index and calculate offset from begin() */
|
||||
|
||||
return project<0>(tc,it)-tc.begin();
|
||||
}
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string text=
|
||||
"'Oh, you wicked little thing!' cried Alice, catching up the kitten, "
|
||||
"and giving it a little kiss to make it understand that it was in "
|
||||
"disgrace. 'Really, Dinah ought to have taught you better manners! You "
|
||||
"ought, Dinah, you know you ought!' she added, looking reproachfully at "
|
||||
"the old cat, and speaking in as cross a voice as she could manage "
|
||||
"-- and then she scrambled back into the armchair, taking the kitten and "
|
||||
"the worsted with her, and began winding up the ball again. But she "
|
||||
"didn't get on very fast, as she was talking all the time, sometimes to "
|
||||
"the kitten, and sometimes to herself. Kitty sat very demurely on her "
|
||||
"knee, pretending to watch the progress of the winding, and now and then "
|
||||
"putting out one paw and gently touching the ball, as if it would be glad "
|
||||
"to help, if it might.";
|
||||
|
||||
/* feed the text into the container */
|
||||
|
||||
text_container tc;
|
||||
tc.reserve(text.size()); /* makes insertion faster */
|
||||
text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
|
||||
std::copy(tok.begin(),tok.end(),std::back_inserter(tc));
|
||||
|
||||
std::cout<<"enter a position (0-"<<tc.size()-1<<"):";
|
||||
text_container::size_type pos=tc.size();
|
||||
std::cin>>pos;
|
||||
if(pos>=tc.size()){
|
||||
std::cout<<"out of bounds"<<std::endl;
|
||||
}
|
||||
else{
|
||||
std::cout<<"the word \""<<tc[pos]<<"\" appears at position(s): ";
|
||||
|
||||
std::pair<ordered_text::iterator,ordered_text::iterator> p=
|
||||
get<1>(tc).equal_range(tc[pos]);
|
||||
while(p.first!=p.second){
|
||||
std::cout<<text_position(tc,p.first++)<<" ";
|
||||
}
|
||||
|
||||
std::cout<<std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/* Boost.MultiIndex example of use of rearrange facilities.
|
||||
*
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
|
||||
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/random_access_index.hpp>
|
||||
#include <boost/random/binomial_distribution.hpp>
|
||||
#include <boost/random/uniform_real.hpp>
|
||||
#include <boost/random/mersenne_twister.hpp>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
using boost::multi_index_container;
|
||||
using namespace boost::multi_index;
|
||||
|
||||
/* We model a card deck with a random access array containing
|
||||
* card numbers (from 0 to 51), supplemented with an additional
|
||||
* index which retains the start ordering.
|
||||
*/
|
||||
|
||||
class deck
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t,num_cards=52);
|
||||
|
||||
typedef multi_index_container<
|
||||
int,
|
||||
indexed_by<
|
||||
random_access<>, /* base index */
|
||||
random_access<> /* "start" index */
|
||||
>
|
||||
> container_type;
|
||||
container_type cont;
|
||||
|
||||
public:
|
||||
deck()
|
||||
{
|
||||
cont.reserve(num_cards);
|
||||
get<1>(cont).reserve(num_cards);
|
||||
for(std::size_t i=0;i<num_cards;++i)cont.push_back(i);
|
||||
}
|
||||
|
||||
typedef container_type::iterator iterator;
|
||||
typedef container_type::size_type size_type;
|
||||
|
||||
iterator begin()const{return cont.begin();}
|
||||
iterator end()const{return cont.end();}
|
||||
size_type size()const{return cont.size();}
|
||||
|
||||
template<typename InputIterator>
|
||||
void rearrange(InputIterator it)
|
||||
{
|
||||
cont.rearrange(it);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
/* simply rearrange the base index like the start index */
|
||||
|
||||
cont.rearrange(get<1>(cont).begin());
|
||||
}
|
||||
|
||||
std::size_t position(int i)const
|
||||
{
|
||||
/* The position of a card in the deck is calculated by locating
|
||||
* the card through the start index (which is ordered), projecting
|
||||
* to the base index and diffing with the begin position.
|
||||
* Resulting complexity: constant.
|
||||
*/
|
||||
|
||||
return project<0>(cont,get<1>(cont).begin()+i)-cont.begin();
|
||||
}
|
||||
|
||||
std::size_t rising_sequences()const
|
||||
{
|
||||
/* Iterate through all cards and increment the sequence count
|
||||
* when the current position is left to the previous.
|
||||
* Resulting complexity: O(n), n=num_cards.
|
||||
*/
|
||||
|
||||
std::size_t s=1;
|
||||
std::size_t last_pos=0;
|
||||
|
||||
for(std::size_t i=0;i<num_cards;++i){
|
||||
std::size_t pos=position(i);
|
||||
if(pos<last_pos)++s;
|
||||
last_pos=pos;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
/* A vector of reference_wrappers to deck elements can be used
|
||||
* as a view to the deck container.
|
||||
* We use a special implicit_reference_wrapper having implicit
|
||||
* ctor from its base type, as this simplifies the use of generic
|
||||
* techniques on the resulting data structures.
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
class implicit_reference_wrapper:public boost::reference_wrapper<T>
|
||||
{
|
||||
private:
|
||||
typedef boost::reference_wrapper<T> super;
|
||||
public:
|
||||
implicit_reference_wrapper(T& t):super(t){}
|
||||
};
|
||||
|
||||
typedef std::vector<implicit_reference_wrapper<const int> > deck_view;
|
||||
|
||||
/* Riffle shuffle is modeled like this: A cut is selected in the deck
|
||||
* following a binomial distribution. Then, cards are randomly selected
|
||||
* from one packet or the other with probability proportional to
|
||||
* packet size.
|
||||
*/
|
||||
|
||||
template<typename RandomAccessIterator,typename OutputIterator>
|
||||
void riffle_shuffle(
|
||||
RandomAccessIterator first,RandomAccessIterator last,
|
||||
OutputIterator out)
|
||||
{
|
||||
static boost::mt19937 rnd_gen;
|
||||
|
||||
typedef typename boost::detail::iterator_traits<
|
||||
RandomAccessIterator>::difference_type difference_type;
|
||||
typedef boost::binomial_distribution<
|
||||
difference_type> rnd_cut_select_type;
|
||||
typedef boost::uniform_real<> rnd_deck_select_type;
|
||||
|
||||
rnd_cut_select_type cut_select(last-first);
|
||||
RandomAccessIterator middle=first+cut_select(rnd_gen);
|
||||
difference_type s0=middle-first;
|
||||
difference_type s1=last-middle;
|
||||
rnd_deck_select_type deck_select;
|
||||
|
||||
while(s0!=0&&s1!=0){
|
||||
if(deck_select(rnd_gen)<(double)s0/(s0+s1)){
|
||||
*out++=*first++;
|
||||
--s0;
|
||||
}
|
||||
else{
|
||||
*out++=*middle++;
|
||||
--s1;
|
||||
}
|
||||
}
|
||||
std::copy(first,first+s0,out);
|
||||
std::copy(middle,middle+s1,out);
|
||||
}
|
||||
|
||||
struct riffle_shuffler
|
||||
{
|
||||
void operator()(deck& d)const
|
||||
{
|
||||
dv.clear();
|
||||
dv.reserve(d.size());
|
||||
riffle_shuffle(
|
||||
d.begin(),d.end(),std::back_inserter(dv)); /* do the shuffling */
|
||||
d.rearrange(dv.begin()); /* apply to the deck */
|
||||
}
|
||||
|
||||
private:
|
||||
mutable deck_view dv;
|
||||
};
|
||||
|
||||
/* A truly random shuffle (up to stdlib implementation quality) using
|
||||
* std::random_shuffle.
|
||||
*/
|
||||
|
||||
struct random_shuffler
|
||||
{
|
||||
void operator()(deck& d)const
|
||||
{
|
||||
dv.clear();
|
||||
dv.reserve(d.size());
|
||||
std::copy(d.begin(),d.end(),std::back_inserter(dv));
|
||||
std::random_shuffle(dv.begin(),dv.end()); /* do the shuffling */
|
||||
d.rearrange(dv.begin()); /* apply to the deck */
|
||||
}
|
||||
|
||||
private:
|
||||
mutable deck_view dv;
|
||||
};
|
||||
|
||||
/* Repeat a given shuffling algorithm repeats_num times
|
||||
* and obtain the resulting rising sequences number. Average
|
||||
* for tests_num trials.
|
||||
*/
|
||||
|
||||
template<typename Shuffler>
|
||||
double shuffle_test(
|
||||
unsigned int repeats_num,unsigned int tests_num
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Shuffler))
|
||||
{
|
||||
deck d;
|
||||
Shuffler sh;
|
||||
unsigned long total=0;
|
||||
|
||||
for(unsigned int n=0;n<tests_num;++n){
|
||||
for(unsigned m=0;m<repeats_num;++m)sh(d);
|
||||
total+=d.rising_sequences();
|
||||
d.reset();
|
||||
}
|
||||
|
||||
return (double)total/tests_num;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned rifs_num=0;
|
||||
unsigned tests_num=0;
|
||||
|
||||
std::cout<<"number of riffle shuffles (vg 5):";
|
||||
std::cin>>rifs_num;
|
||||
std::cout<<"number of tests (vg 1000):";
|
||||
std::cin>>tests_num;
|
||||
|
||||
std::cout<<"shuffling..."<<std::endl;
|
||||
|
||||
std::cout<<"riffle shuffling\n"
|
||||
" avg number of rising sequences: "
|
||||
<<shuffle_test<riffle_shuffler>(rifs_num,tests_num)
|
||||
<<std::endl;
|
||||
|
||||
std::cout<<"random shuffling\n"
|
||||
" avg number of rising sequences: "
|
||||
<<shuffle_test<random_shuffler>(1,tests_num)
|
||||
<<std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex example of use of sequenced indices.
|
||||
*
|
||||
* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex example of serialization of a MRU list.
|
||||
*
|
||||
* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
typedef Item item_type;
|
||||
typedef typename item_list::iterator iterator;
|
||||
|
||||
mru_list(std::size_t max_num_items):max_num_items(max_num_items){}
|
||||
mru_list(std::size_t max_num_items_):max_num_items(max_num_items_){}
|
||||
|
||||
void insert(const item_type& item)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2011 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,6 +14,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
#include <boost/multi_index/detail/access_specifier.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
@@ -29,8 +30,17 @@
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <functional>
|
||||
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
#include <boost/ref.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#endif
|
||||
|
||||
/* A composite key stores n key extractors and "computes" the
|
||||
* result on a given value as a packed reference to the value and
|
||||
* the composite key itself. Actual invocations to the component
|
||||
@@ -97,7 +107,6 @@
|
||||
namespace boost{
|
||||
|
||||
template<class T> class reference_wrapper; /* fwd decl. */
|
||||
template<class T> struct hash; /* fwd decl. */
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
@@ -554,6 +563,11 @@ struct hash_cval:
|
||||
|
||||
/* composite_key_result */
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4512)
|
||||
#endif
|
||||
|
||||
template<typename CompositeKey>
|
||||
struct composite_key_result
|
||||
{
|
||||
@@ -569,6 +583,10 @@ struct composite_key_result
|
||||
const value_type& value;
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/* composite_key */
|
||||
|
||||
/* NB. Some overloads of operator() have an extra dummy parameter int=0.
|
||||
@@ -607,7 +625,15 @@ public:
|
||||
key_extractor_tuple& key_extractors(){return *this;}
|
||||
|
||||
template<typename ChainedPtr>
|
||||
result_type operator()(const ChainedPtr& x)const
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
typename disable_if<
|
||||
is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
|
||||
#else
|
||||
result_type
|
||||
#endif
|
||||
|
||||
operator()(const ChainedPtr& x)const
|
||||
{
|
||||
return operator()(*x);
|
||||
}
|
||||
@@ -966,6 +992,16 @@ public:
|
||||
key_comps());
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
template<typename CompositeKey,typename Value>
|
||||
bool operator()(
|
||||
const composite_key_result<CompositeKey>& x,
|
||||
const Value& y)const
|
||||
{
|
||||
return operator()(x,boost::make_tuple(boost::cref(y)));
|
||||
}
|
||||
#endif
|
||||
|
||||
template
|
||||
<
|
||||
typename CompositeKey,
|
||||
@@ -991,6 +1027,16 @@ public:
|
||||
>::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
template<typename Value,typename CompositeKey>
|
||||
bool operator()(
|
||||
const Value& x,
|
||||
const composite_key_result<CompositeKey>& y)const
|
||||
{
|
||||
return operator()(boost::make_tuple(boost::cref(x)),y);
|
||||
}
|
||||
#endif
|
||||
|
||||
template
|
||||
<
|
||||
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -34,12 +34,19 @@
|
||||
* MSVC 7.1/8.0 seem to have a similar problem, though the conditions in
|
||||
* which the error happens are not that simple. I have yet to isolate this
|
||||
* into a snippet suitable for bug reporting.
|
||||
* Sun Studio also has this problem, which might be related, from the
|
||||
* information gathered at Sun forums, with a known issue notified at the
|
||||
* internal bug report 6421933. The bug is present up to Studio Express 2,
|
||||
* the latest preview version of the future Sun Studio 12. As of this writing
|
||||
* (October 2006) it is not known whether a fix will finally make it into the
|
||||
* official Sun Studio 12.
|
||||
*/
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, <3)||\
|
||||
BOOST_WORKAROUND(__GNUC__,==3)&&(__GNUC_MINOR__<4)||\
|
||||
BOOST_WORKAROUND(BOOST_MSVC,==1310)||\
|
||||
BOOST_WORKAROUND(BOOST_MSVC,==1400)
|
||||
BOOST_WORKAROUND(BOOST_MSVC,==1400)||\
|
||||
BOOST_WORKAROUND(__SUNPRO_CC,BOOST_TESTED_AT(0x590))
|
||||
#define BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS public
|
||||
#else
|
||||
#define BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS private
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_ADL_SWAP_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_ADL_SWAP_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template<typename T>
|
||||
void adl_swap(T& x,T& y)
|
||||
{
|
||||
|
||||
#if !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)
|
||||
using std::swap;
|
||||
swap(x,y);
|
||||
#else
|
||||
std::swap(x,y);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,10 +14,11 @@
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/aligned_storage.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
@@ -63,10 +64,10 @@ struct archive_constructed:private noncopyable
|
||||
(&get())->~T();
|
||||
}
|
||||
|
||||
T& get(){return *static_cast<T*>(space.address());}
|
||||
T& get(){return *static_cast<T*>(static_cast<void*>(&space));}
|
||||
|
||||
private:
|
||||
aligned_storage<sizeof(T)> space;
|
||||
typename aligned_storage<sizeof(T),alignment_of<T>::value>::type space;
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/detail/allocator_utilities.hpp>
|
||||
#include <boost/multi_index/detail/adl_swap.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <memory>
|
||||
|
||||
@@ -44,8 +46,15 @@ namespace detail{
|
||||
template<typename T,typename Allocator=std::allocator<T> >
|
||||
struct auto_space:private noncopyable
|
||||
{
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,T
|
||||
>::type
|
||||
>::type::pointer pointer;
|
||||
|
||||
explicit auto_space(const Allocator& al=Allocator(),std::size_t n=1):
|
||||
al_(al),n_(n),data_(n_?al_.allocate(n_):0)
|
||||
al_(al),n_(n),data_(n_?al_.allocate(n_):pointer(0))
|
||||
{}
|
||||
|
||||
~auto_space()
|
||||
@@ -53,10 +62,13 @@ struct auto_space:private noncopyable
|
||||
if(n_)al_.deallocate(data_,n_);
|
||||
}
|
||||
|
||||
T* data()const{return data_;}
|
||||
Allocator get_allocator()const{return al_;}
|
||||
|
||||
pointer data()const{return data_;}
|
||||
|
||||
void swap(auto_space& x)
|
||||
{
|
||||
if(al_!=x.al_)adl_swap(al_,x.al_);
|
||||
std::swap(n_,x.n_);
|
||||
std::swap(data_,x.data_);
|
||||
}
|
||||
@@ -65,7 +77,7 @@ private:
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,T>::type al_;
|
||||
std::size_t n_;
|
||||
T* data_;
|
||||
pointer data_;
|
||||
};
|
||||
|
||||
template<typename T,typename Allocator>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -46,12 +46,12 @@ struct index_applier
|
||||
#else
|
||||
struct index_applier
|
||||
{
|
||||
template<typename IndexSpecifierMeta,typename Super>
|
||||
template<typename IndexSpecifierMeta,typename SuperMeta>
|
||||
struct apply
|
||||
{
|
||||
typedef typename IndexSpecifierMeta::type index_specifier;
|
||||
typedef typename IndexSpecifierMeta::type index_specifier;
|
||||
typedef typename index_specifier::
|
||||
BOOST_NESTED_TEMPLATE index_class<Super>::type type;
|
||||
BOOST_NESTED_TEMPLATE index_class<SuperMeta>::type type;
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_BIDIR_NODE_ITERATOR_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_BIDIR_NODE_ITERATOR_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* Iterator class for node-based indices with bidirectional
|
||||
* iterators (ordered and sequenced indices.)
|
||||
*/
|
||||
|
||||
template<typename Node>
|
||||
class bidir_node_iterator:
|
||||
public bidirectional_iterator_helper<
|
||||
bidir_node_iterator<Node>,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
const typename Node::value_type*,
|
||||
const typename Node::value_type&>
|
||||
{
|
||||
public:
|
||||
bidir_node_iterator(){}
|
||||
explicit bidir_node_iterator(Node* node_):node(node_){}
|
||||
|
||||
const typename Node::value_type& operator*()const
|
||||
{
|
||||
return node->value();
|
||||
}
|
||||
|
||||
bidir_node_iterator& operator++()
|
||||
{
|
||||
Node::increment(node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bidir_node_iterator& operator--()
|
||||
{
|
||||
Node::decrement(node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
/* Serialization. As for why the following is public,
|
||||
* see explanation in safe_mode_iterator notes in safe_mode.hpp.
|
||||
*/
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
typedef typename Node::base_type node_base_type;
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive& ar,const unsigned int)const
|
||||
{
|
||||
node_base_type* bnode=node;
|
||||
ar<<serialization::make_nvp("pointer",bnode);
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive& ar,const unsigned int)
|
||||
{
|
||||
node_base_type* bnode;
|
||||
ar>>serialization::make_nvp("pointer",bnode);
|
||||
node=static_cast<Node*>(bnode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get_node is not to be used by the user */
|
||||
|
||||
typedef Node node_type;
|
||||
|
||||
Node* get_node()const{return node;}
|
||||
|
||||
private:
|
||||
Node* node;
|
||||
};
|
||||
|
||||
template<typename Node>
|
||||
bool operator==(
|
||||
const bidir_node_iterator<Node>& x,
|
||||
const bidir_node_iterator<Node>& y)
|
||||
{
|
||||
return x.get_node()==y.get_node();
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <algorithm>
|
||||
#include <boost/multi_index/detail/auto_space.hpp>
|
||||
#include <boost/multi_index/detail/hash_index_node.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <cstddef>
|
||||
#include <limits.h>
|
||||
@@ -84,8 +85,20 @@ protected:
|
||||
template<typename Allocator>
|
||||
class bucket_array:public bucket_array_base
|
||||
{
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
hashed_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type node_impl_type;
|
||||
|
||||
public:
|
||||
bucket_array(const Allocator& al,hashed_index_node_impl* end_,std::size_t size):
|
||||
typedef typename node_impl_type::pointer pointer;
|
||||
|
||||
bucket_array(const Allocator& al,pointer end_,std::size_t size):
|
||||
size_(bucket_array_base::next_prime(size)),
|
||||
spc(al,size_+1)
|
||||
{
|
||||
@@ -104,21 +117,21 @@ public:
|
||||
return hash%size_;
|
||||
}
|
||||
|
||||
hashed_index_node_impl* begin()const{return &buckets()[0];}
|
||||
hashed_index_node_impl* end()const{return &buckets()[size_];}
|
||||
hashed_index_node_impl* at(std::size_t n)const{return &buckets()[n];}
|
||||
pointer begin()const{return buckets();}
|
||||
pointer end()const{return buckets()+size_;}
|
||||
pointer at(std::size_t n)const{return buckets()+n;}
|
||||
|
||||
std::size_t first_nonempty(std::size_t n)const
|
||||
{
|
||||
for(;;++n){
|
||||
hashed_index_node_impl* x=at(n);
|
||||
pointer x=at(n);
|
||||
if(x->next()!=x)return n;
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for(hashed_index_node_impl* x=begin(),*y=end();x!=y;++x)x->next()=x;
|
||||
for(pointer x=begin(),y=end();x!=y;++x)x->next()=x;
|
||||
}
|
||||
|
||||
void swap(bucket_array& x)
|
||||
@@ -128,10 +141,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t size_;
|
||||
auto_space<hashed_index_node_impl,Allocator> spc;
|
||||
std::size_t size_;
|
||||
auto_space<node_impl_type,Allocator> spc;
|
||||
|
||||
hashed_index_node_impl* buckets()const
|
||||
pointer buckets()const
|
||||
{
|
||||
return spc.data();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <algorithm>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/multi_index/detail/auto_space.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
@@ -69,31 +70,31 @@ public:
|
||||
{
|
||||
if(!released){
|
||||
for(std::size_t i=0;i<n;++i){
|
||||
boost::detail::allocator::destroy(&spc.data()[i].second->value);
|
||||
deallocate(spc.data()[i].second);
|
||||
boost::detail::allocator::destroy(&(spc.data()+i)->second->value());
|
||||
deallocate((spc.data()+i)->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const_iterator begin()const{return spc.data();}
|
||||
const_iterator end()const{return spc.data()+n;}
|
||||
const_iterator begin()const{return &*spc.data();}
|
||||
const_iterator end()const{return &*(spc.data()+n);}
|
||||
|
||||
void clone(Node* node)
|
||||
{
|
||||
spc.data()[n].first=node;
|
||||
spc.data()[n].second=al_.allocate(1);
|
||||
(spc.data()+n)->first=node;
|
||||
(spc.data()+n)->second=&*al_.allocate(1);
|
||||
BOOST_TRY{
|
||||
boost::detail::allocator::construct(
|
||||
&spc.data()[n].second->value,node->value);
|
||||
&(spc.data()+n)->second->value(),node->value());
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
deallocate(spc.data()[n].second);
|
||||
deallocate((spc.data()+n)->second);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
++n;
|
||||
|
||||
if(n==size_)std::sort(spc.data(),spc.data()+size_);
|
||||
if(n==size_)std::sort(&*spc.data(),&*spc.data()+size_);
|
||||
}
|
||||
|
||||
Node* find(Node* node)const
|
||||
@@ -109,18 +110,24 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,Node>::type al_;
|
||||
std::size_t size_;
|
||||
auto_space<copy_map_entry<Node>,Allocator> spc;
|
||||
std::size_t n;
|
||||
Node* header_org_;
|
||||
Node* header_cpy_;
|
||||
bool released;
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,Node>::type
|
||||
>::type allocator_type;
|
||||
typedef typename allocator_type::pointer allocator_pointer;
|
||||
|
||||
allocator_type al_;
|
||||
std::size_t size_;
|
||||
auto_space<copy_map_entry<Node>,Allocator> spc;
|
||||
std::size_t n;
|
||||
Node* header_org_;
|
||||
Node* header_cpy_;
|
||||
bool released;
|
||||
|
||||
void deallocate(Node* node)
|
||||
{
|
||||
al_.deallocate(node,1);
|
||||
al_.deallocate(static_cast<allocator_pointer>(node),1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_DEF_CTOR_TUPLE_CONS_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_DEF_CTOR_TUPLE_CONS_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
/* In MSVC, tuples::cons is not default constructible. We provide a
|
||||
* tiny wrapper around tuple::cons filling that hole.
|
||||
*/
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template<typename Cons>
|
||||
struct default_constructible_tuple_cons:Cons
|
||||
{
|
||||
default_constructible_tuple_cons():
|
||||
Cons(
|
||||
Cons::head_type(),
|
||||
static_cast<const Cons::tail_type&>(
|
||||
default_constructible_tuple_cons<Cons::tail_type>()))
|
||||
{}
|
||||
|
||||
default_constructible_tuple_cons(const Cons& cons):Cons(cons){}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct default_constructible_tuple_cons<tuples::null_type>:tuples::null_type
|
||||
{
|
||||
default_constructible_tuple_cons(){}
|
||||
default_constructible_tuple_cons(const tuples::null_type&){}
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_MSVC */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -37,25 +37,25 @@ public:
|
||||
typedef const typename Node::value_type& reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
duplicates_iterator(Node* node,Node* end,Predicate pred):
|
||||
node(node),begin_chunk(0),end(end),pred(pred)
|
||||
duplicates_iterator(Node* node_,Node* end_,Predicate pred_):
|
||||
node(node_),begin_chunk(0),end(end_),pred(pred_)
|
||||
{
|
||||
advance();
|
||||
}
|
||||
|
||||
duplicates_iterator(Node* end,Predicate pred):
|
||||
node(end),begin_chunk(end),end(end),pred(pred)
|
||||
duplicates_iterator(Node* end_,Predicate pred_):
|
||||
node(end_),begin_chunk(end_),end(end_),pred(pred_)
|
||||
{
|
||||
}
|
||||
|
||||
reference operator*()const
|
||||
{
|
||||
return node->value;
|
||||
return node->value();
|
||||
}
|
||||
|
||||
pointer operator->()const
|
||||
{
|
||||
return node->value;
|
||||
return &node->value();
|
||||
}
|
||||
|
||||
duplicates_iterator& operator++()
|
||||
@@ -77,15 +77,14 @@ public:
|
||||
private:
|
||||
void sync()
|
||||
{
|
||||
if(pred(begin_chunk->value,node->value))advance();
|
||||
if(node!=end&&pred(begin_chunk->value(),node->value()))advance();
|
||||
}
|
||||
|
||||
void advance()
|
||||
{
|
||||
for(Node* node2=node;node!=end;node=node2){
|
||||
Node::increment(node2);
|
||||
if(node2!=end&&!pred(node->value,node2->value))break;
|
||||
node=node2;
|
||||
if(node2!=end&&!pred(node->value(),node2->value()))break;
|
||||
}
|
||||
begin_chunk=node;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,7 +14,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/functional/hash/hash.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/mpl/aux_/na.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
@@ -26,8 +26,6 @@
|
||||
|
||||
namespace boost{
|
||||
|
||||
template<class T> struct hash; /* fwd decl. */
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,9 +14,6 @@
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/multi_index/detail/hash_index_proxy.hpp>
|
||||
#include <boost/multi_index/detail/safe_mode.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
@@ -30,144 +27,81 @@ namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* An iterator template for nodes of multi_index::detail::hashed_index.
|
||||
* Built with the aid boost::forward_iterator_helper from
|
||||
* boost/operators.hpp.
|
||||
/* Iterator class for hashed indices.
|
||||
*/
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
template<typename Node,typename BucketArray>
|
||||
class hashed_index_iterator:
|
||||
public boost::forward_iterator_helper<
|
||||
hashed_index_iterator<Node,BucketArray>,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
const typename Node::value_type*,
|
||||
const typename Node::value_type&>,
|
||||
public safe_iterator<hashed_index_proxy<Node,BucketArray> >
|
||||
#else
|
||||
template<typename Node,typename BucketArray,typename Container>
|
||||
class hashed_index_iterator:
|
||||
public boost::forward_iterator_helper<
|
||||
hashed_index_iterator<Node,BucketArray,Container>,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
const typename Node::value_type*,
|
||||
const typename Node::value_type&>,
|
||||
public safe_iterator<Container>
|
||||
#endif
|
||||
#else
|
||||
template<typename Node,typename BucketArray>
|
||||
class hashed_index_iterator:
|
||||
public boost::forward_iterator_helper<
|
||||
public forward_iterator_helper<
|
||||
hashed_index_iterator<Node,BucketArray>,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
const typename Node::value_type*,
|
||||
const typename Node::value_type&>
|
||||
#endif
|
||||
|
||||
{
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
public:
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
typedef hashed_index_proxy<Node,BucketArray> container_type;
|
||||
#else
|
||||
typedef Container container_type;
|
||||
#endif
|
||||
|
||||
private:
|
||||
typedef safe_iterator<container_type> safe_super;
|
||||
|
||||
public:
|
||||
hashed_index_iterator():node(0),buckets(0){}
|
||||
hashed_index_iterator(
|
||||
Node* node_,BucketArray& buckets_,container_type* cont_):
|
||||
safe_super(cont_),node(node_),buckets(&buckets_){}
|
||||
|
||||
hashed_index_iterator& operator=(const hashed_index_iterator& x)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
|
||||
safe_super::operator=(x);
|
||||
node=x.node;
|
||||
buckets=x.buckets;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#else
|
||||
public:
|
||||
hashed_index_iterator(){}
|
||||
hashed_index_iterator(Node* node_,BucketArray& buckets_):
|
||||
node(node_),buckets(&buckets_){}
|
||||
#endif
|
||||
hashed_index_iterator(Node* node_,BucketArray* buckets_):
|
||||
node(node_),buckets(buckets_)
|
||||
{}
|
||||
|
||||
const typename Node::value_type& operator*()const
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);
|
||||
return node->value;
|
||||
return node->value();
|
||||
}
|
||||
|
||||
hashed_index_iterator& operator++()
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);
|
||||
Node::increment(node,buckets->begin(),buckets->end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const hashed_index_iterator& x,const hashed_index_iterator& y)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(y);
|
||||
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(x,y);
|
||||
return x.node==y.node;
|
||||
}
|
||||
|
||||
/* get_node is not to be used by the user */
|
||||
|
||||
Node* get_node()const{return node;}
|
||||
|
||||
private:
|
||||
Node* node;
|
||||
BucketArray* buckets;
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
/* serialization */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
/* Serialization. As for why the following is public,
|
||||
* see explanation in safe_mode_iterator notes in safe_mode.hpp.
|
||||
*/
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
typedef typename Node::base_type node_base_type;
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive& ar,const unsigned int version)const
|
||||
void save(Archive& ar,const unsigned int)const
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
node_base_type* bnode=node;
|
||||
ar<<serialization::make_nvp("pointer",bnode);
|
||||
ar<<serialization::make_nvp("pointer",buckets);
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive& ar,const unsigned int version)
|
||||
void load(Archive& ar,const unsigned int)
|
||||
{
|
||||
node_base_type* bnode;
|
||||
ar>>serialization::make_nvp("pointer",bnode);
|
||||
node=static_cast<Node*>(bnode);
|
||||
ar>>serialization::make_nvp("pointer",buckets);
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
safe_super::uncheck();
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get_node is not to be used by the user */
|
||||
|
||||
typedef Node node_type;
|
||||
|
||||
Node* get_node()const{return node;}
|
||||
|
||||
private:
|
||||
Node* node;
|
||||
BucketArray* buckets;
|
||||
};
|
||||
|
||||
template<typename Node,typename BucketArray>
|
||||
bool operator==(
|
||||
const hashed_index_iterator<Node,BucketArray>& x,
|
||||
const hashed_index_iterator<Node,BucketArray>& y)
|
||||
{
|
||||
return x.get_node()==y.get_node();
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_ITERATOR_FWD_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_ITERATOR_FWD_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
template<typename Node,typename BucketArray>
|
||||
class hashed_index_iterator;
|
||||
#else
|
||||
template<typename Node,typename BucketArray,typename Container>
|
||||
class hashed_index_iterator;
|
||||
#endif
|
||||
#else
|
||||
template<typename Node,typename BucketArray>
|
||||
class hashed_index_iterator;
|
||||
#endif
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,6 +14,8 @@
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/detail/allocator_utilities.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace boost{
|
||||
@@ -24,28 +26,33 @@ namespace detail{
|
||||
|
||||
/* singly-linked node for use by hashed_index */
|
||||
|
||||
template<typename Allocator>
|
||||
struct hashed_index_node_impl
|
||||
{
|
||||
hashed_index_node_impl*& next(){return next_;}
|
||||
hashed_index_node_impl*const & next()const{return next_;}
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,hashed_index_node_impl
|
||||
>::type
|
||||
>::type::pointer pointer;
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,hashed_index_node_impl
|
||||
>::type
|
||||
>::type::const_pointer const_pointer;
|
||||
|
||||
/* interoperability with hashed_index_proxy */
|
||||
|
||||
static hashed_index_node_impl* end(hashed_index_node_impl* header)
|
||||
{
|
||||
return header;
|
||||
}
|
||||
pointer& next(){return next_;}
|
||||
pointer next()const{return next_;}
|
||||
|
||||
/* algorithmic stuff */
|
||||
|
||||
static void increment(
|
||||
hashed_index_node_impl*& x,
|
||||
hashed_index_node_impl* bbegin,hashed_index_node_impl* bbend)
|
||||
static void increment(pointer& x,pointer bbegin,pointer bend)
|
||||
{
|
||||
std::less_equal<hashed_index_node_impl*> leq;
|
||||
std::less_equal<pointer> leq;
|
||||
|
||||
x=x->next();
|
||||
if(leq(bbegin,x)&&leq(x,bbend)){ /* bucket node */
|
||||
if(leq(bbegin,x)&&leq(x,bend)){ /* bucket node */
|
||||
do{
|
||||
++x;
|
||||
}while(x->next()==x);
|
||||
@@ -53,76 +60,100 @@ struct hashed_index_node_impl
|
||||
}
|
||||
}
|
||||
|
||||
static void link(
|
||||
hashed_index_node_impl* x,hashed_index_node_impl* pos)
|
||||
static void link(pointer x,pointer pos)
|
||||
{
|
||||
x->next()=pos->next();
|
||||
pos->next()=x;
|
||||
};
|
||||
|
||||
static void unlink(hashed_index_node_impl* x)
|
||||
static void unlink(pointer x)
|
||||
{
|
||||
hashed_index_node_impl* y=x->next();
|
||||
pointer y=x->next();
|
||||
while(y->next()!=x){y=y->next();}
|
||||
y->next()=x->next();
|
||||
}
|
||||
|
||||
static hashed_index_node_impl* prev(hashed_index_node_impl* x)
|
||||
static pointer prev(pointer x)
|
||||
{
|
||||
hashed_index_node_impl* y=x->next();
|
||||
pointer y=x->next();
|
||||
while(y->next()!=x){y=y->next();}
|
||||
return y;
|
||||
}
|
||||
|
||||
static void unlink_next(hashed_index_node_impl* x)
|
||||
static void unlink_next(pointer x)
|
||||
{
|
||||
x->next()=x->next()->next();
|
||||
}
|
||||
|
||||
private:
|
||||
hashed_index_node_impl();
|
||||
|
||||
hashed_index_node_impl* next_;
|
||||
pointer next_;
|
||||
};
|
||||
|
||||
template<typename Super>
|
||||
struct hashed_index_node_trampoline:hashed_index_node_impl{};
|
||||
struct hashed_index_node_trampoline:
|
||||
prevent_eti<
|
||||
Super,
|
||||
hashed_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
typename Super::allocator_type,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type
|
||||
{
|
||||
typedef typename prevent_eti<
|
||||
Super,
|
||||
hashed_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
typename Super::allocator_type,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type impl_type;
|
||||
};
|
||||
|
||||
template<typename Super>
|
||||
struct hashed_index_node:Super,hashed_index_node_trampoline<Super>
|
||||
{
|
||||
hashed_index_node_impl* impl()
|
||||
{return static_cast<impl_type*>(this);}
|
||||
const hashed_index_node_impl* impl()const
|
||||
{return static_cast<const impl_type*>(this);}
|
||||
private:
|
||||
typedef hashed_index_node_trampoline<Super> trampoline;
|
||||
|
||||
static hashed_index_node* from_impl(hashed_index_node_impl *x)
|
||||
{return static_cast<hashed_index_node*>(static_cast<impl_type*>(x));}
|
||||
static const hashed_index_node* from_impl(
|
||||
const hashed_index_node_impl* x)
|
||||
public:
|
||||
typedef typename trampoline::impl_type impl_type;
|
||||
typedef typename trampoline::pointer impl_pointer;
|
||||
typedef typename trampoline::const_pointer const_impl_pointer;
|
||||
|
||||
impl_pointer impl()
|
||||
{
|
||||
return static_cast<impl_pointer>(
|
||||
static_cast<impl_type*>(static_cast<trampoline*>(this)));
|
||||
}
|
||||
|
||||
const_impl_pointer impl()const
|
||||
{
|
||||
return static_cast<const_impl_pointer>(
|
||||
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
|
||||
}
|
||||
|
||||
static hashed_index_node* from_impl(impl_pointer x)
|
||||
{
|
||||
return static_cast<hashed_index_node*>(
|
||||
static_cast<trampoline*>(&*x));
|
||||
}
|
||||
|
||||
static const hashed_index_node* from_impl(const_impl_pointer x)
|
||||
{
|
||||
return static_cast<const hashed_index_node*>(
|
||||
static_cast<const impl_type*>(x));
|
||||
static_cast<const trampoline*>(&*x));
|
||||
}
|
||||
|
||||
static void increment(
|
||||
hashed_index_node*& x,
|
||||
hashed_index_node_impl* bbegin,hashed_index_node_impl* bend)
|
||||
hashed_index_node*& x,impl_pointer bbegin,impl_pointer bend)
|
||||
{
|
||||
hashed_index_node_impl* xi=x->impl();
|
||||
impl_type::increment(xi,bbegin,bend);
|
||||
impl_pointer xi=x->impl();
|
||||
trampoline::increment(xi,bbegin,bend);
|
||||
x=from_impl(xi);
|
||||
}
|
||||
|
||||
/* interoperability with hashed_index_proxy */
|
||||
|
||||
static hashed_index_node* end(hashed_index_node* header)
|
||||
{
|
||||
return from_impl(impl_type::end(header->impl()));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef hashed_index_node_trampoline<Super> impl_type;
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/* Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_HASH_hashed_index_proxy_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_HASH_hashed_index_proxy_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
#include <algorithm>
|
||||
#include <boost/multi_index/detail/hash_index_iterator_fwd.hpp>
|
||||
#include <boost/multi_index/detail/safe_mode.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* Analogous of index_proxy for interoperability with
|
||||
* hashed_index_iterator.
|
||||
*/
|
||||
|
||||
template<typename Node,typename BucketArray>
|
||||
class hashed_index_proxy:
|
||||
public safe_container<hashed_index_proxy<Node,BucketArray> >
|
||||
{
|
||||
protected:
|
||||
hashed_index_proxy(Node* header_,BucketArray& buckets_):
|
||||
header(header_),buckets(&buckets_){}
|
||||
|
||||
void swap(hashed_index_proxy<Node,BucketArray>& x)
|
||||
{
|
||||
std::swap(header,x.header);
|
||||
std::swap(buckets,x.buckets);
|
||||
safe_container<hashed_index_proxy<Node,BucketArray> >::swap(x);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef hashed_index_iterator<Node,BucketArray> iterator;
|
||||
typedef hashed_index_iterator<Node,BucketArray> const_iterator;
|
||||
|
||||
hashed_index_iterator<Node,BucketArray> end()const
|
||||
{
|
||||
return hashed_index_iterator<Node,BucketArray>(
|
||||
Node::end(header),*buckets,const_cast<hashed_index_proxy*>(this));
|
||||
}
|
||||
|
||||
private:
|
||||
Node* header;
|
||||
BucketArray* buckets;
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* workaround */
|
||||
|
||||
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,7 +14,6 @@
|
||||
#endif
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
@@ -22,23 +21,23 @@ namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* An utility class derived from base_from_member used to hold
|
||||
* a pointer to the header node. The base from member idiom is used
|
||||
* because index classes, which are superclasses of multi_index_container,
|
||||
* need this header in construction time.
|
||||
* The allocation is made by the allocator of the multi_index_container
|
||||
/* A utility class used to hold a pointer to the header node.
|
||||
* The base from member idiom is used because index classes, which are
|
||||
* superclasses of multi_index_container, need this header in construction
|
||||
* time. The allocation is made by the allocator of the multi_index_container
|
||||
* class --hence, this allocator needs also be stored resorting
|
||||
* to the base from member trick.
|
||||
*/
|
||||
|
||||
template<typename NodeType,typename Final>
|
||||
struct header_holder:base_from_member<NodeType*>,private noncopyable
|
||||
template<typename NodeTypePtr,typename Final>
|
||||
struct header_holder:private noncopyable
|
||||
{
|
||||
header_holder():super(final().allocate_node()){}
|
||||
~header_holder(){final().deallocate_node(super::member);}
|
||||
header_holder():member(final().allocate_node()){}
|
||||
~header_holder(){final().deallocate_node(&*member);}
|
||||
|
||||
NodeTypePtr member;
|
||||
|
||||
private:
|
||||
typedef base_from_member<NodeType*> super;
|
||||
Final& final(){return *static_cast<Final*>(this);}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -46,7 +46,7 @@ template<typename Value,typename IndexSpecifierList,typename Allocator>
|
||||
class index_base
|
||||
{
|
||||
protected:
|
||||
typedef index_node_base<Value> node_type;
|
||||
typedef index_node_base<Value,Allocator> node_type;
|
||||
typedef typename multi_index_node_type<
|
||||
Value,IndexSpecifierList,Allocator>::type final_node_type;
|
||||
typedef multi_index_container<
|
||||
@@ -85,24 +85,24 @@ protected:
|
||||
|
||||
node_type* insert_(value_param_type v,node_type* x)
|
||||
{
|
||||
boost::detail::allocator::construct(&x->value,v);
|
||||
boost::detail::allocator::construct(&x->value(),v);
|
||||
return x;
|
||||
}
|
||||
|
||||
node_type* insert_(value_param_type v,node_type*,node_type* x)
|
||||
{
|
||||
boost::detail::allocator::construct(&x->value,v);
|
||||
boost::detail::allocator::construct(&x->value(),v);
|
||||
return x;
|
||||
}
|
||||
|
||||
void erase_(node_type* x)
|
||||
{
|
||||
boost::detail::allocator::destroy(&x->value);
|
||||
boost::detail::allocator::destroy(&x->value());
|
||||
}
|
||||
|
||||
void delete_node_(node_type* x)
|
||||
{
|
||||
boost::detail::allocator::destroy(&x->value);
|
||||
boost::detail::allocator::destroy(&x->value());
|
||||
}
|
||||
|
||||
void clear_(){}
|
||||
@@ -111,12 +111,14 @@ protected:
|
||||
|
||||
bool replace_(value_param_type v,node_type* x)
|
||||
{
|
||||
x->value=v;
|
||||
x->value()=v;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool modify_(node_type*){return true;}
|
||||
|
||||
bool modify_rollback_(node_type*){return true;}
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
/* serialization */
|
||||
|
||||
@@ -162,9 +164,13 @@ protected:
|
||||
{return final().replace_(k,x);}
|
||||
|
||||
template<typename Modifier>
|
||||
bool final_modify_(Modifier mod,final_node_type* x)
|
||||
bool final_modify_(Modifier& mod,final_node_type* x)
|
||||
{return final().modify_(mod,x);}
|
||||
|
||||
template<typename Modifier,typename Rollback>
|
||||
bool final_modify_(Modifier& mod,Rollback& back,final_node_type* x)
|
||||
{return final().modify_(mod,back,x);}
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
|
||||
void final_check_invariant_()const{final().check_invariant_();}
|
||||
#endif
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/multi_index/detail/index_iterator_fwd.hpp>
|
||||
#include <boost/multi_index/detail/index_proxy.hpp>
|
||||
#include <boost/multi_index/detail/safe_mode.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* An iterator template for nodes of multi_index::detail::index.
|
||||
* Built with the aid boost::bidirectional_iterator_helper from
|
||||
* boost/operators.hpp.
|
||||
*/
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
template<typename Node>
|
||||
class index_iterator:
|
||||
public boost::bidirectional_iterator_helper<
|
||||
index_iterator<Node>,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
const typename Node::value_type*,
|
||||
const typename Node::value_type&>,
|
||||
public safe_iterator<index_proxy<Node> >
|
||||
#else
|
||||
template<typename Node,typename Container>
|
||||
class index_iterator:
|
||||
public boost::bidirectional_iterator_helper<
|
||||
index_iterator<Node,Container>,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
const typename Node::value_type*,
|
||||
const typename Node::value_type&>,
|
||||
public safe_iterator<Container>
|
||||
#endif
|
||||
#else
|
||||
template<typename Node>
|
||||
class index_iterator:
|
||||
public boost::bidirectional_iterator_helper<
|
||||
index_iterator<Node>,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
const typename Node::value_type*,
|
||||
const typename Node::value_type&>
|
||||
#endif
|
||||
|
||||
{
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
public:
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
typedef index_proxy<Node> container_type;
|
||||
#else
|
||||
typedef Container container_type;
|
||||
#endif
|
||||
|
||||
private:
|
||||
typedef safe_iterator<container_type> safe_super;
|
||||
|
||||
public:
|
||||
index_iterator():node(0){}
|
||||
index_iterator(Node* node_,container_type* cont_):
|
||||
safe_super(cont_),node(node_){}
|
||||
|
||||
index_iterator& operator=(const index_iterator& x)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
|
||||
safe_super::operator=(x);
|
||||
node=x.node;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#else
|
||||
public:
|
||||
index_iterator(){}
|
||||
index_iterator(Node* node_):node(node_){}
|
||||
#endif
|
||||
|
||||
const typename Node::value_type& operator*()const
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);
|
||||
return node->value;
|
||||
}
|
||||
|
||||
index_iterator& operator++()
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);
|
||||
Node::increment(node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
index_iterator& operator--()
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(*this);
|
||||
Node::decrement(node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const index_iterator& x,const index_iterator& y)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(y);
|
||||
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(x,y);
|
||||
return x.node==y.node;
|
||||
}
|
||||
|
||||
/* get_node is not to be used by the user */
|
||||
|
||||
Node* get_node()const{return node;}
|
||||
|
||||
private:
|
||||
Node* node;
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
/* serialization */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
typedef typename Node::base_type node_base_type;
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive& ar,const unsigned int version)const
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
node_base_type* bnode=node;
|
||||
ar<<serialization::make_nvp("pointer",bnode);
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive& ar,const unsigned int version)
|
||||
{
|
||||
node_base_type* bnode;
|
||||
ar>>serialization::make_nvp("pointer",bnode);
|
||||
node=static_cast<Node*>(bnode);
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
safe_super::uncheck();
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,44 +0,0 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_FWD_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_FWD_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
template<typename Node>
|
||||
class index_iterator;
|
||||
#else
|
||||
template<typename Node,typename Container>
|
||||
class index_iterator;
|
||||
#endif
|
||||
#else
|
||||
template<typename Node>
|
||||
class index_iterator;
|
||||
#endif
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Node** entries()const{return spc.data();}
|
||||
Node** entries()const{return &*spc.data();}
|
||||
|
||||
/* We try to delay sorting as much as possible just in case it
|
||||
* is not necessary, hence this version of load_node.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -179,7 +179,7 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
entry* entries()const{return spc.data();}
|
||||
entry* entries()const{return &*spc.data();}
|
||||
|
||||
auto_space<entry,Allocator> spc;
|
||||
std::size_t size_;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -13,8 +13,11 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
@@ -31,16 +34,41 @@ namespace detail{
|
||||
*/
|
||||
|
||||
template<typename Value>
|
||||
struct index_node_base
|
||||
struct pod_value_holder
|
||||
{
|
||||
typename aligned_storage<
|
||||
sizeof(Value),
|
||||
alignment_of<Value>::value
|
||||
>::type space;
|
||||
};
|
||||
|
||||
template<typename Value,typename Allocator>
|
||||
struct index_node_base:private pod_value_holder<Value>
|
||||
{
|
||||
typedef index_node_base base_type; /* used for serialization purposes */
|
||||
typedef Value value_type;
|
||||
value_type value;
|
||||
typedef Allocator allocator_type;
|
||||
|
||||
value_type& value()
|
||||
{
|
||||
return *static_cast<value_type*>(
|
||||
static_cast<void*>(&this->space));
|
||||
}
|
||||
|
||||
const value_type& value()const
|
||||
{
|
||||
return *static_cast<const value_type*>(
|
||||
static_cast<const void*>(&this->space));
|
||||
}
|
||||
|
||||
static index_node_base* from_value(const value_type* p)
|
||||
{
|
||||
return static_cast<index_node_base *>(
|
||||
reinterpret_cast<pod_value_holder<Value>*>( /* std 9.2.17 */
|
||||
const_cast<value_type*>(p)));
|
||||
}
|
||||
|
||||
private:
|
||||
index_node_base();
|
||||
/* this class is not intended to be cted, merely allocated */
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
friend class boost::serialization::access;
|
||||
|
||||
@@ -54,9 +82,18 @@ private:
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
template<typename Node,typename Value>
|
||||
Node* node_from_value(
|
||||
const Value* p
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
|
||||
{
|
||||
typedef typename Node::allocator_type allocator_type;
|
||||
return static_cast<Node*>(
|
||||
index_node_base<Value,allocator_type>::from_value(p));
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
@@ -75,9 +112,9 @@ namespace multi_index{
|
||||
namespace detail{
|
||||
#endif
|
||||
|
||||
template<class Archive,typename Value>
|
||||
template<class Archive,typename Value,typename Allocator>
|
||||
inline void load_construct_data(
|
||||
Archive&,boost::multi_index::detail::index_node_base<Value>*,
|
||||
Archive&,boost::multi_index::detail::index_node_base<Value,Allocator>*,
|
||||
const unsigned int)
|
||||
{
|
||||
throw_exception(
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_PROXY_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_INDEX_PROXY_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
#include <algorithm>
|
||||
#include <boost/multi_index/detail/index_iterator_fwd.hpp>
|
||||
#include <boost/multi_index/detail/safe_mode.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* In safe mode, index iterators are derived from safe_iterator<Index>,
|
||||
* where Index is the type of the index where the iterator belongs. Due
|
||||
* to the long symbol names of indices, MSVC++ 6.0 often issues a
|
||||
* LNK1179 (duplicate comdat) error. To workaround this problem,
|
||||
* index_proxy is used instead. index_proxy<Node> acts as an index
|
||||
* over nodes of type Node in all aspects relevant to safe_iterator, and
|
||||
* its shorter symbol name makes life easier for MSVC++ 6.0.
|
||||
*/
|
||||
|
||||
template<typename Node>
|
||||
class index_proxy:public safe_container<index_proxy<Node> >
|
||||
{
|
||||
protected:
|
||||
index_proxy(Node* header_):header(header_){}
|
||||
|
||||
void swap(index_proxy<Node>& x)
|
||||
{
|
||||
std::swap(header,x.header);
|
||||
safe_container<index_proxy<Node> >::swap(x);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef index_iterator<Node> iterator;
|
||||
typedef index_iterator<Node> const_iterator;
|
||||
|
||||
index_iterator<Node> begin()const
|
||||
{
|
||||
return index_iterator<Node>(
|
||||
Node::begin(header),const_cast<index_proxy*>(this));
|
||||
}
|
||||
|
||||
index_iterator<Node> end()const
|
||||
{
|
||||
return index_iterator<Node>(
|
||||
Node::end(header),const_cast<index_proxy*>(this));
|
||||
}
|
||||
|
||||
private:
|
||||
Node* header;
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* workaround */
|
||||
|
||||
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* Poor man's version of boost::iterator_adaptor. Used instead of the
|
||||
* original as compile times for the latter are significantly higher.
|
||||
* The interface is not replicated exactly, only to the extent necessary
|
||||
* for internal consumption.
|
||||
*/
|
||||
|
||||
/* NB. The purpose of the (non-inclass) global operators ==, < and - defined
|
||||
* above is to partially alleviate a problem of MSVC++ 6.0 by * which
|
||||
* friend-injected operators on T are not visible if T is instantiated only
|
||||
* in template code where T is a dependent type.
|
||||
*/
|
||||
|
||||
class iter_adaptor_access
|
||||
{
|
||||
public:
|
||||
template<class Class>
|
||||
static typename Class::reference dereference(const Class& x)
|
||||
{
|
||||
return x.dereference();
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
static bool equal(const Class& x,const Class& y)
|
||||
{
|
||||
return x.equal(y);
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
static void increment(Class& x)
|
||||
{
|
||||
x.increment();
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
static void decrement(Class& x)
|
||||
{
|
||||
x.decrement();
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
static void advance(Class& x,typename Class::difference_type n)
|
||||
{
|
||||
x.advance(n);
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
static typename Class::difference_type distance_to(
|
||||
const Class& x,const Class& y)
|
||||
{
|
||||
return x.distance_to(y);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Category>
|
||||
struct iter_adaptor_selector;
|
||||
|
||||
template<class Derived,class Base>
|
||||
class forward_iter_adaptor_base:
|
||||
public forward_iterator_helper<
|
||||
Derived,
|
||||
typename Base::value_type,
|
||||
typename Base::difference_type,
|
||||
typename Base::pointer,
|
||||
typename Base::reference>
|
||||
{
|
||||
public:
|
||||
typedef typename Base::reference reference;
|
||||
|
||||
reference operator*()const
|
||||
{
|
||||
return iter_adaptor_access::dereference(final());
|
||||
}
|
||||
|
||||
friend bool operator==(const Derived& x,const Derived& y)
|
||||
{
|
||||
return iter_adaptor_access::equal(x,y);
|
||||
}
|
||||
|
||||
Derived& operator++()
|
||||
{
|
||||
iter_adaptor_access::increment(final());
|
||||
return final();
|
||||
}
|
||||
|
||||
private:
|
||||
Derived& final(){return *static_cast<Derived*>(this);}
|
||||
const Derived& final()const{return *static_cast<const Derived*>(this);}
|
||||
};
|
||||
|
||||
template<class Derived,class Base>
|
||||
bool operator==(
|
||||
const forward_iter_adaptor_base<Derived,Base>& x,
|
||||
const forward_iter_adaptor_base<Derived,Base>& y)
|
||||
{
|
||||
return iter_adaptor_access::equal(
|
||||
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
|
||||
}
|
||||
|
||||
template<>
|
||||
struct iter_adaptor_selector<std::forward_iterator_tag>
|
||||
{
|
||||
template<class Derived,class Base>
|
||||
struct apply
|
||||
{
|
||||
typedef forward_iter_adaptor_base<Derived,Base> type;
|
||||
};
|
||||
};
|
||||
|
||||
template<class Derived,class Base>
|
||||
class bidirectional_iter_adaptor_base:
|
||||
public bidirectional_iterator_helper<
|
||||
Derived,
|
||||
typename Base::value_type,
|
||||
typename Base::difference_type,
|
||||
typename Base::pointer,
|
||||
typename Base::reference>
|
||||
{
|
||||
public:
|
||||
typedef typename Base::reference reference;
|
||||
|
||||
reference operator*()const
|
||||
{
|
||||
return iter_adaptor_access::dereference(final());
|
||||
}
|
||||
|
||||
friend bool operator==(const Derived& x,const Derived& y)
|
||||
{
|
||||
return iter_adaptor_access::equal(x,y);
|
||||
}
|
||||
|
||||
Derived& operator++()
|
||||
{
|
||||
iter_adaptor_access::increment(final());
|
||||
return final();
|
||||
}
|
||||
|
||||
Derived& operator--()
|
||||
{
|
||||
iter_adaptor_access::decrement(final());
|
||||
return final();
|
||||
}
|
||||
|
||||
private:
|
||||
Derived& final(){return *static_cast<Derived*>(this);}
|
||||
const Derived& final()const{return *static_cast<const Derived*>(this);}
|
||||
};
|
||||
|
||||
template<class Derived,class Base>
|
||||
bool operator==(
|
||||
const bidirectional_iter_adaptor_base<Derived,Base>& x,
|
||||
const bidirectional_iter_adaptor_base<Derived,Base>& y)
|
||||
{
|
||||
return iter_adaptor_access::equal(
|
||||
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
|
||||
}
|
||||
|
||||
template<>
|
||||
struct iter_adaptor_selector<std::bidirectional_iterator_tag>
|
||||
{
|
||||
template<class Derived,class Base>
|
||||
struct apply
|
||||
{
|
||||
typedef bidirectional_iter_adaptor_base<Derived,Base> type;
|
||||
};
|
||||
};
|
||||
|
||||
template<class Derived,class Base>
|
||||
class random_access_iter_adaptor_base:
|
||||
public random_access_iterator_helper<
|
||||
Derived,
|
||||
typename Base::value_type,
|
||||
typename Base::difference_type,
|
||||
typename Base::pointer,
|
||||
typename Base::reference>
|
||||
{
|
||||
public:
|
||||
typedef typename Base::reference reference;
|
||||
typedef typename Base::difference_type difference_type;
|
||||
|
||||
reference operator*()const
|
||||
{
|
||||
return iter_adaptor_access::dereference(final());
|
||||
}
|
||||
|
||||
friend bool operator==(const Derived& x,const Derived& y)
|
||||
{
|
||||
return iter_adaptor_access::equal(x,y);
|
||||
}
|
||||
|
||||
friend bool operator<(const Derived& x,const Derived& y)
|
||||
{
|
||||
return iter_adaptor_access::distance_to(x,y)>0;
|
||||
}
|
||||
|
||||
Derived& operator++()
|
||||
{
|
||||
iter_adaptor_access::increment(final());
|
||||
return final();
|
||||
}
|
||||
|
||||
Derived& operator--()
|
||||
{
|
||||
iter_adaptor_access::decrement(final());
|
||||
return final();
|
||||
}
|
||||
|
||||
Derived& operator+=(difference_type n)
|
||||
{
|
||||
iter_adaptor_access::advance(final(),n);
|
||||
return final();
|
||||
}
|
||||
|
||||
Derived& operator-=(difference_type n)
|
||||
{
|
||||
iter_adaptor_access::advance(final(),-n);
|
||||
return final();
|
||||
}
|
||||
|
||||
friend difference_type operator-(const Derived& x,const Derived& y)
|
||||
{
|
||||
return iter_adaptor_access::distance_to(y,x);
|
||||
}
|
||||
|
||||
private:
|
||||
Derived& final(){return *static_cast<Derived*>(this);}
|
||||
const Derived& final()const{return *static_cast<const Derived*>(this);}
|
||||
};
|
||||
|
||||
template<class Derived,class Base>
|
||||
bool operator==(
|
||||
const random_access_iter_adaptor_base<Derived,Base>& x,
|
||||
const random_access_iter_adaptor_base<Derived,Base>& y)
|
||||
{
|
||||
return iter_adaptor_access::equal(
|
||||
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
|
||||
}
|
||||
|
||||
template<class Derived,class Base>
|
||||
bool operator<(
|
||||
const random_access_iter_adaptor_base<Derived,Base>& x,
|
||||
const random_access_iter_adaptor_base<Derived,Base>& y)
|
||||
{
|
||||
return iter_adaptor_access::distance_to(
|
||||
static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0;
|
||||
}
|
||||
|
||||
template<class Derived,class Base>
|
||||
typename random_access_iter_adaptor_base<Derived,Base>::difference_type
|
||||
operator-(
|
||||
const random_access_iter_adaptor_base<Derived,Base>& x,
|
||||
const random_access_iter_adaptor_base<Derived,Base>& y)
|
||||
{
|
||||
return iter_adaptor_access::distance_to(
|
||||
static_cast<const Derived&>(y),static_cast<const Derived&>(x));
|
||||
}
|
||||
|
||||
template<>
|
||||
struct iter_adaptor_selector<std::random_access_iterator_tag>
|
||||
{
|
||||
template<class Derived,class Base>
|
||||
struct apply
|
||||
{
|
||||
typedef random_access_iter_adaptor_base<Derived,Base> type;
|
||||
};
|
||||
};
|
||||
|
||||
template<class Derived,class Base>
|
||||
struct iter_adaptor_base
|
||||
{
|
||||
typedef iter_adaptor_selector<
|
||||
typename Base::iterator_category> selector;
|
||||
typedef typename prevent_eti<
|
||||
selector,
|
||||
typename mpl::apply2<
|
||||
selector,Derived,Base>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<class Derived,class Base>
|
||||
class iter_adaptor:public iter_adaptor_base<Derived,Base>::type
|
||||
{
|
||||
protected:
|
||||
iter_adaptor(){}
|
||||
explicit iter_adaptor(const Base& b_):b(b_){}
|
||||
|
||||
const Base& base_reference()const{return b;}
|
||||
Base& base_reference(){return b;}
|
||||
|
||||
private:
|
||||
Base b;
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -24,19 +24,19 @@ namespace detail{
|
||||
* with references to references, dealing with function pointers, etc.
|
||||
*/
|
||||
|
||||
template<typename Modifier,typename Value,typename KeyFromValue>
|
||||
template<typename Fun,typename Value,typename KeyFromValue>
|
||||
struct modify_key_adaptor
|
||||
{
|
||||
|
||||
modify_key_adaptor(Modifier mod_,KeyFromValue kfv_):mod(mod_),kfv(kfv_){}
|
||||
modify_key_adaptor(Fun f_,KeyFromValue kfv_):f(f_),kfv(kfv_){}
|
||||
|
||||
void operator()(Value& x)
|
||||
{
|
||||
mod(kfv(x));
|
||||
f(kfv(x));
|
||||
}
|
||||
|
||||
private:
|
||||
Modifier mod;
|
||||
Fun f;
|
||||
KeyFromValue kfv;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -65,7 +65,7 @@ struct multi_index_node_type
|
||||
|
||||
typedef typename mpl::reverse_iter_fold<
|
||||
IndexSpecifierList,
|
||||
index_node_base<Value>,
|
||||
index_node_base<Value,Allocator>,
|
||||
mpl::bind2<index_node_applier,mpl::_2,mpl::_1>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -40,8 +40,18 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <cstddef>
|
||||
#include <boost/detail/allocator_utilities.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/multi_index/detail/uintptr_type.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
@@ -52,28 +62,199 @@ namespace detail{
|
||||
/* definition of red-black nodes for ordered_index */
|
||||
|
||||
enum ordered_index_color{red=false,black=true};
|
||||
enum ordered_index_side{to_left=false,to_right=true};
|
||||
|
||||
struct ordered_index_node_impl
|
||||
template<typename Allocator>
|
||||
struct ordered_index_node_impl; /* fwd decl. */
|
||||
|
||||
template<typename Allocator>
|
||||
struct ordered_index_node_std_base
|
||||
{
|
||||
ordered_index_color& color(){return color_;}
|
||||
const ordered_index_color& color()const{return color_;}
|
||||
ordered_index_node_impl*& parent(){return parent_;}
|
||||
ordered_index_node_impl*const & parent()const{return parent_;}
|
||||
ordered_index_node_impl*& left(){return left_;}
|
||||
ordered_index_node_impl*const & left()const{return left_;}
|
||||
ordered_index_node_impl*& right(){return right_;}
|
||||
ordered_index_node_impl*const & right()const{return right_;}
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,
|
||||
ordered_index_node_impl<Allocator>
|
||||
>::type
|
||||
>::type::pointer pointer;
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,
|
||||
ordered_index_node_impl<Allocator>
|
||||
>::type
|
||||
>::type::const_pointer const_pointer;
|
||||
typedef ordered_index_color& color_ref;
|
||||
typedef pointer& parent_ref;
|
||||
|
||||
/* interoperability with index_iterator */
|
||||
ordered_index_color& color(){return color_;}
|
||||
ordered_index_color color()const{return color_;}
|
||||
pointer& parent(){return parent_;}
|
||||
pointer parent()const{return parent_;}
|
||||
pointer& left(){return left_;}
|
||||
pointer left()const{return left_;}
|
||||
pointer& right(){return right_;}
|
||||
pointer right()const{return right_;}
|
||||
|
||||
static void increment(ordered_index_node_impl*& x)
|
||||
private:
|
||||
ordered_index_color color_;
|
||||
pointer parent_;
|
||||
pointer left_;
|
||||
pointer right_;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
|
||||
/* If ordered_index_node_impl has even alignment, we can use the least
|
||||
* significant bit of one of the ordered_index_node_impl pointers to
|
||||
* store color information. This typically reduces the size of
|
||||
* ordered_index_node_impl by 25%.
|
||||
*/
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
/* This code casts pointers to an integer type that has been computed
|
||||
* to be large enough to hold the pointer, however the metaprogramming
|
||||
* logic is not always spotted by the VC++ code analyser that issues a
|
||||
* long list of warnings.
|
||||
*/
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4312 4311)
|
||||
#endif
|
||||
|
||||
template<typename Allocator>
|
||||
struct ordered_index_node_compressed_base
|
||||
{
|
||||
typedef ordered_index_node_impl<Allocator>* pointer;
|
||||
typedef const ordered_index_node_impl<Allocator>* const_pointer;
|
||||
|
||||
struct color_ref
|
||||
{
|
||||
if(x->right()){
|
||||
color_ref(uintptr_type* r_):r(r_){}
|
||||
|
||||
operator ordered_index_color()const
|
||||
{
|
||||
return ordered_index_color(*r&uintptr_type(1));
|
||||
}
|
||||
|
||||
color_ref& operator=(ordered_index_color c)
|
||||
{
|
||||
*r&=~uintptr_type(1);
|
||||
*r|=uintptr_type(c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
color_ref& operator=(const color_ref& x)
|
||||
{
|
||||
return operator=(x.operator ordered_index_color());
|
||||
}
|
||||
|
||||
private:
|
||||
uintptr_type* r;
|
||||
};
|
||||
|
||||
struct parent_ref
|
||||
{
|
||||
parent_ref(uintptr_type* r_):r(r_){}
|
||||
|
||||
operator pointer()const
|
||||
{
|
||||
return (pointer)(void*)(*r&~uintptr_type(1));
|
||||
}
|
||||
|
||||
parent_ref& operator=(pointer p)
|
||||
{
|
||||
*r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
parent_ref& operator=(const parent_ref& x)
|
||||
{
|
||||
return operator=(x.operator pointer());
|
||||
}
|
||||
|
||||
pointer operator->()const
|
||||
{
|
||||
return operator pointer();
|
||||
}
|
||||
|
||||
private:
|
||||
uintptr_type* r;
|
||||
};
|
||||
|
||||
color_ref color(){return color_ref(&parentcolor_);}
|
||||
ordered_index_color color()const
|
||||
{
|
||||
return ordered_index_color(parentcolor_&std::size_t(1ul));
|
||||
}
|
||||
|
||||
parent_ref parent(){return parent_ref(&parentcolor_);}
|
||||
pointer parent()const
|
||||
{
|
||||
return (pointer)(void*)(parentcolor_&~uintptr_type(1));
|
||||
}
|
||||
|
||||
pointer& left(){return left_;}
|
||||
pointer left()const{return left_;}
|
||||
pointer& right(){return right_;}
|
||||
pointer right()const{return right_;}
|
||||
|
||||
private:
|
||||
uintptr_type parentcolor_;
|
||||
pointer left_;
|
||||
pointer right_;
|
||||
};
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template<typename Allocator>
|
||||
struct ordered_index_node_impl_base:
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
|
||||
mpl::if_c<
|
||||
!(has_uintptr_type::value)||
|
||||
(alignment_of<ordered_index_node_compressed_base<Allocator> >::value%2)||
|
||||
!(is_same<
|
||||
typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,
|
||||
ordered_index_node_impl<Allocator>
|
||||
>::type
|
||||
>::type::pointer,
|
||||
ordered_index_node_impl<Allocator>*>::value),
|
||||
ordered_index_node_std_base<Allocator>,
|
||||
ordered_index_node_compressed_base<Allocator>
|
||||
>::type
|
||||
#else
|
||||
ordered_index_node_std_base<Allocator>
|
||||
#endif
|
||||
|
||||
{};
|
||||
|
||||
template<typename Allocator>
|
||||
struct ordered_index_node_impl:ordered_index_node_impl_base<Allocator>
|
||||
{
|
||||
private:
|
||||
typedef ordered_index_node_impl_base<Allocator> super;
|
||||
|
||||
public:
|
||||
typedef typename super::color_ref color_ref;
|
||||
typedef typename super::parent_ref parent_ref;
|
||||
typedef typename super::pointer pointer;
|
||||
typedef typename super::const_pointer const_pointer;
|
||||
|
||||
/* interoperability with bidir_node_iterator */
|
||||
|
||||
static void increment(pointer& x)
|
||||
{
|
||||
if(x->right()!=pointer(0)){
|
||||
x=x->right();
|
||||
while(x->left())x=x->left();
|
||||
while(x->left()!=pointer(0))x=x->left();
|
||||
}
|
||||
else{
|
||||
ordered_index_node_impl* y=x->parent();
|
||||
pointer y=x->parent();
|
||||
while(x==y->right()){
|
||||
x=y;
|
||||
y=y->parent();
|
||||
@@ -82,17 +263,17 @@ struct ordered_index_node_impl
|
||||
}
|
||||
}
|
||||
|
||||
static void decrement(ordered_index_node_impl*& x)
|
||||
static void decrement(pointer& x)
|
||||
{
|
||||
if(x->color()==red&&x->parent()->parent()==x){
|
||||
x=x->right();
|
||||
}
|
||||
else if(x->left()){
|
||||
ordered_index_node_impl* y=x->left();
|
||||
while(y->right())y=y->right();
|
||||
else if(x->left()!=pointer(0)){
|
||||
pointer y=x->left();
|
||||
while(y->right()!=pointer(0))y=y->right();
|
||||
x=y;
|
||||
}else{
|
||||
ordered_index_node_impl* y=x->parent();
|
||||
pointer y=x->parent();
|
||||
while(x==y->left()){
|
||||
x=y;
|
||||
y=y->parent();
|
||||
@@ -101,26 +282,13 @@ struct ordered_index_node_impl
|
||||
}
|
||||
}
|
||||
|
||||
/* interoperability with index_proxy */
|
||||
|
||||
static ordered_index_node_impl* begin(ordered_index_node_impl* header)
|
||||
{
|
||||
return header->left();
|
||||
}
|
||||
|
||||
static ordered_index_node_impl* end(ordered_index_node_impl* header)
|
||||
{
|
||||
return header;
|
||||
}
|
||||
|
||||
/* algorithmic stuff */
|
||||
|
||||
static void rotate_left(
|
||||
ordered_index_node_impl* x,ordered_index_node_impl*& root)
|
||||
static void rotate_left(pointer x,parent_ref root)
|
||||
{
|
||||
ordered_index_node_impl* y=x->right();
|
||||
pointer y=x->right();
|
||||
x->right()=y->left();
|
||||
if(y->left())y->left()->parent()=x;
|
||||
if(y->left()!=pointer(0))y->left()->parent()=x;
|
||||
y->parent()=x->parent();
|
||||
|
||||
if(x==root) root=y;
|
||||
@@ -130,24 +298,23 @@ struct ordered_index_node_impl
|
||||
x->parent()=y;
|
||||
}
|
||||
|
||||
static ordered_index_node_impl* minimum(ordered_index_node_impl* x)
|
||||
static pointer minimum(pointer x)
|
||||
{
|
||||
while(x->left())x=x->left();
|
||||
while(x->left()!=pointer(0))x=x->left();
|
||||
return x;
|
||||
}
|
||||
|
||||
static ordered_index_node_impl* maximum(ordered_index_node_impl* x)
|
||||
static pointer maximum(pointer x)
|
||||
{
|
||||
while(x->right())x=x->right();
|
||||
while(x->right()!=pointer(0))x=x->right();
|
||||
return x;
|
||||
}
|
||||
|
||||
static void rotate_right(
|
||||
ordered_index_node_impl* x,ordered_index_node_impl*& root)
|
||||
static void rotate_right(pointer x,parent_ref root)
|
||||
{
|
||||
ordered_index_node_impl* y=x->left();
|
||||
pointer y=x->left();
|
||||
x->left()=y->right();
|
||||
if(y->right())y->right()->parent()=x;
|
||||
if(y->right()!=pointer(0))y->right()->parent()=x;
|
||||
y->parent()=x->parent();
|
||||
|
||||
if(x==root) root=y;
|
||||
@@ -157,14 +324,13 @@ struct ordered_index_node_impl
|
||||
x->parent()=y;
|
||||
}
|
||||
|
||||
static void rebalance(
|
||||
ordered_index_node_impl* x,ordered_index_node_impl*& root)
|
||||
static void rebalance(pointer x,parent_ref root)
|
||||
{
|
||||
x->color()=red;
|
||||
while(x!=root&&x->parent()->color()==red){
|
||||
if(x->parent()==x->parent()->parent()->left()){
|
||||
ordered_index_node_impl* y=x->parent()->parent()->right();
|
||||
if(y&&y->color()==red){
|
||||
pointer y=x->parent()->parent()->right();
|
||||
if(y!=pointer(0)&&y->color()==red){
|
||||
x->parent()->color()=black;
|
||||
y->color()=black;
|
||||
x->parent()->parent()->color()=red;
|
||||
@@ -181,8 +347,8 @@ struct ordered_index_node_impl
|
||||
}
|
||||
}
|
||||
else{
|
||||
ordered_index_node_impl* y=x->parent()->parent()->left();
|
||||
if(y&&y->color()==red){
|
||||
pointer y=x->parent()->parent()->left();
|
||||
if(y!=pointer(0)&&y->color()==red){
|
||||
x->parent()->color()=black;
|
||||
y->color()=black;
|
||||
x->parent()->parent()->color()=red;
|
||||
@@ -202,23 +368,47 @@ struct ordered_index_node_impl
|
||||
root->color()=black;
|
||||
}
|
||||
|
||||
static ordered_index_node_impl* rebalance_for_erase(
|
||||
ordered_index_node_impl* z,ordered_index_node_impl*& root,
|
||||
ordered_index_node_impl*& leftmost,ordered_index_node_impl*& rightmost)
|
||||
static void link(
|
||||
pointer x,ordered_index_side side,pointer position,pointer header)
|
||||
{
|
||||
ordered_index_node_impl* y=z;
|
||||
ordered_index_node_impl* x=0;
|
||||
ordered_index_node_impl* x_parent=0;
|
||||
if(y->left()==0){ /* z has at most one non-null child. y==z. */
|
||||
x=y->right(); /* x might be null */
|
||||
if(side==to_left){
|
||||
position->left()=x; /* also makes leftmost=x when parent==header */
|
||||
if(position==header){
|
||||
header->parent()=x;
|
||||
header->right()=x;
|
||||
}
|
||||
else if(position==header->left()){
|
||||
header->left()=x; /* maintain leftmost pointing to min node */
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(y->right()==0) { /* z has exactly one non-null child. y==z. */
|
||||
x=y->left(); /* x is not null */
|
||||
position->right()=x;
|
||||
if(position==header->right()){
|
||||
header->right()=x; /* maintain rightmost pointing to max node */
|
||||
}
|
||||
else{ /* z has two non-null children. Set y to */
|
||||
y=y->right(); /* z's successor. x might be null. */
|
||||
while(y->left())y=y->left();
|
||||
}
|
||||
x->parent()=position;
|
||||
x->left()=pointer(0);
|
||||
x->right()=pointer(0);
|
||||
ordered_index_node_impl::rebalance(x,header->parent());
|
||||
}
|
||||
|
||||
static pointer rebalance_for_erase(
|
||||
pointer z,parent_ref root,pointer& leftmost,pointer& rightmost)
|
||||
{
|
||||
pointer y=z;
|
||||
pointer x=pointer(0);
|
||||
pointer x_parent=pointer(0);
|
||||
if(y->left()==pointer(0)){ /* z has at most one non-null child. y==z. */
|
||||
x=y->right(); /* x might be null */
|
||||
}
|
||||
else{
|
||||
if(y->right()==pointer(0)){ /* z has exactly one non-null child. y==z. */
|
||||
x=y->left(); /* x is not null */
|
||||
}
|
||||
else{ /* z has two non-null children. Set y to */
|
||||
y=y->right(); /* z's successor. x might be null. */
|
||||
while(y->left()!=pointer(0))y=y->left();
|
||||
x=y->right();
|
||||
}
|
||||
}
|
||||
@@ -227,7 +417,7 @@ struct ordered_index_node_impl
|
||||
y->left()=z->left();
|
||||
if(y!=z->right()){
|
||||
x_parent=y->parent();
|
||||
if(x) x->parent()=y->parent();
|
||||
if(x!=pointer(0))x->parent()=y->parent();
|
||||
y->parent()->left()=x; /* y must be a child of left */
|
||||
y->right()=z->right();
|
||||
z->right()->parent()=y;
|
||||
@@ -240,12 +430,14 @@ struct ordered_index_node_impl
|
||||
else if(z->parent()->left()==z)z->parent()->left()=y;
|
||||
else z->parent()->right()=y;
|
||||
y->parent()=z->parent();
|
||||
std::swap(y->color(),z->color());
|
||||
ordered_index_color c=y->color();
|
||||
y->color()=z->color();
|
||||
z->color()=c;
|
||||
y=z; /* y now points to node to be actually deleted */
|
||||
}
|
||||
else{ /* y==z */
|
||||
x_parent=y->parent();
|
||||
if(x)x->parent()=y->parent();
|
||||
if(x!=pointer(0))x->parent()=y->parent();
|
||||
if(root==z){
|
||||
root=x;
|
||||
}
|
||||
@@ -254,15 +446,15 @@ struct ordered_index_node_impl
|
||||
else z->parent()->right()=x;
|
||||
}
|
||||
if(leftmost==z){
|
||||
if(z->right()==0){ /* z->left() must be null also */
|
||||
if(z->right()==pointer(0)){ /* z->left() must be null also */
|
||||
leftmost=z->parent();
|
||||
}
|
||||
else{
|
||||
leftmost=minimum(x); /* makes leftmost==header if z==root */
|
||||
leftmost=minimum(x); /* makes leftmost==header if z==root */
|
||||
}
|
||||
}
|
||||
if(rightmost==z){
|
||||
if(z->left()==0){ /* z->right() must be null also */
|
||||
if(z->left()==pointer(0)){ /* z->right() must be null also */
|
||||
rightmost=z->parent();
|
||||
}
|
||||
else{ /* x==z->left() */
|
||||
@@ -271,106 +463,87 @@ struct ordered_index_node_impl
|
||||
}
|
||||
}
|
||||
if(y->color()!=red){
|
||||
while(x!=root&&(x==0 || x->color()==black)){
|
||||
while(x!=root&&(x==pointer(0)|| x->color()==black)){
|
||||
if(x==x_parent->left()){
|
||||
ordered_index_node_impl* w=x_parent->right();
|
||||
pointer w=x_parent->right();
|
||||
if(w->color()==red){
|
||||
w->color()=black;
|
||||
x_parent->color()=red;
|
||||
rotate_left(x_parent,root);
|
||||
w=x_parent->right();
|
||||
}
|
||||
if((w->left()==0||w->left()->color()==black) &&
|
||||
(w->right()==0||w->right()->color()==black)){
|
||||
if((w->left()==pointer(0)||w->left()->color()==black) &&
|
||||
(w->right()==pointer(0)||w->right()->color()==black)){
|
||||
w->color()=red;
|
||||
x=x_parent;
|
||||
x_parent=x_parent->parent();
|
||||
}
|
||||
else{
|
||||
if(w->right()==0
|
||||
if(w->right()==pointer(0 )
|
||||
|| w->right()->color()==black){
|
||||
if(w->left()) w->left()->color()=black;
|
||||
if(w->left()!=pointer(0)) w->left()->color()=black;
|
||||
w->color()=red;
|
||||
rotate_right(w,root);
|
||||
w=x_parent->right();
|
||||
}
|
||||
w->color()=x_parent->color();
|
||||
x_parent->color()=black;
|
||||
if(w->right())w->right()->color()=black;
|
||||
if(w->right()!=pointer(0))w->right()->color()=black;
|
||||
rotate_left(x_parent,root);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{ /* same as above,with right <-> left */
|
||||
ordered_index_node_impl* w=x_parent->left();
|
||||
pointer w=x_parent->left();
|
||||
if(w->color()==red){
|
||||
w->color()=black;
|
||||
x_parent->color()=red;
|
||||
rotate_right(x_parent,root);
|
||||
w=x_parent->left();
|
||||
}
|
||||
if((w->right()==0||w->right()->color()==black) &&
|
||||
(w->left()==0||w->left()->color()==black)){
|
||||
if((w->right()==pointer(0)||w->right()->color()==black) &&
|
||||
(w->left()==pointer(0)||w->left()->color()==black)){
|
||||
w->color()=red;
|
||||
x=x_parent;
|
||||
x_parent=x_parent->parent();
|
||||
}
|
||||
else{
|
||||
if(w->left()==0||w->left()->color()==black){
|
||||
if(w->right())w->right()->color()=black;
|
||||
if(w->left()==pointer(0)||w->left()->color()==black){
|
||||
if(w->right()!=pointer(0))w->right()->color()=black;
|
||||
w->color()=red;
|
||||
rotate_left(w,root);
|
||||
w=x_parent->left();
|
||||
}
|
||||
w->color()=x_parent->color();
|
||||
x_parent->color()=black;
|
||||
if(w->left())w->left()->color()=black;
|
||||
if(w->left()!=pointer(0))w->left()->color()=black;
|
||||
rotate_right(x_parent,root);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(x)x->color()=black;
|
||||
if(x!=pointer(0))x->color()=black;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
static void restore(
|
||||
ordered_index_node_impl* x,ordered_index_node_impl* prior,
|
||||
ordered_index_node_impl* next,ordered_index_node_impl* header)
|
||||
static void restore(pointer x,pointer position,pointer header)
|
||||
{
|
||||
if(next->left()==0){
|
||||
next->left()=x;
|
||||
x->parent()=next;
|
||||
if(next==header->left()){
|
||||
header->left()=x; /* maintain leftmost pointing to min node */
|
||||
}
|
||||
}
|
||||
else if(x!=prior){ /* prior->right() must be null */
|
||||
prior->right()=x;
|
||||
x->parent()=prior;
|
||||
if(prior==header->right()){
|
||||
header->right()=x; /* maintain rightmost pointing to max node */
|
||||
}
|
||||
if(position->left()==pointer(0)||position->left()==header){
|
||||
link(x,to_left,position,header);
|
||||
}
|
||||
else{
|
||||
header->parent()=x;
|
||||
header->left()=x;
|
||||
header->right()=x;
|
||||
x->parent()=header;
|
||||
decrement(position);
|
||||
link(x,to_right,position,header);
|
||||
}
|
||||
x->left()=0;
|
||||
x->right()=0;
|
||||
rebalance(x,header->parent());
|
||||
}
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
|
||||
/* invariant stuff */
|
||||
|
||||
static std::size_t black_count(
|
||||
ordered_index_node_impl* node,ordered_index_node_impl* root)
|
||||
static std::size_t black_count(pointer node,pointer root)
|
||||
{
|
||||
if(!node)return 0;
|
||||
if(node==pointer(0))return 0;
|
||||
std::size_t sum=0;
|
||||
for(;;){
|
||||
if(node->color()==black)++sum;
|
||||
@@ -380,76 +553,92 @@ struct ordered_index_node_impl
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
ordered_index_node_impl();
|
||||
|
||||
ordered_index_color color_;
|
||||
ordered_index_node_impl* parent_;
|
||||
ordered_index_node_impl* left_;
|
||||
ordered_index_node_impl* right_;
|
||||
};
|
||||
|
||||
template<typename Super>
|
||||
struct ordered_index_node_trampoline:ordered_index_node_impl{};
|
||||
struct ordered_index_node_trampoline:
|
||||
prevent_eti<
|
||||
Super,
|
||||
ordered_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
typename Super::allocator_type,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type
|
||||
{
|
||||
typedef typename prevent_eti<
|
||||
Super,
|
||||
ordered_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
typename Super::allocator_type,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type impl_type;
|
||||
};
|
||||
|
||||
template<typename Super>
|
||||
struct ordered_index_node:Super,ordered_index_node_trampoline<Super>
|
||||
{
|
||||
ordered_index_color& color(){return impl_type::color();}
|
||||
const ordered_index_color& color()const{return impl_type::color();}
|
||||
ordered_index_node_impl*& parent(){return impl_type::parent();}
|
||||
ordered_index_node_impl*const & parent()const{return impl_type::parent();}
|
||||
ordered_index_node_impl*& left(){return impl_type::left();}
|
||||
ordered_index_node_impl*const & left()const{return impl_type::left();}
|
||||
ordered_index_node_impl*& right(){return impl_type::right();}
|
||||
ordered_index_node_impl*const & right()const{return impl_type::right();}
|
||||
private:
|
||||
typedef ordered_index_node_trampoline<Super> trampoline;
|
||||
|
||||
ordered_index_node_impl* impl(){return static_cast<impl_type*>(this);}
|
||||
const ordered_index_node_impl* impl()const
|
||||
{return static_cast<const impl_type*>(this);}
|
||||
public:
|
||||
typedef typename trampoline::impl_type impl_type;
|
||||
typedef typename trampoline::color_ref impl_color_ref;
|
||||
typedef typename trampoline::parent_ref impl_parent_ref;
|
||||
typedef typename trampoline::pointer impl_pointer;
|
||||
typedef typename trampoline::const_pointer const_impl_pointer;
|
||||
|
||||
static ordered_index_node* from_impl(ordered_index_node_impl *x)
|
||||
impl_color_ref color(){return trampoline::color();}
|
||||
ordered_index_color color()const{return trampoline::color();}
|
||||
impl_parent_ref parent(){return trampoline::parent();}
|
||||
impl_pointer parent()const{return trampoline::parent();}
|
||||
impl_pointer& left(){return trampoline::left();}
|
||||
impl_pointer left()const{return trampoline::left();}
|
||||
impl_pointer& right(){return trampoline::right();}
|
||||
impl_pointer right()const{return trampoline::right();}
|
||||
|
||||
impl_pointer impl()
|
||||
{
|
||||
return static_cast<ordered_index_node*>(static_cast<impl_type*>(x));
|
||||
return static_cast<impl_pointer>(
|
||||
static_cast<impl_type*>(static_cast<trampoline*>(this)));
|
||||
}
|
||||
|
||||
static const ordered_index_node* from_impl(const ordered_index_node_impl* x)
|
||||
|
||||
const_impl_pointer impl()const
|
||||
{
|
||||
return static_cast<const_impl_pointer>(
|
||||
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
|
||||
}
|
||||
|
||||
static ordered_index_node* from_impl(impl_pointer x)
|
||||
{
|
||||
return static_cast<ordered_index_node*>(
|
||||
static_cast<trampoline*>(&*x));
|
||||
}
|
||||
|
||||
static const ordered_index_node* from_impl(const_impl_pointer x)
|
||||
{
|
||||
return static_cast<const ordered_index_node*>(
|
||||
static_cast<const impl_type*>(x));
|
||||
static_cast<const trampoline*>(&*x));
|
||||
}
|
||||
|
||||
/* interoperability with index_iterator */
|
||||
/* interoperability with bidir_node_iterator */
|
||||
|
||||
static void increment(ordered_index_node*& x)
|
||||
{
|
||||
ordered_index_node_impl* xi=x->impl();
|
||||
impl_type::increment(xi);
|
||||
impl_pointer xi=x->impl();
|
||||
trampoline::increment(xi);
|
||||
x=from_impl(xi);
|
||||
}
|
||||
|
||||
static void decrement(ordered_index_node*& x)
|
||||
{
|
||||
ordered_index_node_impl* xi=x->impl();
|
||||
impl_type::decrement(xi);
|
||||
impl_pointer xi=x->impl();
|
||||
trampoline::decrement(xi);
|
||||
x=from_impl(xi);
|
||||
}
|
||||
|
||||
/* interoperability with index_proxy */
|
||||
|
||||
static ordered_index_node* begin(ordered_index_node* header)
|
||||
{
|
||||
return from_impl(impl_type::begin(header->impl()));
|
||||
}
|
||||
|
||||
static ordered_index_node* end(ordered_index_node* header)
|
||||
{
|
||||
return from_impl(impl_type::end(header->impl()));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef ordered_index_node_trampoline<Super> impl_type;
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -40,6 +40,9 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <utility>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
@@ -55,21 +58,20 @@ template<
|
||||
typename CompatibleKey,typename CompatibleCompare
|
||||
>
|
||||
inline Node* ordered_index_find(
|
||||
Node* header,const KeyFromValue& key,const CompatibleKey& x,
|
||||
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||
const CompatibleCompare& comp)
|
||||
{
|
||||
Node* y=header;
|
||||
Node* z=Node::from_impl(header->parent());
|
||||
|
||||
while (z){
|
||||
if(!comp(key(z->value),x)){
|
||||
y=z;
|
||||
z=Node::from_impl(z->left());
|
||||
Node* y0=y;
|
||||
|
||||
while (top){
|
||||
if(!comp(key(top->value()),x)){
|
||||
y=top;
|
||||
top=Node::from_impl(top->left());
|
||||
}
|
||||
else z=Node::from_impl(z->right());
|
||||
else top=Node::from_impl(top->right());
|
||||
}
|
||||
|
||||
return (y==header||comp(x,key(y->value)))?header:y;
|
||||
return (y==y0||comp(x,key(y->value())))?y0:y;
|
||||
}
|
||||
|
||||
template<
|
||||
@@ -77,18 +79,15 @@ template<
|
||||
typename CompatibleKey,typename CompatibleCompare
|
||||
>
|
||||
inline Node* ordered_index_lower_bound(
|
||||
Node* header,const KeyFromValue& key,const CompatibleKey& x,
|
||||
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||
const CompatibleCompare& comp)
|
||||
{
|
||||
Node* y=header;
|
||||
Node* z=Node::from_impl(header->parent());
|
||||
|
||||
while(z){
|
||||
if(!comp(key(z->value),x)){
|
||||
y=z;
|
||||
z=Node::from_impl(z->left());
|
||||
while(top){
|
||||
if(!comp(key(top->value()),x)){
|
||||
y=top;
|
||||
top=Node::from_impl(top->left());
|
||||
}
|
||||
else z=Node::from_impl(z->right());
|
||||
else top=Node::from_impl(top->right());
|
||||
}
|
||||
|
||||
return y;
|
||||
@@ -99,23 +98,46 @@ template<
|
||||
typename CompatibleKey,typename CompatibleCompare
|
||||
>
|
||||
inline Node* ordered_index_upper_bound(
|
||||
Node* header,const KeyFromValue& key,const CompatibleKey& x,
|
||||
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||
const CompatibleCompare& comp)
|
||||
{
|
||||
Node* y=header;
|
||||
Node* z=Node::from_impl(header->parent());
|
||||
|
||||
while(z){
|
||||
if(comp(x,key(z->value))){
|
||||
y=z;
|
||||
z=Node::from_impl(z->left());
|
||||
while(top){
|
||||
if(comp(x,key(top->value()))){
|
||||
y=top;
|
||||
top=Node::from_impl(top->left());
|
||||
}
|
||||
else z=Node::from_impl(z->right());
|
||||
else top=Node::from_impl(top->right());
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
template<
|
||||
typename Node,typename KeyFromValue,
|
||||
typename CompatibleKey,typename CompatibleCompare
|
||||
>
|
||||
inline std::pair<Node*,Node*> ordered_index_equal_range(
|
||||
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||
const CompatibleCompare& comp)
|
||||
{
|
||||
while(top){
|
||||
if(comp(key(top->value()),x)){
|
||||
top=Node::from_impl(top->right());
|
||||
}
|
||||
else if(comp(x,key(top->value()))){
|
||||
y=top;
|
||||
top=Node::from_impl(top->left());
|
||||
}
|
||||
else{
|
||||
return std::pair<Node*,Node*>(
|
||||
ordered_index_lower_bound(Node::from_impl(top->left()),top,key,x,comp),
|
||||
ordered_index_upper_bound(Node::from_impl(top->right()),y,key,x,comp));
|
||||
}
|
||||
}
|
||||
|
||||
return std::pair<Node*,Node*>(y,y);
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaqu匤 M L�ez Mu�z.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_LOADER_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_LOADER_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/detail/allocator_utilities.hpp>
|
||||
#include <boost/multi_index/detail/auto_space.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* This class implements a serialization rearranger for random access
|
||||
* indices. In order to achieve O(n) performance, the following strategy
|
||||
* is followed: the nodes of the index are handled as if in a bidirectional
|
||||
* list, where the next pointers are stored in the original
|
||||
* random_access_index_ptr_array and the prev pointers are stored in
|
||||
* an auxiliary array. Rearranging of nodes in such a bidirectional list
|
||||
* is constant time. Once all the arrangements are performed (on destruction
|
||||
* time) the list is traversed in reverse order and
|
||||
* pointers are swapped and set accordingly so that they recover its
|
||||
* original semantics ( *(node->up())==node ) while retaining the
|
||||
* new order.
|
||||
*/
|
||||
|
||||
template<typename Allocator>
|
||||
class random_access_index_loader_base:private noncopyable
|
||||
{
|
||||
protected:
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
random_access_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type node_impl_type;
|
||||
typedef typename node_impl_type::pointer node_impl_pointer;
|
||||
typedef random_access_index_ptr_array<Allocator> ptr_array;
|
||||
|
||||
random_access_index_loader_base(const Allocator& al_,ptr_array& ptrs_):
|
||||
al(al_),
|
||||
ptrs(ptrs_),
|
||||
header(*ptrs.end()),
|
||||
prev_spc(al,0),
|
||||
preprocessed(false)
|
||||
{}
|
||||
|
||||
~random_access_index_loader_base()
|
||||
{
|
||||
if(preprocessed)
|
||||
{
|
||||
node_impl_pointer n=header;
|
||||
next(n)=n;
|
||||
|
||||
for(std::size_t i=ptrs.size();i--;){
|
||||
n=prev(n);
|
||||
std::size_t d=position(n);
|
||||
if(d!=i){
|
||||
node_impl_pointer m=prev(next_at(i));
|
||||
std::swap(m->up(),n->up());
|
||||
next_at(d)=next_at(i);
|
||||
std::swap(prev_at(d),prev_at(i));
|
||||
}
|
||||
next(n)=n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rearrange(node_impl_pointer position,node_impl_pointer x)
|
||||
{
|
||||
preprocess(); /* only incur this penalty if rearrange() is ever called */
|
||||
if(position==node_impl_pointer(0))position=header;
|
||||
next(prev(x))=next(x);
|
||||
prev(next(x))=prev(x);
|
||||
prev(x)=position;
|
||||
next(x)=next(position);
|
||||
next(prev(x))=prev(next(x))=x;
|
||||
}
|
||||
|
||||
private:
|
||||
void preprocess()
|
||||
{
|
||||
if(!preprocessed){
|
||||
/* get space for the auxiliary prev array */
|
||||
auto_space<node_impl_pointer,Allocator> tmp(al,ptrs.size()+1);
|
||||
prev_spc.swap(tmp);
|
||||
|
||||
/* prev_spc elements point to the prev nodes */
|
||||
std::rotate_copy(
|
||||
&*ptrs.begin(),&*ptrs.end(),&*ptrs.end()+1,&*prev_spc.data());
|
||||
|
||||
/* ptrs elements point to the next nodes */
|
||||
std::rotate(&*ptrs.begin(),&*ptrs.begin()+1,&*ptrs.end()+1);
|
||||
|
||||
preprocessed=true;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t position(node_impl_pointer x)const
|
||||
{
|
||||
return (std::size_t)(x->up()-ptrs.begin());
|
||||
}
|
||||
|
||||
node_impl_pointer& next_at(std::size_t n)const
|
||||
{
|
||||
return *ptrs.at(n);
|
||||
}
|
||||
|
||||
node_impl_pointer& prev_at(std::size_t n)const
|
||||
{
|
||||
return *(prev_spc.data()+n);
|
||||
}
|
||||
|
||||
node_impl_pointer& next(node_impl_pointer x)const
|
||||
{
|
||||
return *(x->up());
|
||||
}
|
||||
|
||||
node_impl_pointer& prev(node_impl_pointer x)const
|
||||
{
|
||||
return prev_at(position(x));
|
||||
}
|
||||
|
||||
Allocator al;
|
||||
ptr_array& ptrs;
|
||||
node_impl_pointer header;
|
||||
auto_space<node_impl_pointer,Allocator> prev_spc;
|
||||
bool preprocessed;
|
||||
};
|
||||
|
||||
template<typename Node,typename Allocator>
|
||||
class random_access_index_loader:
|
||||
private random_access_index_loader_base<Allocator>
|
||||
{
|
||||
typedef random_access_index_loader_base<Allocator> super;
|
||||
typedef typename super::node_impl_pointer node_impl_pointer;
|
||||
typedef typename super::ptr_array ptr_array;
|
||||
|
||||
public:
|
||||
random_access_index_loader(const Allocator& al_,ptr_array& ptrs_):
|
||||
super(al_,ptrs_)
|
||||
{}
|
||||
|
||||
void rearrange(Node* position,Node *x)
|
||||
{
|
||||
super::rearrange(position?position->impl():node_impl_pointer(0),x->impl());
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,281 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_NODE_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_NODE_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/detail/allocator_utilities.hpp>
|
||||
#include <boost/math/common_factor_rt.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template<typename Allocator>
|
||||
struct random_access_index_node_impl
|
||||
{
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,random_access_index_node_impl
|
||||
>::type
|
||||
>::type::pointer pointer;
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,random_access_index_node_impl
|
||||
>::type
|
||||
>::type::const_pointer const_pointer;
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,pointer
|
||||
>::type
|
||||
>::type::pointer ptr_pointer;
|
||||
|
||||
ptr_pointer& up(){return up_;}
|
||||
ptr_pointer up()const{return up_;}
|
||||
|
||||
/* interoperability with rnd_node_iterator */
|
||||
|
||||
static void increment(pointer& x)
|
||||
{
|
||||
x=*(x->up()+1);
|
||||
}
|
||||
|
||||
static void decrement(pointer& x)
|
||||
{
|
||||
x=*(x->up()-1);
|
||||
}
|
||||
|
||||
static void advance(pointer& x,std::ptrdiff_t n)
|
||||
{
|
||||
x=*(x->up()+n);
|
||||
}
|
||||
|
||||
static std::ptrdiff_t distance(pointer x,pointer y)
|
||||
{
|
||||
return y->up()-x->up();
|
||||
}
|
||||
|
||||
/* algorithmic stuff */
|
||||
|
||||
static void relocate(ptr_pointer pos,ptr_pointer x)
|
||||
{
|
||||
pointer n=*x;
|
||||
if(x<pos){
|
||||
extract(x,pos);
|
||||
*(pos-1)=n;
|
||||
n->up()=pos-1;
|
||||
}
|
||||
else{
|
||||
while(x!=pos){
|
||||
*x=*(x-1);
|
||||
(*x)->up()=x;
|
||||
--x;
|
||||
}
|
||||
*pos=n;
|
||||
n->up()=pos;
|
||||
}
|
||||
};
|
||||
|
||||
static void relocate(ptr_pointer pos,ptr_pointer first,ptr_pointer last)
|
||||
{
|
||||
ptr_pointer begin,middle,end;
|
||||
if(pos<first){
|
||||
begin=pos;
|
||||
middle=first;
|
||||
end=last;
|
||||
}
|
||||
else{
|
||||
begin=first;
|
||||
middle=last;
|
||||
end=pos;
|
||||
}
|
||||
|
||||
std::ptrdiff_t n=end-begin;
|
||||
std::ptrdiff_t m=middle-begin;
|
||||
std::ptrdiff_t n_m=n-m;
|
||||
std::ptrdiff_t p=math::gcd(n,m);
|
||||
|
||||
for(std::ptrdiff_t i=0;i<p;++i){
|
||||
pointer tmp=begin[i];
|
||||
for(std::ptrdiff_t j=i,k;;){
|
||||
if(j<n_m)k=j+m;
|
||||
else k=j-n_m;
|
||||
if(k==i){
|
||||
*(begin+j)=tmp;
|
||||
(*(begin+j))->up()=begin+j;
|
||||
break;
|
||||
}
|
||||
else{
|
||||
*(begin+j)=*(begin+k);
|
||||
(*(begin+j))->up()=begin+j;
|
||||
}
|
||||
|
||||
if(k<n_m)j=k+m;
|
||||
else j=k-n_m;
|
||||
if(j==i){
|
||||
*(begin+k)=tmp;
|
||||
(*(begin+k))->up()=begin+k;
|
||||
break;
|
||||
}
|
||||
else{
|
||||
*(begin+k)=*(begin+j);
|
||||
(*(begin+k))->up()=begin+k;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void extract(ptr_pointer x,ptr_pointer pend)
|
||||
{
|
||||
--pend;
|
||||
while(x!=pend){
|
||||
*x=*(x+1);
|
||||
(*x)->up()=x;
|
||||
++x;
|
||||
}
|
||||
}
|
||||
|
||||
static void transfer(
|
||||
ptr_pointer pbegin0,ptr_pointer pend0,ptr_pointer pbegin1)
|
||||
{
|
||||
while(pbegin0!=pend0){
|
||||
*pbegin1=*pbegin0++;
|
||||
(*pbegin1)->up()=pbegin1;
|
||||
++pbegin1;
|
||||
}
|
||||
}
|
||||
|
||||
static void reverse(ptr_pointer pbegin,ptr_pointer pend)
|
||||
{
|
||||
std::ptrdiff_t d=(pend-pbegin)/2;
|
||||
for(std::ptrdiff_t i=0;i<d;++i){
|
||||
std::swap(*pbegin,*--pend);
|
||||
(*pbegin)->up()=pbegin;
|
||||
(*pend)->up()=pend;
|
||||
++pbegin;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ptr_pointer up_;
|
||||
};
|
||||
|
||||
template<typename Super>
|
||||
struct random_access_index_node_trampoline:
|
||||
prevent_eti<
|
||||
Super,
|
||||
random_access_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
typename Super::allocator_type,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type
|
||||
{
|
||||
typedef typename prevent_eti<
|
||||
Super,
|
||||
random_access_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
typename Super::allocator_type,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type impl_type;
|
||||
};
|
||||
|
||||
template<typename Super>
|
||||
struct random_access_index_node:
|
||||
Super,random_access_index_node_trampoline<Super>
|
||||
{
|
||||
private:
|
||||
typedef random_access_index_node_trampoline<Super> trampoline;
|
||||
|
||||
public:
|
||||
typedef typename trampoline::impl_type impl_type;
|
||||
typedef typename trampoline::pointer impl_pointer;
|
||||
typedef typename trampoline::const_pointer const_impl_pointer;
|
||||
typedef typename trampoline::ptr_pointer impl_ptr_pointer;
|
||||
|
||||
impl_ptr_pointer& up(){return trampoline::up();}
|
||||
impl_ptr_pointer up()const{return trampoline::up();}
|
||||
|
||||
impl_pointer impl()
|
||||
{
|
||||
return static_cast<impl_pointer>(
|
||||
static_cast<impl_type*>(static_cast<trampoline*>(this)));
|
||||
}
|
||||
|
||||
const_impl_pointer impl()const
|
||||
{
|
||||
return static_cast<const_impl_pointer>(
|
||||
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
|
||||
}
|
||||
|
||||
static random_access_index_node* from_impl(impl_pointer x)
|
||||
{
|
||||
return static_cast<random_access_index_node*>(
|
||||
static_cast<trampoline*>(&*x));
|
||||
}
|
||||
|
||||
static const random_access_index_node* from_impl(const_impl_pointer x)
|
||||
{
|
||||
return static_cast<const random_access_index_node*>(
|
||||
static_cast<const trampoline*>(&*x));
|
||||
}
|
||||
|
||||
/* interoperability with rnd_node_iterator */
|
||||
|
||||
static void increment(random_access_index_node*& x)
|
||||
{
|
||||
impl_pointer xi=x->impl();
|
||||
trampoline::increment(xi);
|
||||
x=from_impl(xi);
|
||||
}
|
||||
|
||||
static void decrement(random_access_index_node*& x)
|
||||
{
|
||||
impl_pointer xi=x->impl();
|
||||
trampoline::decrement(xi);
|
||||
x=from_impl(xi);
|
||||
}
|
||||
|
||||
static void advance(random_access_index_node*& x,std::ptrdiff_t n)
|
||||
{
|
||||
impl_pointer xi=x->impl();
|
||||
trampoline::advance(xi,n);
|
||||
x=from_impl(xi);
|
||||
}
|
||||
|
||||
static std::ptrdiff_t distance(
|
||||
random_access_index_node* x,random_access_index_node* y)
|
||||
{
|
||||
return trampoline::distance(x->impl(),y->impl());
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,208 @@
|
||||
/* Copyright 2003-2009 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* Common code for random_access_index memfuns having templatized and
|
||||
* non-templatized versions.
|
||||
*/
|
||||
|
||||
template<typename Node,typename Allocator,typename Predicate>
|
||||
Node* random_access_index_remove(
|
||||
random_access_index_ptr_array<Allocator>& ptrs,Predicate pred
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
|
||||
{
|
||||
typedef typename Node::value_type value_type;
|
||||
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
|
||||
|
||||
impl_ptr_pointer first=ptrs.begin(),
|
||||
res=first,
|
||||
last=ptrs.end();
|
||||
for(;first!=last;++first){
|
||||
if(!pred(
|
||||
const_cast<const value_type&>(Node::from_impl(*first)->value()))){
|
||||
if(first!=res){
|
||||
std::swap(*first,*res);
|
||||
(*first)->up()=first;
|
||||
(*res)->up()=res;
|
||||
}
|
||||
++res;
|
||||
}
|
||||
}
|
||||
return Node::from_impl(*res);
|
||||
}
|
||||
|
||||
template<typename Node,typename Allocator,class BinaryPredicate>
|
||||
Node* random_access_index_unique(
|
||||
random_access_index_ptr_array<Allocator>& ptrs,BinaryPredicate binary_pred
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
|
||||
{
|
||||
typedef typename Node::value_type value_type;
|
||||
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
|
||||
|
||||
impl_ptr_pointer first=ptrs.begin(),
|
||||
res=first,
|
||||
last=ptrs.end();
|
||||
if(first!=last){
|
||||
for(;++first!=last;){
|
||||
if(!binary_pred(
|
||||
const_cast<const value_type&>(Node::from_impl(*res)->value()),
|
||||
const_cast<const value_type&>(Node::from_impl(*first)->value()))){
|
||||
++res;
|
||||
if(first!=res){
|
||||
std::swap(*first,*res);
|
||||
(*first)->up()=first;
|
||||
(*res)->up()=res;
|
||||
}
|
||||
}
|
||||
}
|
||||
++res;
|
||||
}
|
||||
return Node::from_impl(*res);
|
||||
}
|
||||
|
||||
template<typename Node,typename Allocator,typename Compare>
|
||||
void random_access_index_inplace_merge(
|
||||
const Allocator& al,
|
||||
random_access_index_ptr_array<Allocator>& ptrs,
|
||||
BOOST_DEDUCED_TYPENAME Node::impl_ptr_pointer first1,Compare comp
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
|
||||
{
|
||||
typedef typename Node::value_type value_type;
|
||||
typedef typename Node::impl_pointer impl_pointer;
|
||||
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
|
||||
|
||||
auto_space<impl_pointer,Allocator> spc(al,ptrs.size());
|
||||
|
||||
impl_ptr_pointer first0=ptrs.begin(),
|
||||
last0=first1,
|
||||
last1=ptrs.end(),
|
||||
out=spc.data();
|
||||
while(first0!=last0&&first1!=last1){
|
||||
if(comp(
|
||||
const_cast<const value_type&>(Node::from_impl(*first1)->value()),
|
||||
const_cast<const value_type&>(Node::from_impl(*first0)->value()))){
|
||||
*out++=*first1++;
|
||||
}
|
||||
else{
|
||||
*out++=*first0++;
|
||||
}
|
||||
}
|
||||
std::copy(&*first0,&*last0,&*out);
|
||||
std::copy(&*first1,&*last1,&*out);
|
||||
|
||||
first1=ptrs.begin();
|
||||
out=spc.data();
|
||||
while(first1!=last1){
|
||||
*first1=*out++;
|
||||
(*first1)->up()=first1;
|
||||
++first1;
|
||||
}
|
||||
}
|
||||
|
||||
/* sorting */
|
||||
|
||||
/* auxiliary stuff */
|
||||
|
||||
template<typename Node,typename Compare>
|
||||
struct random_access_index_sort_compare:
|
||||
std::binary_function<
|
||||
typename Node::impl_pointer,
|
||||
typename Node::impl_pointer,bool>
|
||||
{
|
||||
random_access_index_sort_compare(Compare comp_=Compare()):comp(comp_){}
|
||||
|
||||
bool operator()(
|
||||
typename Node::impl_pointer x,typename Node::impl_pointer y)const
|
||||
{
|
||||
typedef typename Node::value_type value_type;
|
||||
|
||||
return comp(
|
||||
const_cast<const value_type&>(Node::from_impl(x)->value()),
|
||||
const_cast<const value_type&>(Node::from_impl(y)->value()));
|
||||
}
|
||||
|
||||
private:
|
||||
Compare comp;
|
||||
};
|
||||
|
||||
template<typename Node,typename Allocator,class Compare>
|
||||
void random_access_index_sort(
|
||||
const Allocator& al,
|
||||
random_access_index_ptr_array<Allocator>& ptrs,
|
||||
Compare comp
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
|
||||
{
|
||||
/* The implementation is extremely simple: an auxiliary
|
||||
* array of pointers is sorted using stdlib facilities and
|
||||
* then used to rearrange the index. This is suboptimal
|
||||
* in space and time, but has some advantages over other
|
||||
* possible approaches:
|
||||
* - Use std::stable_sort() directly on ptrs using some
|
||||
* special iterator in charge of maintaining pointers
|
||||
* and up() pointers in sync: we cannot guarantee
|
||||
* preservation of the container invariants in the face of
|
||||
* exceptions, if, for instance, std::stable_sort throws
|
||||
* when ptrs transitorily contains duplicate elements.
|
||||
* - Rewrite the internal algorithms of std::stable_sort
|
||||
* adapted for this case: besides being a fair amount of
|
||||
* work, making a stable sort compatible with Boost.MultiIndex
|
||||
* invariants (basically, no duplicates or missing elements
|
||||
* even if an exception is thrown) is complicated, error-prone
|
||||
* and possibly won't perform much better than the
|
||||
* solution adopted.
|
||||
*/
|
||||
|
||||
if(ptrs.size()<=1)return;
|
||||
|
||||
typedef typename Node::value_type value_type;
|
||||
typedef typename Node::impl_pointer impl_pointer;
|
||||
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
|
||||
typedef random_access_index_sort_compare<
|
||||
Node,Compare> ptr_compare;
|
||||
|
||||
impl_ptr_pointer first=ptrs.begin();
|
||||
impl_ptr_pointer last=ptrs.end();
|
||||
auto_space<
|
||||
impl_pointer,
|
||||
Allocator> spc(al,ptrs.size());
|
||||
impl_ptr_pointer buf=spc.data();
|
||||
|
||||
std::copy(&*first,&*last,&*buf);
|
||||
std::stable_sort(&*buf,&*buf+ptrs.size(),ptr_compare(comp));
|
||||
|
||||
while(first!=last){
|
||||
*first=*buf++;
|
||||
(*first)->up()=first;
|
||||
++first;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_PTR_ARRAY_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_PTR_ARRAY_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/detail/allocator_utilities.hpp>
|
||||
#include <boost/multi_index/detail/auto_space.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
#include <boost/multi_index/detail/rnd_index_node.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* pointer structure for use by random access indices */
|
||||
|
||||
template<typename Allocator>
|
||||
class random_access_index_ptr_array:private noncopyable
|
||||
{
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
random_access_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type node_impl_type;
|
||||
|
||||
public:
|
||||
typedef typename node_impl_type::pointer value_type;
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,value_type
|
||||
>::type
|
||||
>::type::pointer pointer;
|
||||
|
||||
random_access_index_ptr_array(
|
||||
const Allocator& al,value_type end_,std::size_t size):
|
||||
size_(size),
|
||||
capacity_(size),
|
||||
spc(al,capacity_+1)
|
||||
{
|
||||
*end()=end_;
|
||||
end_->up()=end();
|
||||
}
|
||||
|
||||
std::size_t size()const{return size_;}
|
||||
std::size_t capacity()const{return capacity_;}
|
||||
|
||||
void room_for_one()
|
||||
{
|
||||
if(size_==capacity_){
|
||||
reserve(capacity_<=10?15:capacity_+capacity_/2);
|
||||
}
|
||||
}
|
||||
|
||||
void reserve(std::size_t c)
|
||||
{
|
||||
if(c>capacity_){
|
||||
auto_space<value_type,Allocator> spc1(spc.get_allocator(),c+1);
|
||||
node_impl_type::transfer(begin(),end()+1,spc1.data());
|
||||
spc.swap(spc1);
|
||||
capacity_=c;
|
||||
}
|
||||
}
|
||||
|
||||
pointer begin()const{return ptrs();}
|
||||
pointer end()const{return ptrs()+size_;}
|
||||
pointer at(std::size_t n)const{return ptrs()+n;}
|
||||
|
||||
void push_back(value_type x)
|
||||
{
|
||||
*(end()+1)=*end();
|
||||
(*(end()+1))->up()=end()+1;
|
||||
*end()=x;
|
||||
(*end())->up()=end();
|
||||
++size_;
|
||||
}
|
||||
|
||||
void erase(value_type x)
|
||||
{
|
||||
node_impl_type::extract(x->up(),end()+1);
|
||||
--size_;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
*begin()=*end();
|
||||
(*begin())->up()=begin();
|
||||
size_=0;
|
||||
}
|
||||
|
||||
void swap(random_access_index_ptr_array& x)
|
||||
{
|
||||
std::swap(size_,x.size_);
|
||||
std::swap(capacity_,x.capacity_);
|
||||
spc.swap(x.spc);
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t size_;
|
||||
std::size_t capacity_;
|
||||
auto_space<value_type,Allocator> spc;
|
||||
|
||||
pointer ptrs()const
|
||||
{
|
||||
return spc.data();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Allocator>
|
||||
void swap(
|
||||
random_access_index_ptr_array<Allocator>& x,
|
||||
random_access_index_ptr_array<Allocator>& y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,139 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_NODE_ITERATOR_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_RND_NODE_ITERATOR_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* Iterator class for node-based indices with random access iterators. */
|
||||
|
||||
template<typename Node>
|
||||
class rnd_node_iterator:
|
||||
public random_access_iterator_helper<
|
||||
rnd_node_iterator<Node>,
|
||||
typename Node::value_type,
|
||||
std::ptrdiff_t,
|
||||
const typename Node::value_type*,
|
||||
const typename Node::value_type&>
|
||||
{
|
||||
public:
|
||||
rnd_node_iterator(){}
|
||||
explicit rnd_node_iterator(Node* node_):node(node_){}
|
||||
|
||||
const typename Node::value_type& operator*()const
|
||||
{
|
||||
return node->value();
|
||||
}
|
||||
|
||||
rnd_node_iterator& operator++()
|
||||
{
|
||||
Node::increment(node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
rnd_node_iterator& operator--()
|
||||
{
|
||||
Node::decrement(node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
rnd_node_iterator& operator+=(std::ptrdiff_t n)
|
||||
{
|
||||
Node::advance(node,n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
rnd_node_iterator& operator-=(std::ptrdiff_t n)
|
||||
{
|
||||
Node::advance(node,-n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
/* Serialization. As for why the following is public,
|
||||
* see explanation in safe_mode_iterator notes in safe_mode.hpp.
|
||||
*/
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
typedef typename Node::base_type node_base_type;
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive& ar,const unsigned int)const
|
||||
{
|
||||
node_base_type* bnode=node;
|
||||
ar<<serialization::make_nvp("pointer",bnode);
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive& ar,const unsigned int)
|
||||
{
|
||||
node_base_type* bnode;
|
||||
ar>>serialization::make_nvp("pointer",bnode);
|
||||
node=static_cast<Node*>(bnode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get_node is not to be used by the user */
|
||||
|
||||
typedef Node node_type;
|
||||
|
||||
Node* get_node()const{return node;}
|
||||
|
||||
private:
|
||||
Node* node;
|
||||
};
|
||||
|
||||
template<typename Node>
|
||||
bool operator==(
|
||||
const rnd_node_iterator<Node>& x,
|
||||
const rnd_node_iterator<Node>& y)
|
||||
{
|
||||
return x.get_node()==y.get_node();
|
||||
}
|
||||
|
||||
template<typename Node>
|
||||
bool operator<(
|
||||
const rnd_node_iterator<Node>& x,
|
||||
const rnd_node_iterator<Node>& y)
|
||||
{
|
||||
return Node::distance(x.get_node(),y.get_node())>0;
|
||||
}
|
||||
|
||||
template<typename Node>
|
||||
std::ptrdiff_t operator-(
|
||||
const rnd_node_iterator<Node>& x,
|
||||
const rnd_node_iterator<Node>& y)
|
||||
{
|
||||
return Node::distance(y.get_node(),x.get_node());
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_SAFE_CTR_PROXY_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_SAFE_CTR_PROXY_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
#include <boost/multi_index/detail/safe_mode.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* A safe iterator is instantiated in the form
|
||||
* safe_iterator<Iterator,Container>: MSVC++ 6.0 has serious troubles with
|
||||
* the resulting symbols names, given that index names (which stand for
|
||||
* Container) are fairly long themselves. safe_ctr_proxy does not statically
|
||||
* depend on Container, and provides the necessary methods (begin and end) to
|
||||
* the safe mode framework via an abstract interface. With safe_ctr_proxy,
|
||||
* instead of deriving from safe_container<Container> the following base class
|
||||
* must be used:
|
||||
*
|
||||
* safe_ctr_proxy_impl<Iterator,Container>
|
||||
*
|
||||
* where Iterator is the type of the *unsafe* iterator being wrapped.
|
||||
* The corresponding safe iterator instantiation is then
|
||||
*
|
||||
* safe_iterator<Iterator,safe_ctr_proxy<Iterator> >,
|
||||
*
|
||||
* which does not include the name of Container.
|
||||
*/
|
||||
|
||||
template<typename Iterator>
|
||||
class safe_ctr_proxy:
|
||||
public safe_mode::safe_container<safe_ctr_proxy<Iterator> >
|
||||
{
|
||||
public:
|
||||
typedef safe_mode::safe_iterator<Iterator,safe_ctr_proxy> iterator;
|
||||
typedef iterator const_iterator;
|
||||
|
||||
iterator begin(){return begin_impl();}
|
||||
const_iterator begin()const{return begin_impl();}
|
||||
iterator end(){return end_impl();}
|
||||
const_iterator end()const{return end_impl();}
|
||||
|
||||
protected:
|
||||
virtual iterator begin_impl()=0;
|
||||
virtual const_iterator begin_impl()const=0;
|
||||
virtual iterator end_impl()=0;
|
||||
virtual const_iterator end_impl()const=0;
|
||||
};
|
||||
|
||||
template<typename Iterator,typename Container>
|
||||
class safe_ctr_proxy_impl:public safe_ctr_proxy<Iterator>
|
||||
{
|
||||
typedef safe_ctr_proxy<Iterator> super;
|
||||
typedef Container container_type;
|
||||
|
||||
public:
|
||||
typedef typename super::iterator iterator;
|
||||
typedef typename super::const_iterator const_iterator;
|
||||
|
||||
virtual iterator begin_impl(){return container().begin();}
|
||||
virtual const_iterator begin_impl()const{return container().begin();}
|
||||
virtual iterator end_impl(){return container().end();}
|
||||
virtual const_iterator end_impl()const{return container().end();}
|
||||
|
||||
private:
|
||||
container_type& container()
|
||||
{
|
||||
return *static_cast<container_type*>(this);
|
||||
}
|
||||
|
||||
const container_type& container()const
|
||||
{
|
||||
return *static_cast<const container_type*>(this);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* workaround */
|
||||
|
||||
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2009 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -13,22 +13,11 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/multi_index/detail/access_specifier.hpp>
|
||||
#include <boost/multi_index/safe_mode_errors.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
/* Safe mode machinery, in the spirit of Cay Hortmann's "Safe STL"
|
||||
* (http://www.horstmann.com/safestl.html).
|
||||
* In this mode, containers of type Container are derived from
|
||||
* safe_container<Container>, and their corresponding iterators
|
||||
* are derived from safe_iterator<Container>. These classes provide
|
||||
* are wrapped with safe_iterator. These classes provide
|
||||
* an internal record of which iterators are at a given moment associated
|
||||
* to a given container, and properly mark the iterators as invalid
|
||||
* when the container gets destroyed.
|
||||
@@ -36,6 +25,11 @@ namespace multi_index{
|
||||
* kept by the container. More elaborate data structures would yield better
|
||||
* performance, but I decided to keep complexity to a minimum since
|
||||
* speed is not an issue here.
|
||||
* Safe mode iterators automatically check that only proper operations
|
||||
* are performed on them: for instance, an invalid iterator cannot be
|
||||
* dereferenced. Additionally, a set of utilty macros and functions are
|
||||
* provided that serve to implement preconditions and cooperate with
|
||||
* the framework within the container.
|
||||
* Iterators can also be unchecked, i.e. they do not have info about
|
||||
* which container they belong in. This situation arises when the iterator
|
||||
* is restored from a serialization archive: only information on the node
|
||||
@@ -47,182 +41,90 @@ namespace multi_index{
|
||||
* for use within the limits of Boost.MultiIndex.
|
||||
*/
|
||||
|
||||
namespace safe_mode{
|
||||
|
||||
/* Invalidates all iterators equivalent to that given. Defined before
|
||||
* safe_iterator_base and safe_container_base as these contain friendship
|
||||
* declarations to this function.
|
||||
/* Assertion macros. These resolve to no-ops if
|
||||
* !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE).
|
||||
*/
|
||||
|
||||
template<typename Iterator>
|
||||
inline void detach_equivalent_iterators(Iterator& it)
|
||||
{
|
||||
if(it.valid()){
|
||||
Iterator *prev_,*next_;
|
||||
for(
|
||||
prev_=static_cast<Iterator*>(&it.cont->header);
|
||||
(next_=static_cast<Iterator*>(prev_->next))!=0;){
|
||||
if(next_!=&it&&*next_==it){
|
||||
prev_->next=next_->next;
|
||||
next_->cont=0;
|
||||
}
|
||||
else prev_=next_;
|
||||
}
|
||||
it.detach();
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace multi_index::safe_mode */
|
||||
|
||||
namespace detail{
|
||||
|
||||
class safe_container_base;
|
||||
|
||||
class safe_iterator_base
|
||||
{
|
||||
public:
|
||||
bool valid()const{return cont!=0;}
|
||||
bool unchecked()const{return unchecked_;}
|
||||
|
||||
inline void detach();
|
||||
|
||||
void uncheck()
|
||||
{
|
||||
detach();
|
||||
unchecked_=true;
|
||||
}
|
||||
|
||||
protected:
|
||||
safe_iterator_base():cont(0),next(0),unchecked_(false){}
|
||||
|
||||
explicit safe_iterator_base(safe_container_base* cont_):
|
||||
unchecked_(false)
|
||||
{
|
||||
attach(cont_);
|
||||
}
|
||||
|
||||
safe_iterator_base(const safe_iterator_base& it):
|
||||
unchecked_(it.unchecked_)
|
||||
{
|
||||
attach(it.cont);
|
||||
}
|
||||
|
||||
safe_iterator_base& operator=(const safe_iterator_base& it)
|
||||
{
|
||||
unchecked_=it.unchecked_;
|
||||
safe_container_base* new_cont=it.cont;
|
||||
if(cont!=new_cont){
|
||||
detach();
|
||||
attach(new_cont);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~safe_iterator_base()
|
||||
{
|
||||
detach();
|
||||
}
|
||||
|
||||
const safe_container_base* owner()const{return cont;}
|
||||
|
||||
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
friend class safe_container_base;
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template<typename Iterator> friend
|
||||
void safe_mode::detach_equivalent_iterators(Iterator&);
|
||||
#if !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#undef BOOST_MULTI_INDEX_SAFE_MODE_ASSERT
|
||||
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) ((void)0)
|
||||
#else
|
||||
#if !defined(BOOST_MULTI_INDEX_SAFE_MODE_ASSERT)
|
||||
#include <boost/assert.hpp>
|
||||
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) BOOST_ASSERT(expr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
inline void attach(safe_container_base* cont_);
|
||||
#define BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_valid_iterator(it), \
|
||||
safe_mode::invalid_iterator);
|
||||
|
||||
safe_container_base* cont;
|
||||
safe_iterator_base* next;
|
||||
bool unchecked_;
|
||||
};
|
||||
#define BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(it) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_dereferenceable_iterator(it), \
|
||||
safe_mode::not_dereferenceable_iterator);
|
||||
|
||||
class safe_container_base:private noncopyable
|
||||
{
|
||||
public:
|
||||
safe_container_base(){}
|
||||
#define BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(it) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_incrementable_iterator(it), \
|
||||
safe_mode::not_incrementable_iterator);
|
||||
|
||||
~safe_container_base()
|
||||
{
|
||||
detach_all_iterators();
|
||||
}
|
||||
#define BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(it) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_decrementable_iterator(it), \
|
||||
safe_mode::not_decrementable_iterator);
|
||||
|
||||
void detach_all_iterators()
|
||||
{
|
||||
for(safe_iterator_base* it=header.next;it;it=it->next)it->cont=0;
|
||||
}
|
||||
#define BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,cont) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_is_owner(it,cont), \
|
||||
safe_mode::not_owner);
|
||||
|
||||
void swap(safe_container_base& x)
|
||||
{
|
||||
for(safe_iterator_base* it0=header.next;it0;it0=it0->next)it0->cont=&x;
|
||||
for(safe_iterator_base* it1=x.header.next;it1;it1=it1->next)it1->cont=this;
|
||||
std::swap(header.cont,x.header.cont);
|
||||
std::swap(header.next,x.header.next);
|
||||
}
|
||||
#define BOOST_MULTI_INDEX_CHECK_SAME_OWNER(it0,it1) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_same_owner(it0,it1), \
|
||||
safe_mode::not_same_owner);
|
||||
|
||||
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
friend class safe_iterator_base;
|
||||
#define BOOST_MULTI_INDEX_CHECK_VALID_RANGE(it0,it1) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_valid_range(it0,it1), \
|
||||
safe_mode::invalid_range);
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template<typename Iterator> friend
|
||||
void safe_mode::detach_equivalent_iterators(Iterator&);
|
||||
#define BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(it,it0,it1) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_outside_range(it,it0,it1), \
|
||||
safe_mode::inside_range);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_IN_BOUNDS(it,n) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_in_bounds(it,n), \
|
||||
safe_mode::out_of_bounds);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(cont0,cont1) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_different_container(cont0,cont1), \
|
||||
safe_mode::same_container);
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/multi_index/detail/access_specifier.hpp>
|
||||
#include <boost/multi_index/detail/iter_adaptor.hpp>
|
||||
#include <boost/multi_index/safe_mode_errors.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#endif
|
||||
|
||||
safe_iterator_base header;
|
||||
};
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
#include <boost/detail/lightweight_mutex.hpp>
|
||||
#endif
|
||||
|
||||
void safe_iterator_base::attach(safe_container_base* cont_)
|
||||
{
|
||||
cont=cont_;
|
||||
if(cont){
|
||||
next=cont->header.next;
|
||||
cont->header.next=this;
|
||||
}
|
||||
}
|
||||
namespace boost{
|
||||
|
||||
void safe_iterator_base::detach()
|
||||
{
|
||||
if(cont){
|
||||
safe_iterator_base *prev_,*next_;
|
||||
for(prev_=&cont->header;(next_=prev_->next)!=this;prev_=next_){}
|
||||
prev_->next=next;
|
||||
cont=0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
class safe_container;
|
||||
|
||||
template<typename Container>
|
||||
class safe_iterator:public safe_iterator_base
|
||||
{
|
||||
public:
|
||||
typedef Container container_type;
|
||||
|
||||
safe_iterator():safe_iterator_base(){}
|
||||
explicit safe_iterator(safe_container<container_type>* cont_):
|
||||
safe_iterator_base(cont_){}
|
||||
|
||||
const container_type* owner()const
|
||||
{
|
||||
return
|
||||
static_cast<const container_type*>(
|
||||
static_cast<const safe_container<container_type>*>(
|
||||
safe_iterator_base::owner()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
class safe_container:public safe_container_base
|
||||
{
|
||||
public:
|
||||
void swap(safe_container<Container>& x){safe_container_base::swap(x);}
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
namespace multi_index{
|
||||
|
||||
namespace safe_mode{
|
||||
|
||||
@@ -310,6 +212,15 @@ inline bool check_outside_range(
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Iterator,typename Difference>
|
||||
inline bool check_in_bounds(const Iterator& it,Difference n)
|
||||
{
|
||||
if(it.unchecked())return true;
|
||||
if(!it.valid()) return false;
|
||||
if(n>0) return it.owner()->end()-it>=n;
|
||||
else return it.owner()->begin()-it<=n;
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
inline bool check_different_container(
|
||||
const Container& cont0,const Container& cont1)
|
||||
@@ -317,6 +228,341 @@ inline bool check_different_container(
|
||||
return &cont0!=&cont1;
|
||||
}
|
||||
|
||||
/* Invalidates all iterators equivalent to that given. Safe containers
|
||||
* must call this when deleting elements: the safe mode framework cannot
|
||||
* perform this operation automatically without outside help.
|
||||
*/
|
||||
|
||||
template<typename Iterator>
|
||||
inline void detach_equivalent_iterators(Iterator& it)
|
||||
{
|
||||
if(it.valid()){
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
boost::detail::lightweight_mutex::scoped_lock lock(it.cont->mutex);
|
||||
#endif
|
||||
|
||||
Iterator *prev_,*next_;
|
||||
for(
|
||||
prev_=static_cast<Iterator*>(&it.cont->header);
|
||||
(next_=static_cast<Iterator*>(prev_->next))!=0;){
|
||||
if(next_!=&it&&*next_==it){
|
||||
prev_->next=next_->next;
|
||||
next_->cont=0;
|
||||
}
|
||||
else prev_=next_;
|
||||
}
|
||||
}
|
||||
it.detach();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Container> class safe_container; /* fwd decl. */
|
||||
|
||||
} /* namespace multi_index::safe_mode */
|
||||
|
||||
namespace detail{
|
||||
|
||||
class safe_container_base; /* fwd decl. */
|
||||
|
||||
class safe_iterator_base
|
||||
{
|
||||
public:
|
||||
bool valid()const{return cont!=0;}
|
||||
bool unchecked()const{return unchecked_;}
|
||||
|
||||
inline void detach();
|
||||
|
||||
void uncheck()
|
||||
{
|
||||
detach();
|
||||
unchecked_=true;
|
||||
}
|
||||
|
||||
protected:
|
||||
safe_iterator_base():cont(0),next(0),unchecked_(false){}
|
||||
|
||||
explicit safe_iterator_base(safe_container_base* cont_):
|
||||
unchecked_(false)
|
||||
{
|
||||
attach(cont_);
|
||||
}
|
||||
|
||||
safe_iterator_base(const safe_iterator_base& it):
|
||||
unchecked_(it.unchecked_)
|
||||
{
|
||||
attach(it.cont);
|
||||
}
|
||||
|
||||
safe_iterator_base& operator=(const safe_iterator_base& it)
|
||||
{
|
||||
unchecked_=it.unchecked_;
|
||||
safe_container_base* new_cont=it.cont;
|
||||
if(cont!=new_cont){
|
||||
detach();
|
||||
attach(new_cont);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~safe_iterator_base()
|
||||
{
|
||||
detach();
|
||||
}
|
||||
|
||||
const safe_container_base* owner()const{return cont;}
|
||||
|
||||
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
friend class safe_container_base;
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template<typename> friend class safe_mode::safe_container;
|
||||
template<typename Iterator> friend
|
||||
void safe_mode::detach_equivalent_iterators(Iterator&);
|
||||
#endif
|
||||
|
||||
inline void attach(safe_container_base* cont_);
|
||||
|
||||
safe_container_base* cont;
|
||||
safe_iterator_base* next;
|
||||
bool unchecked_;
|
||||
};
|
||||
|
||||
class safe_container_base:private noncopyable
|
||||
{
|
||||
public:
|
||||
safe_container_base(){}
|
||||
|
||||
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
friend class safe_iterator_base;
|
||||
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template<typename Iterator> friend
|
||||
void safe_mode::detach_equivalent_iterators(Iterator&);
|
||||
#endif
|
||||
|
||||
~safe_container_base()
|
||||
{
|
||||
/* Detaches all remaining iterators, which by now will
|
||||
* be those pointing to the end of the container.
|
||||
*/
|
||||
|
||||
for(safe_iterator_base* it=header.next;it;it=it->next)it->cont=0;
|
||||
header.next=0;
|
||||
}
|
||||
|
||||
void swap(safe_container_base& x)
|
||||
{
|
||||
for(safe_iterator_base* it0=header.next;it0;it0=it0->next)it0->cont=&x;
|
||||
for(safe_iterator_base* it1=x.header.next;it1;it1=it1->next)it1->cont=this;
|
||||
std::swap(header.cont,x.header.cont);
|
||||
std::swap(header.next,x.header.next);
|
||||
}
|
||||
|
||||
safe_iterator_base header;
|
||||
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
boost::detail::lightweight_mutex mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
void safe_iterator_base::attach(safe_container_base* cont_)
|
||||
{
|
||||
cont=cont_;
|
||||
if(cont){
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
boost::detail::lightweight_mutex::scoped_lock lock(cont->mutex);
|
||||
#endif
|
||||
|
||||
next=cont->header.next;
|
||||
cont->header.next=this;
|
||||
}
|
||||
}
|
||||
|
||||
void safe_iterator_base::detach()
|
||||
{
|
||||
if(cont){
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
boost::detail::lightweight_mutex::scoped_lock lock(cont->mutex);
|
||||
#endif
|
||||
|
||||
safe_iterator_base *prev_,*next_;
|
||||
for(prev_=&cont->header;(next_=prev_->next)!=this;prev_=next_){}
|
||||
prev_->next=next;
|
||||
cont=0;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
namespace safe_mode{
|
||||
|
||||
/* In order to enable safe mode on a container:
|
||||
* - The container must derive from safe_container<container_type>,
|
||||
* - iterators must be generated via safe_iterator, which adapts a
|
||||
* preexistent unsafe iterator class.
|
||||
*/
|
||||
|
||||
template<typename Container>
|
||||
class safe_container;
|
||||
|
||||
template<typename Iterator,typename Container>
|
||||
class safe_iterator:
|
||||
public detail::iter_adaptor<safe_iterator<Iterator,Container>,Iterator>,
|
||||
public detail::safe_iterator_base
|
||||
{
|
||||
typedef detail::iter_adaptor<safe_iterator,Iterator> super;
|
||||
typedef detail::safe_iterator_base safe_super;
|
||||
|
||||
public:
|
||||
typedef Container container_type;
|
||||
typedef typename Iterator::reference reference;
|
||||
typedef typename Iterator::difference_type difference_type;
|
||||
|
||||
safe_iterator(){}
|
||||
explicit safe_iterator(safe_container<container_type>* cont_):
|
||||
safe_super(cont_){}
|
||||
template<typename T0>
|
||||
safe_iterator(const T0& t0,safe_container<container_type>* cont_):
|
||||
super(Iterator(t0)),safe_super(cont_){}
|
||||
template<typename T0,typename T1>
|
||||
safe_iterator(
|
||||
const T0& t0,const T1& t1,safe_container<container_type>* cont_):
|
||||
super(Iterator(t0,t1)),safe_super(cont_){}
|
||||
|
||||
safe_iterator& operator=(const safe_iterator& x)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
|
||||
this->base_reference()=x.base_reference();
|
||||
safe_super::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const container_type* owner()const
|
||||
{
|
||||
return
|
||||
static_cast<const container_type*>(
|
||||
static_cast<const safe_container<container_type>*>(
|
||||
this->safe_super::owner()));
|
||||
}
|
||||
|
||||
/* get_node is not to be used by the user */
|
||||
|
||||
typedef typename Iterator::node_type node_type;
|
||||
|
||||
node_type* get_node()const{return this->base_reference().get_node();}
|
||||
|
||||
private:
|
||||
friend class boost::multi_index::detail::iter_adaptor_access;
|
||||
|
||||
reference dereference()const
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);
|
||||
return *(this->base_reference());
|
||||
}
|
||||
|
||||
bool equal(const safe_iterator& x)const
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
|
||||
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(*this,x);
|
||||
return this->base_reference()==x.base_reference();
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);
|
||||
++(this->base_reference());
|
||||
}
|
||||
|
||||
void decrement()
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(*this);
|
||||
--(this->base_reference());
|
||||
}
|
||||
|
||||
void advance(difference_type n)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_IN_BOUNDS(*this,n);
|
||||
this->base_reference()+=n;
|
||||
}
|
||||
|
||||
difference_type distance_to(const safe_iterator& x)const
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
|
||||
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(*this,x);
|
||||
return x.base_reference()-this->base_reference();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
|
||||
/* Serialization. Note that Iterator::save and Iterator:load
|
||||
* are assumed to be defined and public: at first sight it seems
|
||||
* like we could have resorted to the public serialization interface
|
||||
* for doing the forwarding to the adapted iterator class:
|
||||
* ar<<base_reference();
|
||||
* ar>>base_reference();
|
||||
* but this would cause incompatibilities if a saving
|
||||
* program is in safe mode and the loading program is not, or
|
||||
* viceversa --in safe mode, the archived iterator data is one layer
|
||||
* deeper, this is especially relevant with XML archives.
|
||||
* It'd be nice if Boost.Serialization provided some forwarding
|
||||
* facility for use by adaptor classes.
|
||||
*/
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive& ar,const unsigned int version)const
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
|
||||
this->base_reference().save(ar,version);
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive& ar,const unsigned int version)
|
||||
{
|
||||
this->base_reference().load(ar,version);
|
||||
safe_super::uncheck();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
class safe_container:public detail::safe_container_base
|
||||
{
|
||||
typedef detail::safe_container_base super;
|
||||
|
||||
public:
|
||||
void detach_dereferenceable_iterators()
|
||||
{
|
||||
typedef typename Container::iterator iterator;
|
||||
|
||||
iterator end_=static_cast<Container*>(this)->end();
|
||||
iterator *prev_,*next_;
|
||||
for(
|
||||
prev_=static_cast<iterator*>(&this->header);
|
||||
(next_=static_cast<iterator*>(prev_->next))!=0;){
|
||||
if(*next_!=end_){
|
||||
prev_->next=next_->next;
|
||||
next_->cont=0;
|
||||
}
|
||||
else prev_=next_;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(safe_container<Container>& x)
|
||||
{
|
||||
super::swap(x);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace multi_index::safe_mode */
|
||||
|
||||
} /* namespace multi_index */
|
||||
@@ -325,61 +571,4 @@ inline bool check_different_container(
|
||||
|
||||
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
|
||||
|
||||
/* assertion macros */
|
||||
|
||||
#if !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#undef BOOST_MULTI_INDEX_SAFE_MODE_ASSERT
|
||||
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) ((void)0)
|
||||
#else
|
||||
#if !defined(BOOST_MULTI_INDEX_SAFE_MODE_ASSERT)
|
||||
#include <boost/assert.hpp>
|
||||
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) BOOST_ASSERT(expr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_valid_iterator(it), \
|
||||
safe_mode::invalid_iterator);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(it) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_dereferenceable_iterator(it), \
|
||||
safe_mode::not_dereferenceable_iterator);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(it) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_incrementable_iterator(it), \
|
||||
safe_mode::not_incrementable_iterator);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(it) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
|
||||
safe_mode::check_decrementable_iterator(it), \
|
||||
safe_mode::not_decrementable_iterator);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,cont) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_is_owner(it,cont), \
|
||||
safe_mode::not_owner);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_SAME_OWNER(it0,it1) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
|
||||
safe_mode::check_same_owner(it0,it1), \
|
||||
safe_mode::not_same_owner);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_VALID_RANGE(it0,it1) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_valid_range(it0,it1), \
|
||||
safe_mode::invalid_range);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(it,it0,it1) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
|
||||
safe_mode::check_outside_range(it,it0,it1), \
|
||||
safe_mode::inside_range);
|
||||
|
||||
#define BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(cont0,cont1) \
|
||||
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
|
||||
safe_mode::check_different_container(cont0,cont1), \
|
||||
safe_mode::same_container);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2011 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -13,6 +13,8 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
@@ -24,12 +26,10 @@ namespace detail{
|
||||
* ScopeGuard.h as defined in:
|
||||
* Alexandrescu, A., Marginean, P.:"Generic<Programming>: Change the Way You
|
||||
* Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000,
|
||||
* http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/
|
||||
* http://www.drdobbs.com/184403758
|
||||
* with the following modifications:
|
||||
* - General pretty formatting (pretty to my taste at least.)
|
||||
* - Naming style changed to standard C++ library requirements.
|
||||
* - safe_execute does not feature a try-catch protection, so we can
|
||||
* use this even if BOOST_NO_EXCEPTIONS is defined.
|
||||
* - Added scope_guard_impl4 and obj_scope_guard_impl3, (Boost.MultiIndex
|
||||
* needs them). A better design would provide guards for many more
|
||||
* arguments through the Boost Preprocessor Library.
|
||||
@@ -42,6 +42,18 @@ namespace detail{
|
||||
*
|
||||
* NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute
|
||||
* without an explicit qualification.
|
||||
*
|
||||
* We also define the following variants of the idiom:
|
||||
*
|
||||
* - make_guard_if_c<bool>( ... )
|
||||
* - make_guard_if<IntegralConstant>( ... )
|
||||
* - make_obj_guard_if_c<bool>( ... )
|
||||
* - make_obj_guard_if<IntegralConstant>( ... )
|
||||
* which may be used with a compile-time constant to yield
|
||||
* a "null_guard" if the boolean compile-time parameter is false,
|
||||
* or conversely, the guard is only constructed if the constant is true.
|
||||
* This is useful to avoid extra tagging, because the returned
|
||||
* null_guard can be optimzed comlpetely away by the compiler.
|
||||
*/
|
||||
|
||||
class scope_guard_impl_base
|
||||
@@ -65,7 +77,13 @@ protected:
|
||||
}
|
||||
|
||||
template<typename J>
|
||||
static void safe_execute(J& j){if(!j.dismissed_)j.execute();}
|
||||
static void safe_execute(J& j){
|
||||
BOOST_TRY{
|
||||
if(!j.dismissed_)j.execute();
|
||||
}
|
||||
BOOST_CATCH(...){}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
mutable bool dismissed_;
|
||||
|
||||
@@ -75,6 +93,35 @@ private:
|
||||
|
||||
typedef const scope_guard_impl_base& scope_guard;
|
||||
|
||||
struct null_guard : public scope_guard_impl_base
|
||||
{
|
||||
template< class T1 >
|
||||
null_guard( const T1& )
|
||||
{ }
|
||||
|
||||
template< class T1, class T2 >
|
||||
null_guard( const T1&, const T2& )
|
||||
{ }
|
||||
|
||||
template< class T1, class T2, class T3 >
|
||||
null_guard( const T1&, const T2&, const T3& )
|
||||
{ }
|
||||
|
||||
template< class T1, class T2, class T3, class T4 >
|
||||
null_guard( const T1&, const T2&, const T3&, const T4& )
|
||||
{ }
|
||||
|
||||
template< class T1, class T2, class T3, class T4, class T5 >
|
||||
null_guard( const T1&, const T2&, const T3&, const T4&, const T5& )
|
||||
{ }
|
||||
};
|
||||
|
||||
template< bool cond, class T >
|
||||
struct null_guard_return
|
||||
{
|
||||
typedef typename boost::mpl::if_c<cond,T,null_guard>::type type;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
class scope_guard_impl0:public scope_guard_impl_base
|
||||
{
|
||||
@@ -94,6 +141,20 @@ inline scope_guard_impl0<F> make_guard(F fun)
|
||||
return scope_guard_impl0<F>(fun);
|
||||
}
|
||||
|
||||
template<bool cond, typename F>
|
||||
inline typename null_guard_return<cond,scope_guard_impl0<F> >::type
|
||||
make_guard_if_c(F fun)
|
||||
{
|
||||
return typename null_guard_return<cond,scope_guard_impl0<F> >::type(fun);
|
||||
}
|
||||
|
||||
template<typename C, typename F>
|
||||
inline typename null_guard_return<C::value,scope_guard_impl0<F> >::type
|
||||
make_guard_if(F fun)
|
||||
{
|
||||
return make_guard_if<C::value>(fun);
|
||||
}
|
||||
|
||||
template<typename F,typename P1>
|
||||
class scope_guard_impl1:public scope_guard_impl_base
|
||||
{
|
||||
@@ -113,6 +174,20 @@ inline scope_guard_impl1<F,P1> make_guard(F fun,P1 p1)
|
||||
return scope_guard_impl1<F,P1>(fun,p1);
|
||||
}
|
||||
|
||||
template<bool cond, typename F,typename P1>
|
||||
inline typename null_guard_return<cond,scope_guard_impl1<F,P1> >::type
|
||||
make_guard_if_c(F fun,P1 p1)
|
||||
{
|
||||
return typename null_guard_return<cond,scope_guard_impl1<F,P1> >::type(fun,p1);
|
||||
}
|
||||
|
||||
template<typename C, typename F,typename P1>
|
||||
inline typename null_guard_return<C::value,scope_guard_impl1<F,P1> >::type
|
||||
make_guard_if(F fun,P1 p1)
|
||||
{
|
||||
return make_guard_if_c<C::value>(fun,p1);
|
||||
}
|
||||
|
||||
template<typename F,typename P1,typename P2>
|
||||
class scope_guard_impl2:public scope_guard_impl_base
|
||||
{
|
||||
@@ -133,6 +208,20 @@ inline scope_guard_impl2<F,P1,P2> make_guard(F fun,P1 p1,P2 p2)
|
||||
return scope_guard_impl2<F,P1,P2>(fun,p1,p2);
|
||||
}
|
||||
|
||||
template<bool cond, typename F,typename P1,typename P2>
|
||||
inline typename null_guard_return<cond,scope_guard_impl2<F,P1,P2> >::type
|
||||
make_guard_if_c(F fun,P1 p1,P2 p2)
|
||||
{
|
||||
return typename null_guard_return<cond,scope_guard_impl2<F,P1,P2> >::type(fun,p1,p2);
|
||||
}
|
||||
|
||||
template<typename C, typename F,typename P1,typename P2>
|
||||
inline typename null_guard_return<C::value,scope_guard_impl2<F,P1,P2> >::type
|
||||
make_guard_if(F fun,P1 p1,P2 p2)
|
||||
{
|
||||
return make_guard_if_c<C::value>(fun,p1,p2);
|
||||
}
|
||||
|
||||
template<typename F,typename P1,typename P2,typename P3>
|
||||
class scope_guard_impl3:public scope_guard_impl_base
|
||||
{
|
||||
@@ -154,6 +243,20 @@ inline scope_guard_impl3<F,P1,P2,P3> make_guard(F fun,P1 p1,P2 p2,P3 p3)
|
||||
return scope_guard_impl3<F,P1,P2,P3>(fun,p1,p2,p3);
|
||||
}
|
||||
|
||||
template<bool cond,typename F,typename P1,typename P2,typename P3>
|
||||
inline typename null_guard_return<cond,scope_guard_impl3<F,P1,P2,P3> >::type
|
||||
make_guard_if_c(F fun,P1 p1,P2 p2,P3 p3)
|
||||
{
|
||||
return typename null_guard_return<cond,scope_guard_impl3<F,P1,P2,P3> >::type(fun,p1,p2,p3);
|
||||
}
|
||||
|
||||
template<typename C,typename F,typename P1,typename P2,typename P3>
|
||||
inline typename null_guard_return< C::value,scope_guard_impl3<F,P1,P2,P3> >::type
|
||||
make_guard_if(F fun,P1 p1,P2 p2,P3 p3)
|
||||
{
|
||||
return make_guard_if_c<C::value>(fun,p1,p2,p3);
|
||||
}
|
||||
|
||||
template<typename F,typename P1,typename P2,typename P3,typename P4>
|
||||
class scope_guard_impl4:public scope_guard_impl_base
|
||||
{
|
||||
@@ -178,6 +281,22 @@ inline scope_guard_impl4<F,P1,P2,P3,P4> make_guard(
|
||||
return scope_guard_impl4<F,P1,P2,P3,P4>(fun,p1,p2,p3,p4);
|
||||
}
|
||||
|
||||
template<bool cond, typename F,typename P1,typename P2,typename P3,typename P4>
|
||||
inline typename null_guard_return<cond,scope_guard_impl4<F,P1,P2,P3,P4> >::type
|
||||
make_guard_if_c(
|
||||
F fun,P1 p1,P2 p2,P3 p3,P4 p4)
|
||||
{
|
||||
return typename null_guard_return<cond,scope_guard_impl4<F,P1,P2,P3,P4> >::type(fun,p1,p2,p3,p4);
|
||||
}
|
||||
|
||||
template<typename C, typename F,typename P1,typename P2,typename P3,typename P4>
|
||||
inline typename null_guard_return<C::value,scope_guard_impl4<F,P1,P2,P3,P4> >::type
|
||||
make_guard_if(
|
||||
F fun,P1 p1,P2 p2,P3 p3,P4 p4)
|
||||
{
|
||||
return make_guard_if_c<C::value>(fun,p1,p2,p3,p4);
|
||||
}
|
||||
|
||||
template<class Obj,typename MemFun>
|
||||
class obj_scope_guard_impl0:public scope_guard_impl_base
|
||||
{
|
||||
@@ -197,6 +316,20 @@ inline obj_scope_guard_impl0<Obj,MemFun> make_obj_guard(Obj& obj,MemFun mem_fun)
|
||||
return obj_scope_guard_impl0<Obj,MemFun>(obj,mem_fun);
|
||||
}
|
||||
|
||||
template<bool cond, class Obj,typename MemFun>
|
||||
inline typename null_guard_return<cond,obj_scope_guard_impl0<Obj,MemFun> >::type
|
||||
make_obj_guard_if_c(Obj& obj,MemFun mem_fun)
|
||||
{
|
||||
return typename null_guard_return<cond,obj_scope_guard_impl0<Obj,MemFun> >::type(obj,mem_fun);
|
||||
}
|
||||
|
||||
template<typename C, class Obj,typename MemFun>
|
||||
inline typename null_guard_return<C::value,obj_scope_guard_impl0<Obj,MemFun> >::type
|
||||
make_obj_guard_if(Obj& obj,MemFun mem_fun)
|
||||
{
|
||||
return make_obj_guard_if_c<C::value>(obj,mem_fun);
|
||||
}
|
||||
|
||||
template<class Obj,typename MemFun,typename P1>
|
||||
class obj_scope_guard_impl1:public scope_guard_impl_base
|
||||
{
|
||||
@@ -219,6 +352,20 @@ inline obj_scope_guard_impl1<Obj,MemFun,P1> make_obj_guard(
|
||||
return obj_scope_guard_impl1<Obj,MemFun,P1>(obj,mem_fun,p1);
|
||||
}
|
||||
|
||||
template<bool cond, class Obj,typename MemFun,typename P1>
|
||||
inline typename null_guard_return<cond,obj_scope_guard_impl1<Obj,MemFun,P1> >::type
|
||||
make_obj_guard_if_c( Obj& obj,MemFun mem_fun,P1 p1)
|
||||
{
|
||||
return typename null_guard_return<cond,obj_scope_guard_impl1<Obj,MemFun,P1> >::type(obj,mem_fun,p1);
|
||||
}
|
||||
|
||||
template<typename C, class Obj,typename MemFun,typename P1>
|
||||
inline typename null_guard_return<C::value,obj_scope_guard_impl1<Obj,MemFun,P1> >::type
|
||||
make_obj_guard_if( Obj& obj,MemFun mem_fun,P1 p1)
|
||||
{
|
||||
return make_obj_guard_if_c<C::value>(obj,mem_fun,p1);
|
||||
}
|
||||
|
||||
template<class Obj,typename MemFun,typename P1,typename P2>
|
||||
class obj_scope_guard_impl2:public scope_guard_impl_base
|
||||
{
|
||||
@@ -243,6 +390,20 @@ make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
|
||||
return obj_scope_guard_impl2<Obj,MemFun,P1,P2>(obj,mem_fun,p1,p2);
|
||||
}
|
||||
|
||||
template<bool cond, class Obj,typename MemFun,typename P1,typename P2>
|
||||
inline typename null_guard_return<cond,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type
|
||||
make_obj_guard_if_c(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
|
||||
{
|
||||
return typename null_guard_return<cond,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type(obj,mem_fun,p1,p2);
|
||||
}
|
||||
|
||||
template<typename C, class Obj,typename MemFun,typename P1,typename P2>
|
||||
inline typename null_guard_return<C::value,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type
|
||||
make_obj_guard_if(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
|
||||
{
|
||||
return make_obj_guard_if_c<C::value>(obj,mem_fun,p1,p2);
|
||||
}
|
||||
|
||||
template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
|
||||
class obj_scope_guard_impl3:public scope_guard_impl_base
|
||||
{
|
||||
@@ -268,6 +429,20 @@ make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
|
||||
return obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>(obj,mem_fun,p1,p2,p3);
|
||||
}
|
||||
|
||||
template<bool cond, class Obj,typename MemFun,typename P1,typename P2,typename P3>
|
||||
inline typename null_guard_return<cond,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type
|
||||
make_obj_guard_if_c(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
|
||||
{
|
||||
return typename null_guard_return<cond,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type(obj,mem_fun,p1,p2,p3);
|
||||
}
|
||||
|
||||
template<typename C, class Obj,typename MemFun,typename P1,typename P2,typename P3>
|
||||
inline typename null_guard_return<C::value,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type
|
||||
make_obj_guard_if(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
|
||||
{
|
||||
return make_obj_guard_if_c<C::value>(obj,mem_fun,p1,p2,p3);
|
||||
}
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -13,7 +13,10 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <algorithm>
|
||||
#include <boost/detail/allocator_utilities.hpp>
|
||||
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
@@ -23,48 +26,48 @@ namespace detail{
|
||||
|
||||
/* doubly-linked node for use by sequenced_index */
|
||||
|
||||
template<typename Allocator>
|
||||
struct sequenced_index_node_impl
|
||||
{
|
||||
sequenced_index_node_impl*& prior(){return prior_;}
|
||||
sequenced_index_node_impl*const & prior()const{return prior_;}
|
||||
sequenced_index_node_impl*& next(){return next_;}
|
||||
sequenced_index_node_impl*const & next()const{return next_;}
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,sequenced_index_node_impl
|
||||
>::type
|
||||
>::type::pointer pointer;
|
||||
typedef typename prevent_eti<
|
||||
Allocator,
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
Allocator,sequenced_index_node_impl
|
||||
>::type
|
||||
>::type::const_pointer const_pointer;
|
||||
|
||||
/* interoperability with index_iterator */
|
||||
pointer& prior(){return prior_;}
|
||||
pointer prior()const{return prior_;}
|
||||
pointer& next(){return next_;}
|
||||
pointer next()const{return next_;}
|
||||
|
||||
static void increment(sequenced_index_node_impl*& x){x=x->next();}
|
||||
static void decrement(sequenced_index_node_impl*& x){x=x->prior();}
|
||||
/* interoperability with bidir_node_iterator */
|
||||
|
||||
/* interoperability with index_proxy */
|
||||
|
||||
static sequenced_index_node_impl* begin(sequenced_index_node_impl* header)
|
||||
{
|
||||
return header->next();
|
||||
}
|
||||
|
||||
static sequenced_index_node_impl* end(sequenced_index_node_impl* header)
|
||||
{
|
||||
return header;
|
||||
}
|
||||
static void increment(pointer& x){x=x->next();}
|
||||
static void decrement(pointer& x){x=x->prior();}
|
||||
|
||||
/* algorithmic stuff */
|
||||
|
||||
static void link(
|
||||
sequenced_index_node_impl* x,sequenced_index_node_impl* header)
|
||||
static void link(pointer x,pointer header)
|
||||
{
|
||||
x->prior()=header->prior();
|
||||
x->next()=header;
|
||||
x->prior()->next()=x->next()->prior()=x;
|
||||
};
|
||||
|
||||
static void unlink(sequenced_index_node_impl* x)
|
||||
static void unlink(pointer x)
|
||||
{
|
||||
x->prior()->next()=x->next();
|
||||
x->next()->prior()=x->prior();
|
||||
}
|
||||
|
||||
static void relink(
|
||||
sequenced_index_node_impl* position,sequenced_index_node_impl* x)
|
||||
static void relink(pointer position,pointer x)
|
||||
{
|
||||
unlink(x);
|
||||
x->prior()=position->prior();
|
||||
@@ -72,14 +75,12 @@ struct sequenced_index_node_impl
|
||||
x->prior()->next()=x->next()->prior()=x;
|
||||
}
|
||||
|
||||
static void relink(
|
||||
sequenced_index_node_impl* position,
|
||||
sequenced_index_node_impl* x,sequenced_index_node_impl* y)
|
||||
static void relink(pointer position,pointer x,pointer y)
|
||||
{
|
||||
/* position is assumed not to be in [x,y) */
|
||||
|
||||
if(x!=y){
|
||||
sequenced_index_node_impl* z=y->prior();
|
||||
pointer z=y->prior();
|
||||
x->prior()->next()=y;
|
||||
y->prior()=x->prior();
|
||||
x->prior()=position->prior();
|
||||
@@ -89,17 +90,17 @@ struct sequenced_index_node_impl
|
||||
}
|
||||
}
|
||||
|
||||
static void reverse(sequenced_index_node_impl* header)
|
||||
static void reverse(pointer header)
|
||||
{
|
||||
sequenced_index_node_impl* x=header;
|
||||
pointer x=header;
|
||||
do{
|
||||
sequenced_index_node_impl* y=x->next();
|
||||
pointer y=x->next();
|
||||
std::swap(x->prior(),x->next());
|
||||
x=y;
|
||||
}while(x!=header);
|
||||
}
|
||||
|
||||
static void swap(sequenced_index_node_impl* x,sequenced_index_node_impl* y)
|
||||
static void swap(pointer x,pointer y)
|
||||
{
|
||||
/* This swap function does not exchange the header nodes,
|
||||
* but rather their pointers. This is *not* used for implementing
|
||||
@@ -129,67 +130,88 @@ struct sequenced_index_node_impl
|
||||
}
|
||||
|
||||
private:
|
||||
sequenced_index_node_impl();
|
||||
|
||||
sequenced_index_node_impl* prior_;
|
||||
sequenced_index_node_impl* next_;
|
||||
pointer prior_;
|
||||
pointer next_;
|
||||
};
|
||||
|
||||
template<typename Super>
|
||||
struct sequenced_index_node_trampoline:sequenced_index_node_impl{};
|
||||
struct sequenced_index_node_trampoline:
|
||||
prevent_eti<
|
||||
Super,
|
||||
sequenced_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
typename Super::allocator_type,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type
|
||||
{
|
||||
typedef typename prevent_eti<
|
||||
Super,
|
||||
sequenced_index_node_impl<
|
||||
typename boost::detail::allocator::rebind_to<
|
||||
typename Super::allocator_type,
|
||||
char
|
||||
>::type
|
||||
>
|
||||
>::type impl_type;
|
||||
};
|
||||
|
||||
template<typename Super>
|
||||
struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
|
||||
{
|
||||
sequenced_index_node_impl*& prior(){return impl_type::prior();}
|
||||
sequenced_index_node_impl*const & prior()const{return impl_type::prior();}
|
||||
sequenced_index_node_impl*& next(){return impl_type::next();}
|
||||
sequenced_index_node_impl*const & next()const{return impl_type::next();}
|
||||
private:
|
||||
typedef sequenced_index_node_trampoline<Super> trampoline;
|
||||
|
||||
sequenced_index_node_impl* impl()
|
||||
{return static_cast<impl_type*>(this);}
|
||||
const sequenced_index_node_impl* impl()const
|
||||
{return static_cast<const impl_type*>(this);}
|
||||
public:
|
||||
typedef typename trampoline::impl_type impl_type;
|
||||
typedef typename trampoline::pointer impl_pointer;
|
||||
typedef typename trampoline::const_pointer const_impl_pointer;
|
||||
|
||||
static sequenced_index_node* from_impl(sequenced_index_node_impl *x)
|
||||
{return static_cast<sequenced_index_node*>(static_cast<impl_type*>(x));}
|
||||
static const sequenced_index_node* from_impl(
|
||||
const sequenced_index_node_impl* x)
|
||||
impl_pointer& prior(){return trampoline::prior();}
|
||||
impl_pointer prior()const{return trampoline::prior();}
|
||||
impl_pointer& next(){return trampoline::next();}
|
||||
impl_pointer next()const{return trampoline::next();}
|
||||
|
||||
impl_pointer impl()
|
||||
{
|
||||
return static_cast<const sequenced_index_node*>(
|
||||
static_cast<const impl_type*>(x));
|
||||
return static_cast<impl_pointer>(
|
||||
static_cast<impl_type*>(static_cast<trampoline*>(this)));
|
||||
}
|
||||
|
||||
/* interoperability with index_iterator */
|
||||
const_impl_pointer impl()const
|
||||
{
|
||||
return static_cast<const_impl_pointer>(
|
||||
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
|
||||
}
|
||||
|
||||
static sequenced_index_node* from_impl(impl_pointer x)
|
||||
{
|
||||
return static_cast<sequenced_index_node*>(
|
||||
static_cast<trampoline*>(&*x));
|
||||
}
|
||||
|
||||
static const sequenced_index_node* from_impl(const_impl_pointer x)
|
||||
{
|
||||
return static_cast<const sequenced_index_node*>(
|
||||
static_cast<const trampoline*>(&*x));
|
||||
}
|
||||
|
||||
/* interoperability with bidir_node_iterator */
|
||||
|
||||
static void increment(sequenced_index_node*& x)
|
||||
{
|
||||
sequenced_index_node_impl* xi=x->impl();
|
||||
impl_type::increment(xi);
|
||||
impl_pointer xi=x->impl();
|
||||
trampoline::increment(xi);
|
||||
x=from_impl(xi);
|
||||
}
|
||||
|
||||
static void decrement(sequenced_index_node*& x)
|
||||
{
|
||||
sequenced_index_node_impl* xi=x->impl();
|
||||
impl_type::decrement(xi);
|
||||
impl_pointer xi=x->impl();
|
||||
trampoline::decrement(xi);
|
||||
x=from_impl(xi);
|
||||
}
|
||||
|
||||
/* interoperability with index_proxy */
|
||||
|
||||
static sequenced_index_node* begin(sequenced_index_node* header)
|
||||
{
|
||||
return from_impl(impl_type::begin(header->impl()));
|
||||
}
|
||||
|
||||
static sequenced_index_node* end(sequenced_index_node* header)
|
||||
{
|
||||
return from_impl(impl_type::end(header->impl()));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef sequenced_index_node_trampoline<Super> impl_type;
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,10 +14,11 @@
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/aligned_storage.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/multi_index/detail/seq_index_node.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost{
|
||||
@@ -59,7 +60,7 @@ template <typename SequencedIndex,typename Compare>
|
||||
void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
|
||||
{
|
||||
typedef typename SequencedIndex::iterator iterator;
|
||||
if(x!=y){
|
||||
if(&x!=&y){
|
||||
iterator first0=x.begin(),last0=x.end();
|
||||
iterator first1=y.begin(),last1=y.end();
|
||||
while(first0!=last0&&first1!=last1){
|
||||
@@ -76,24 +77,40 @@ void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
|
||||
|
||||
template<typename Node,typename Compare>
|
||||
void sequenced_index_collate(
|
||||
sequenced_index_node_impl* x,sequenced_index_node_impl* y,Compare comp
|
||||
BOOST_DEDUCED_TYPENAME Node::impl_type* x,
|
||||
BOOST_DEDUCED_TYPENAME Node::impl_type* y,
|
||||
Compare comp
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
|
||||
{
|
||||
sequenced_index_node_impl* first0=x->next();
|
||||
sequenced_index_node_impl* last0=x;
|
||||
sequenced_index_node_impl* first1=y->next();
|
||||
sequenced_index_node_impl* last1=y;
|
||||
typedef typename Node::impl_type impl_type;
|
||||
typedef typename Node::impl_pointer impl_pointer;
|
||||
|
||||
impl_pointer first0=x->next();
|
||||
impl_pointer last0=x;
|
||||
impl_pointer first1=y->next();
|
||||
impl_pointer last1=y;
|
||||
while(first0!=last0&&first1!=last1){
|
||||
if(comp(Node::from_impl(first1)->value,Node::from_impl(first0)->value)){
|
||||
sequenced_index_node_impl* tmp=first1->next();
|
||||
sequenced_index_node_impl::relink(first0,first1);
|
||||
if(comp(
|
||||
Node::from_impl(first1)->value(),Node::from_impl(first0)->value())){
|
||||
impl_pointer tmp=first1->next();
|
||||
impl_type::relink(first0,first1);
|
||||
first1=tmp;
|
||||
}
|
||||
else first0=first0->next();
|
||||
}
|
||||
sequenced_index_node_impl::relink(last0,first1,last1);
|
||||
impl_type::relink(last0,first1,last1);
|
||||
}
|
||||
|
||||
/* Some versions of CGG require a bogus typename in counter_spc
|
||||
* inside sequenced_index_sort if the following is defined
|
||||
* also inside sequenced_index_sort.
|
||||
*/
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
std::size_t,
|
||||
sequenced_index_sort_max_fill=
|
||||
(std::size_t)std::numeric_limits<std::size_t>::digits+1);
|
||||
|
||||
template<typename Node,typename Compare>
|
||||
void sequenced_index_sort(Node* header,Compare comp)
|
||||
{
|
||||
@@ -110,49 +127,64 @@ void sequenced_index_sort(Node* header,Compare comp)
|
||||
if(header->next()==header->impl()||
|
||||
header->next()->next()==header->impl())return;
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
std::size_t,
|
||||
max_fill=(std::size_t)std::numeric_limits<std::size_t>::digits+1);
|
||||
typedef typename Node::impl_type impl_type;
|
||||
typedef typename Node::impl_pointer impl_pointer;
|
||||
|
||||
aligned_storage<
|
||||
sizeof(sequenced_index_node_impl)> carry_spc;
|
||||
sequenced_index_node_impl& carry=
|
||||
*static_cast<sequenced_index_node_impl*>(carry_spc.address());
|
||||
aligned_storage<
|
||||
typedef typename aligned_storage<
|
||||
sizeof(impl_type),
|
||||
alignment_of<impl_type>::value
|
||||
>::type carry_spc_type;
|
||||
carry_spc_type carry_spc;
|
||||
impl_type& carry=
|
||||
*static_cast<impl_type*>(static_cast<void*>(&carry_spc));
|
||||
typedef typename aligned_storage<
|
||||
sizeof(
|
||||
sequenced_index_node_impl[max_fill])> counter_spc;
|
||||
sequenced_index_node_impl* counter=
|
||||
static_cast<sequenced_index_node_impl*>(counter_spc.address());
|
||||
std::size_t fill=0;
|
||||
impl_type
|
||||
[sequenced_index_sort_max_fill]),
|
||||
alignment_of<
|
||||
impl_type
|
||||
[sequenced_index_sort_max_fill]
|
||||
>::value
|
||||
>::type counter_spc_type;
|
||||
counter_spc_type counter_spc;
|
||||
impl_type* counter=
|
||||
static_cast<impl_type*>(static_cast<void*>(&counter_spc));
|
||||
std::size_t fill=0;
|
||||
|
||||
carry.prior()=carry.next()=&carry;
|
||||
counter[0].prior()=counter[0].next()=&counter[0];
|
||||
carry.prior()=carry.next()=static_cast<impl_pointer>(&carry);
|
||||
counter[0].prior()=counter[0].next()=static_cast<impl_pointer>(&counter[0]);
|
||||
|
||||
BOOST_TRY{
|
||||
while(header->next()!=header->impl()){
|
||||
sequenced_index_node_impl::relink(carry.next(),header->next());
|
||||
impl_type::relink(carry.next(),header->next());
|
||||
std::size_t i=0;
|
||||
while(i<fill&&counter[i].next()!=&counter[i]){
|
||||
while(i<fill&&counter[i].next()!=static_cast<impl_pointer>(&counter[i])){
|
||||
sequenced_index_collate<Node>(&carry,&counter[i++],comp);
|
||||
}
|
||||
sequenced_index_node_impl::swap(&carry,&counter[i]);
|
||||
impl_type::swap(
|
||||
static_cast<impl_pointer>(&carry),
|
||||
static_cast<impl_pointer>(&counter[i]));
|
||||
if(i==fill){
|
||||
++fill;
|
||||
counter[fill].prior()=counter[fill].next()=&counter[fill];
|
||||
counter[fill].prior()=counter[fill].next()=
|
||||
static_cast<impl_pointer>(&counter[fill]);
|
||||
}
|
||||
}
|
||||
|
||||
for(std::size_t i=1;i<fill;++i){
|
||||
sequenced_index_collate<Node>(&counter[i],&counter[i-1],comp);
|
||||
}
|
||||
sequenced_index_node_impl::swap(header->impl(),&counter[fill-1]);
|
||||
impl_type::swap(
|
||||
header->impl(),static_cast<impl_pointer>(&counter[fill-1]));
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
sequenced_index_node_impl::relink(header->impl(),carry.next(),&carry);
|
||||
impl_type::relink(
|
||||
header->impl(),carry.next(),static_cast<impl_pointer>(&carry));
|
||||
for(std::size_t i=0;i<=fill;++i){
|
||||
sequenced_index_node_impl::relink(
|
||||
header->impl(),counter[i].next(),&counter[i]);
|
||||
impl_type::relink(
|
||||
header->impl(),counter[i].next(),
|
||||
static_cast<impl_pointer>(&counter[i]));
|
||||
}
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/* Copyright 2003-2010 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_SERIALIZATION_VERSION_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_SERIALIZATION_VERSION_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* Helper class for storing and retrieving a given type serialization class
|
||||
* version while avoiding saving the number multiple times in the same
|
||||
* archive.
|
||||
* Behavior undefined if template partial specialization is not supported.
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
struct serialization_version
|
||||
{
|
||||
serialization_version():
|
||||
value(boost::serialization::version<serialization_version>::value){}
|
||||
|
||||
serialization_version& operator=(unsigned int x){value=x;return *this;};
|
||||
|
||||
operator unsigned int()const{return value;}
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive&,const unsigned int)const{}
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive&,const unsigned int version)
|
||||
{
|
||||
this->value=version;
|
||||
}
|
||||
|
||||
unsigned int value;
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
namespace serialization {
|
||||
template<typename T>
|
||||
struct version<boost::multi_index::detail::serialization_version<T> >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(int,value=version<T>::value);
|
||||
};
|
||||
} /* namespace serialization */
|
||||
#endif
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_DETAIL_UINTPTR_TYPE_HPP
|
||||
#define BOOST_MULTI_INDEX_DETAIL_UINTPTR_TYPE_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* has_uintptr_type is an MPL integral constant determining whether
|
||||
* there exists an unsigned integral type with the same size as
|
||||
* void *.
|
||||
* uintptr_type is such a type if has_uintptr is true, or unsigned int
|
||||
* otherwise.
|
||||
* Note that uintptr_type is more restrictive than C99 uintptr_t,
|
||||
* where an integral type with size greater than that of void *
|
||||
* would be conformant.
|
||||
*/
|
||||
|
||||
template<int N>struct uintptr_candidates;
|
||||
template<>struct uintptr_candidates<-1>{typedef unsigned int type;};
|
||||
template<>struct uintptr_candidates<0> {typedef unsigned int type;};
|
||||
template<>struct uintptr_candidates<1> {typedef unsigned short type;};
|
||||
template<>struct uintptr_candidates<2> {typedef unsigned long type;};
|
||||
|
||||
#if defined(BOOST_HAS_LONG_LONG)
|
||||
template<>struct uintptr_candidates<3> {typedef boost::ulong_long_type type;};
|
||||
#else
|
||||
template<>struct uintptr_candidates<3> {typedef unsigned int type;};
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_MS_INT64)
|
||||
template<>struct uintptr_candidates<4> {typedef unsigned __int64 type;};
|
||||
#else
|
||||
template<>struct uintptr_candidates<4> {typedef unsigned int type;};
|
||||
#endif
|
||||
|
||||
struct uintptr_aux
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(int,index=
|
||||
sizeof(void*)==sizeof(uintptr_candidates<0>::type)?0:
|
||||
sizeof(void*)==sizeof(uintptr_candidates<1>::type)?1:
|
||||
sizeof(void*)==sizeof(uintptr_candidates<2>::type)?2:
|
||||
sizeof(void*)==sizeof(uintptr_candidates<3>::type)?3:
|
||||
sizeof(void*)==sizeof(uintptr_candidates<4>::type)?4:-1);
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool,has_uintptr_type=(index>=0));
|
||||
|
||||
typedef uintptr_candidates<index>::type type;
|
||||
};
|
||||
|
||||
typedef mpl::bool_<uintptr_aux::has_uintptr_type> has_uintptr_type;
|
||||
typedef uintptr_aux::type uintptr_type;
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -13,24 +13,68 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
/* dummy type and variable for use in ordered_index::range() */
|
||||
|
||||
namespace detail{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
/* The default branch actually works for MSVC 6.0, but seems like
|
||||
* this implementation of unbounded improves the performance of ordered
|
||||
* indices! This behavior is hard to explain and probably a test artifact,
|
||||
* but it does not hurt to have the workaround anyway.
|
||||
*/
|
||||
|
||||
struct unbounded_type{};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
namespace detail{struct unbounded_type{};}
|
||||
|
||||
namespace{
|
||||
|
||||
detail::unbounded_type unbounded_obj=detail::unbounded_type();
|
||||
detail::unbounded_type& unbounded=unbounded_obj;
|
||||
static detail::unbounded_type unbounded_obj=detail::unbounded_type();
|
||||
static detail::unbounded_type& unbounded=unbounded_obj;
|
||||
|
||||
} /* unnamed */
|
||||
#else
|
||||
/* ODR-abiding technique shown at the example attached to
|
||||
* http://lists.boost.org/Archives/boost/2006/07/108355.php
|
||||
*/
|
||||
|
||||
namespace detail{class unbounded_helper;}
|
||||
|
||||
detail::unbounded_helper unbounded(detail::unbounded_helper);
|
||||
|
||||
namespace detail{
|
||||
|
||||
class unbounded_helper
|
||||
{
|
||||
unbounded_helper(){}
|
||||
unbounded_helper(const unbounded_helper&){}
|
||||
friend unbounded_helper multi_index::unbounded(unbounded_helper);
|
||||
};
|
||||
|
||||
typedef unbounded_helper (*unbounded_type)(unbounded_helper);
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
inline detail::unbounded_helper unbounded(detail::unbounded_helper)
|
||||
{
|
||||
return detail::unbounded_helper();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* tags used in the implementation of range */
|
||||
|
||||
namespace detail{
|
||||
|
||||
struct none_unbounded_tag{};
|
||||
struct lower_unbounded_tag{};
|
||||
struct upper_unbounded_tag{};
|
||||
struct both_unbounded_tag{};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -26,14 +26,15 @@ namespace detail{
|
||||
template<typename Value,typename KeyFromValue,typename Compare>
|
||||
struct value_comparison:std::binary_function<Value,Value,bool>
|
||||
{
|
||||
value_comparison(KeyFromValue key_=KeyFromValue(),Compare comp_=Compare()):
|
||||
value_comparison(
|
||||
const KeyFromValue& key_=KeyFromValue(),const Compare& comp_=Compare()):
|
||||
key(key_),comp(comp_)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(
|
||||
typename call_traits<Value>::param_type x,
|
||||
typename call_traits<Value>::param_type y)
|
||||
typename call_traits<Value>::param_type y)const
|
||||
{
|
||||
return comp(key(x),key(y));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MULTI_INDEX_GLOBAL_FUN_HPP
|
||||
#define BOOST_MULTI_INDEX_GLOBAL_FUN_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
template<class T> class reference_wrapper; /* fwd decl. */
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
/* global_fun is a read-only key extractor from Value based on a given global
|
||||
* (or static member) function with signature:
|
||||
*
|
||||
* Type f([const] Value [&]);
|
||||
*
|
||||
* Additionally, global_fun and const_global_fun are overloaded to support
|
||||
* referece_wrappers of Value and "chained pointers" to Value's. By chained
|
||||
* pointer to T we mean a type P such that, given a p of Type P
|
||||
* *...n...*x is convertible to T&, for some n>=1.
|
||||
* Examples of chained pointers are raw and smart pointers, iterators and
|
||||
* arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
|
||||
*/
|
||||
|
||||
/* NB. Some overloads of operator() have an extra dummy parameter int=0.
|
||||
* This disambiguator serves several purposes:
|
||||
* - Without it, MSVC++ 6.0 incorrectly regards some overloads as
|
||||
* specializations of a previous member function template.
|
||||
* - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
|
||||
* as if they have the same signature.
|
||||
* - If remove_const is broken due to lack of PTS, int=0 avoids the
|
||||
* declaration of memfuns with identical signature.
|
||||
*/
|
||||
|
||||
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
|
||||
struct const_ref_global_fun_base
|
||||
{
|
||||
typedef typename remove_reference<Type>::type result_type;
|
||||
|
||||
template<typename ChainedPtr>
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
typename disable_if<
|
||||
is_convertible<const ChainedPtr&,Value>,Type>::type
|
||||
#else
|
||||
Type
|
||||
#endif
|
||||
|
||||
operator()(const ChainedPtr& x)const
|
||||
{
|
||||
return operator()(*x);
|
||||
}
|
||||
|
||||
Type operator()(Value x)const
|
||||
{
|
||||
return PtrToFunction(x);
|
||||
}
|
||||
|
||||
Type operator()(
|
||||
const reference_wrapper<
|
||||
typename remove_reference<Value>::type>& x)const
|
||||
{
|
||||
return operator()(x.get());
|
||||
}
|
||||
|
||||
Type operator()(
|
||||
const reference_wrapper<
|
||||
typename remove_const<
|
||||
typename remove_reference<Value>::type>::type>& x,int=0)const
|
||||
{
|
||||
return operator()(x.get());
|
||||
}
|
||||
};
|
||||
|
||||
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
|
||||
struct non_const_ref_global_fun_base
|
||||
{
|
||||
typedef typename remove_reference<Type>::type result_type;
|
||||
|
||||
template<typename ChainedPtr>
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
typename disable_if<
|
||||
is_convertible<ChainedPtr&,Value>,Type>::type
|
||||
#else
|
||||
Type
|
||||
#endif
|
||||
|
||||
operator()(const ChainedPtr& x)const
|
||||
{
|
||||
return operator()(*x);
|
||||
}
|
||||
|
||||
Type operator()(Value x)const
|
||||
{
|
||||
return PtrToFunction(x);
|
||||
}
|
||||
|
||||
Type operator()(
|
||||
const reference_wrapper<
|
||||
typename remove_reference<Value>::type>& x)const
|
||||
{
|
||||
return operator()(x.get());
|
||||
}
|
||||
};
|
||||
|
||||
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
|
||||
struct non_ref_global_fun_base
|
||||
{
|
||||
typedef typename remove_reference<Type>::type result_type;
|
||||
|
||||
template<typename ChainedPtr>
|
||||
|
||||
#if !defined(BOOST_NO_SFINAE)
|
||||
typename disable_if<
|
||||
is_convertible<const ChainedPtr&,const Value&>,Type>::type
|
||||
#else
|
||||
Type
|
||||
#endif
|
||||
|
||||
operator()(const ChainedPtr& x)const
|
||||
{
|
||||
return operator()(*x);
|
||||
}
|
||||
|
||||
Type operator()(const Value& x)const
|
||||
{
|
||||
return PtrToFunction(x);
|
||||
}
|
||||
|
||||
Type operator()(const reference_wrapper<const Value>& x)const
|
||||
{
|
||||
return operator()(x.get());
|
||||
}
|
||||
|
||||
Type operator()(
|
||||
const reference_wrapper<
|
||||
typename remove_const<Value>::type>& x,int=0)const
|
||||
{
|
||||
return operator()(x.get());
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
|
||||
struct global_fun:
|
||||
mpl::if_c<
|
||||
is_reference<Value>::value,
|
||||
typename mpl::if_c<
|
||||
is_const<typename remove_reference<Value>::type>::value,
|
||||
detail::const_ref_global_fun_base<Value,Type,PtrToFunction>,
|
||||
detail::non_const_ref_global_fun_base<Value,Type,PtrToFunction>
|
||||
>::type,
|
||||
detail::non_ref_global_fun_base<Value,Type,PtrToFunction>
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
} /* namespace multi_index */
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2005 Joaquín M López Muñoz.
|
||||
/* Copyright 2003-2011 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -19,13 +19,17 @@
|
||||
#include <boost/detail/allocator_utilities.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/foreach_fwd.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/push_front.hpp>
|
||||
#include <boost/multi_index/detail/access_specifier.hpp>
|
||||
#include <boost/multi_index/detail/auto_space.hpp>
|
||||
#include <boost/multi_index/detail/bucket_array.hpp>
|
||||
#include <boost/multi_index/detail/hash_index_iterator.hpp>
|
||||
#include <boost/multi_index/detail/index_node_base.hpp>
|
||||
#include <boost/multi_index/detail/modify_key_adaptor.hpp>
|
||||
#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
|
||||
#include <boost/multi_index/detail/safe_mode.hpp>
|
||||
#include <boost/multi_index/detail/scope_guard.hpp>
|
||||
#include <boost/multi_index/hashed_index_fwd.hpp>
|
||||
@@ -67,23 +71,20 @@ template<
|
||||
typename KeyFromValue,typename Hash,typename Pred,
|
||||
typename SuperMeta,typename TagList,typename Category
|
||||
>
|
||||
class hashed_index:
|
||||
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
class hashed_index:
|
||||
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type,
|
||||
public hashed_index_proxy<
|
||||
hashed_index_node<SuperMeta::type::node_type>,
|
||||
bucket_array<SuperMeta::type::final_allocator_type> >
|
||||
,public safe_ctr_proxy_impl<
|
||||
hashed_index_iterator<
|
||||
hashed_index_node<typename SuperMeta::type::node_type>,
|
||||
bucket_array<typename SuperMeta::type::final_allocator_type> >,
|
||||
hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
|
||||
#else
|
||||
class hashed_index:
|
||||
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type,
|
||||
public safe_container<
|
||||
,public safe_mode::safe_container<
|
||||
hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
|
||||
#endif
|
||||
#else
|
||||
class hashed_index:
|
||||
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
|
||||
#endif
|
||||
|
||||
{
|
||||
@@ -102,6 +103,10 @@ class hashed_index:
|
||||
protected:
|
||||
typedef hashed_index_node<
|
||||
typename super::node_type> node_type;
|
||||
|
||||
private:
|
||||
typedef typename node_type::impl_type node_impl_type;
|
||||
typedef typename node_impl_type::pointer node_impl_pointer;
|
||||
typedef bucket_array<
|
||||
typename super::final_allocator_type> bucket_array_type;
|
||||
|
||||
@@ -125,23 +130,25 @@ public:
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
typedef hashed_index_iterator<
|
||||
node_type,bucket_array_type> iterator;
|
||||
typedef hashed_index_iterator<
|
||||
node_type,bucket_array_type> const_iterator;
|
||||
typedef safe_mode::safe_iterator<
|
||||
hashed_index_iterator<
|
||||
node_type,bucket_array_type>,
|
||||
safe_ctr_proxy<
|
||||
hashed_index_iterator<
|
||||
node_type,bucket_array_type> > > iterator;
|
||||
#else
|
||||
typedef hashed_index_iterator<
|
||||
node_type,bucket_array_type,hashed_index> iterator;
|
||||
typedef hashed_index_iterator<
|
||||
node_type,bucket_array_type,hashed_index> const_iterator;
|
||||
typedef safe_mode::safe_iterator<
|
||||
hashed_index_iterator<
|
||||
node_type,bucket_array_type>,
|
||||
hashed_index> iterator;
|
||||
#endif
|
||||
#else
|
||||
typedef hashed_index_iterator<
|
||||
node_type,bucket_array_type> iterator;
|
||||
typedef hashed_index_iterator<
|
||||
node_type,bucket_array_type> const_iterator;
|
||||
#endif
|
||||
|
||||
typedef iterator const_iterator;
|
||||
|
||||
typedef iterator local_iterator;
|
||||
typedef const_iterator const_local_iterator;
|
||||
typedef TagList tag_list;
|
||||
@@ -170,10 +177,13 @@ protected:
|
||||
private:
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
typedef hashed_index_proxy<
|
||||
node_type,bucket_array_type> safe_super;
|
||||
typedef safe_ctr_proxy_impl<
|
||||
hashed_index_iterator<
|
||||
node_type,bucket_array_type>,
|
||||
hashed_index> safe_super;
|
||||
#else
|
||||
typedef safe_container<hashed_index> safe_super;
|
||||
typedef safe_mode::safe_container<
|
||||
hashed_index> safe_super;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -223,6 +233,19 @@ public:
|
||||
iterator end(){return make_iterator(header());}
|
||||
const_iterator end()const{return make_iterator(header());}
|
||||
|
||||
const_iterator cbegin()const{return begin();}
|
||||
const_iterator cend()const{return end();}
|
||||
|
||||
iterator iterator_to(const value_type& x)
|
||||
{
|
||||
return make_iterator(node_from_value<node_type>(&x));
|
||||
}
|
||||
|
||||
const_iterator iterator_to(const value_type& x)const
|
||||
{
|
||||
return make_iterator(node_from_value<node_type>(&x));
|
||||
}
|
||||
|
||||
/* modifiers */
|
||||
|
||||
std::pair<iterator,bool> insert(value_param_type x)
|
||||
@@ -250,42 +273,45 @@ public:
|
||||
for(;first!=last;++first)hint=insert(hint,*first);
|
||||
}
|
||||
|
||||
void erase(iterator position)
|
||||
iterator erase(iterator position)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
|
||||
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
|
||||
* this is not added. Left it for all compilers as it does no
|
||||
* harm.
|
||||
*/
|
||||
|
||||
position.detach();
|
||||
#endif
|
||||
|
||||
this->final_erase_(static_cast<final_node_type*>(position.get_node()));
|
||||
this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
|
||||
return position;
|
||||
}
|
||||
|
||||
size_type erase(key_param_type x)
|
||||
|
||||
size_type erase(key_param_type k)
|
||||
{
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
|
||||
size_type s=0;
|
||||
iterator it=find(x); /* caveat: relies on find() returning */
|
||||
if(it!=end()){ /* the first element */
|
||||
do{
|
||||
erase(it++);
|
||||
++s;
|
||||
}while(it!=end()&&eq(x,key(*it)));
|
||||
size_type s=0;
|
||||
std::size_t buc=buckets.position(hash(k));
|
||||
node_impl_pointer x=buckets.at(buc);
|
||||
node_impl_pointer y=x->next();
|
||||
while(y!=x){
|
||||
if(eq(k,key(node_type::from_impl(y)->value()))){
|
||||
bool b;
|
||||
do{
|
||||
node_impl_pointer z=y->next();
|
||||
b=z!=x&&eq(
|
||||
key(node_type::from_impl(y)->value()),
|
||||
key(node_type::from_impl(z)->value()));
|
||||
this->final_erase_(
|
||||
static_cast<final_node_type*>(node_type::from_impl(y)));
|
||||
y=z;
|
||||
++s;
|
||||
}while(b);
|
||||
break;
|
||||
}
|
||||
y=y->next();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void erase(iterator first,iterator last)
|
||||
iterator erase(iterator first,iterator last)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
|
||||
@@ -294,8 +320,9 @@ public:
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
while(first!=last){
|
||||
erase(first++);
|
||||
first=erase(first);
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
bool replace(iterator position,value_param_type x)
|
||||
@@ -329,6 +356,27 @@ public:
|
||||
mod,static_cast<final_node_type*>(position.get_node()));
|
||||
}
|
||||
|
||||
template<typename Modifier,typename Rollback>
|
||||
bool modify(iterator position,Modifier mod,Rollback back)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
|
||||
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
|
||||
* this is not added. Left it for all compilers as it does no
|
||||
* harm.
|
||||
*/
|
||||
|
||||
position.detach();
|
||||
#endif
|
||||
|
||||
return this->final_modify_(
|
||||
mod,back,static_cast<final_node_type*>(position.get_node()));
|
||||
}
|
||||
|
||||
template<typename Modifier>
|
||||
bool modify_key(iterator position,Modifier mod)
|
||||
{
|
||||
@@ -340,6 +388,19 @@ public:
|
||||
position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
|
||||
}
|
||||
|
||||
template<typename Modifier,typename Rollback>
|
||||
bool modify_key(iterator position,Modifier mod,Rollback back)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
|
||||
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
return modify(
|
||||
position,
|
||||
modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
|
||||
modify_key_adaptor<Rollback,value_type,KeyFromValue>(back,key));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
@@ -377,11 +438,11 @@ public:
|
||||
const CompatibleKey& k,
|
||||
const CompatibleHash& hash,const CompatiblePred& eq)const
|
||||
{
|
||||
std::size_t buc=buckets.position(hash(k));
|
||||
hashed_index_node_impl* x=buckets.at(buc);
|
||||
hashed_index_node_impl* y=x->next();
|
||||
std::size_t buc=buckets.position(hash(k));
|
||||
node_impl_pointer x=buckets.at(buc);
|
||||
node_impl_pointer y=x->next();
|
||||
while(y!=x){
|
||||
if(eq(k,key(node_type::from_impl(y)->value))){
|
||||
if(eq(k,key(node_type::from_impl(y)->value()))){
|
||||
return make_iterator(node_type::from_impl(y));
|
||||
}
|
||||
y=y->next();
|
||||
@@ -402,16 +463,16 @@ public:
|
||||
const CompatibleKey& k,
|
||||
const CompatibleHash& hash,const CompatiblePred& eq)const
|
||||
{
|
||||
size_type res=0;
|
||||
std::size_t buc=buckets.position(hash(k));
|
||||
hashed_index_node_impl* x=buckets.at(buc);
|
||||
hashed_index_node_impl* y=x->next();
|
||||
size_type res=0;
|
||||
std::size_t buc=buckets.position(hash(k));
|
||||
node_impl_pointer x=buckets.at(buc);
|
||||
node_impl_pointer y=x->next();
|
||||
while(y!=x){
|
||||
if(eq(k,key(node_type::from_impl(y)->value))){
|
||||
if(eq(k,key(node_type::from_impl(y)->value()))){
|
||||
do{
|
||||
++res;
|
||||
y=y->next();
|
||||
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value)));
|
||||
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
|
||||
break;
|
||||
}
|
||||
y=y->next();
|
||||
@@ -432,15 +493,15 @@ public:
|
||||
const CompatibleKey& k,
|
||||
const CompatibleHash& hash,const CompatiblePred& eq)const
|
||||
{
|
||||
std::size_t buc=buckets.position(hash(k));
|
||||
hashed_index_node_impl* x=buckets.at(buc);
|
||||
hashed_index_node_impl* y=x->next();
|
||||
std::size_t buc=buckets.position(hash(k));
|
||||
node_impl_pointer x=buckets.at(buc);
|
||||
node_impl_pointer y=x->next();
|
||||
while(y!=x){
|
||||
if(eq(k,key(node_type::from_impl(y)->value))){
|
||||
hashed_index_node_impl* y0=y;
|
||||
if(eq(k,key(node_type::from_impl(y)->value()))){
|
||||
node_impl_pointer y0=y;
|
||||
do{
|
||||
y=y->next();
|
||||
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value)));
|
||||
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
|
||||
if(y==x){
|
||||
do{
|
||||
++y;
|
||||
@@ -463,9 +524,9 @@ public:
|
||||
|
||||
size_type bucket_size(size_type n)const
|
||||
{
|
||||
size_type res=0;
|
||||
hashed_index_node_impl* x=buckets.at(n);
|
||||
hashed_index_node_impl* y=x->next();
|
||||
size_type res=0;
|
||||
node_impl_pointer x=buckets.at(n);
|
||||
node_impl_pointer y=x->next();
|
||||
while(y!=x){
|
||||
++res;
|
||||
y=y->next();
|
||||
@@ -485,8 +546,8 @@ public:
|
||||
|
||||
const_local_iterator begin(size_type n)const
|
||||
{
|
||||
hashed_index_node_impl* x=buckets.at(n);
|
||||
hashed_index_node_impl* y=x->next();
|
||||
node_impl_pointer x=buckets.at(n);
|
||||
node_impl_pointer y=x->next();
|
||||
if(y==x)return end();
|
||||
return make_iterator(node_type::from_impl(y));
|
||||
}
|
||||
@@ -498,7 +559,7 @@ public:
|
||||
|
||||
const_local_iterator end(size_type n)const
|
||||
{
|
||||
hashed_index_node_impl* x=buckets.at(n);
|
||||
node_impl_pointer x=buckets.at(n);
|
||||
if(x==x->next())return end();
|
||||
do{
|
||||
++x;
|
||||
@@ -506,6 +567,19 @@ public:
|
||||
return make_iterator(node_type::from_impl(x->next()));
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n)const{return begin(n);}
|
||||
const_local_iterator cend(size_type n)const{return end(n);}
|
||||
|
||||
local_iterator local_iterator_to(const value_type& x)
|
||||
{
|
||||
return make_iterator(node_from_value<node_type>(&x));
|
||||
}
|
||||
|
||||
const_local_iterator local_iterator_to(const value_type& x)const
|
||||
{
|
||||
return make_iterator(node_from_value<node_type>(&x));
|
||||
}
|
||||
|
||||
/* hash policy */
|
||||
|
||||
float load_factor()const{return static_cast<float>(size())/bucket_count();}
|
||||
@@ -529,17 +603,11 @@ public:
|
||||
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
hashed_index(const ctor_args_list& args_list,const allocator_type& al):
|
||||
super(args_list.get_tail(),al),
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)&&\
|
||||
BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
safe_super(final_header(),buckets),
|
||||
#endif
|
||||
|
||||
key(tuples::get<1>(args_list.get_head())),
|
||||
hash(tuples::get<2>(args_list.get_head())),
|
||||
eq(tuples::get<3>(args_list.get_head())),
|
||||
buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
|
||||
mlf(1.0),
|
||||
mlf(1.0f),
|
||||
first_bucket(buckets.size())
|
||||
{
|
||||
calculate_max_load();
|
||||
@@ -549,9 +617,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
|
||||
super(x),
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)&&\
|
||||
BOOST_WORKAROUND(BOOST_MSVC,<1300)
|
||||
safe_super(final_header(),buckets),
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
safe_super(),
|
||||
#endif
|
||||
|
||||
key(x.key),
|
||||
@@ -575,25 +642,25 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
iterator make_iterator(node_type* node)
|
||||
{
|
||||
return iterator(node,buckets,this);
|
||||
return iterator(node,&buckets,this);
|
||||
}
|
||||
|
||||
const_iterator make_iterator(node_type* node)const
|
||||
{
|
||||
return const_iterator(
|
||||
node,
|
||||
const_cast<bucket_array_type&>(buckets),
|
||||
&const_cast<bucket_array_type&>(buckets),
|
||||
const_cast<hashed_index*>(this));
|
||||
}
|
||||
#else
|
||||
iterator make_iterator(node_type* node)
|
||||
{
|
||||
return iterator(node,buckets);
|
||||
return iterator(node,&buckets);
|
||||
}
|
||||
|
||||
const_iterator make_iterator(node_type* node)const
|
||||
{
|
||||
return const_iterator(node,const_cast<bucket_array_type&>(buckets));
|
||||
return const_iterator(node,&const_cast<bucket_array_type&>(buckets));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -601,13 +668,13 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
|
||||
const copy_map_type& map)
|
||||
{
|
||||
for(hashed_index_node_impl* begin_org=x.buckets.begin(),
|
||||
* begin_cpy=buckets.begin(),
|
||||
* end_org=x.buckets.end();
|
||||
for(node_impl_pointer begin_org=x.buckets.begin(),
|
||||
begin_cpy=buckets.begin(),
|
||||
end_org=x.buckets.end();
|
||||
begin_org!=end_org;++begin_org,++begin_cpy){
|
||||
|
||||
hashed_index_node_impl* next_org=begin_org->next();
|
||||
hashed_index_node_impl* cpy=begin_cpy;
|
||||
node_impl_pointer next_org=begin_org->next();
|
||||
node_impl_pointer cpy=begin_cpy;
|
||||
while(next_org!=begin_org){
|
||||
cpy->next()=
|
||||
static_cast<node_type*>(
|
||||
@@ -627,8 +694,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
{
|
||||
reserve(size()+1);
|
||||
|
||||
std::size_t buc=find_bucket(v);
|
||||
hashed_index_node_impl* pos=buckets.at(buc);
|
||||
std::size_t buc=find_bucket(v);
|
||||
node_impl_pointer pos=buckets.at(buc);
|
||||
if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
|
||||
|
||||
node_type* res=static_cast<node_type*>(super::insert_(v,x));
|
||||
@@ -643,8 +710,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
{
|
||||
reserve(size()+1);
|
||||
|
||||
std::size_t buc=find_bucket(v);
|
||||
hashed_index_node_impl* pos=buckets.at(buc);
|
||||
std::size_t buc=find_bucket(v);
|
||||
node_impl_pointer pos=buckets.at(buc);
|
||||
if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
|
||||
|
||||
node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
|
||||
@@ -668,11 +735,11 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
|
||||
void delete_all_nodes_()
|
||||
{
|
||||
for(hashed_index_node_impl* x=buckets.begin(),*x_end=buckets.end();
|
||||
for(node_impl_pointer x=buckets.begin(),x_end=buckets.end();
|
||||
x!=x_end;++x){
|
||||
hashed_index_node_impl* y=x->next();
|
||||
node_impl_pointer y=x->next();
|
||||
while(y!=x){
|
||||
hashed_index_node_impl* z=y->next();
|
||||
node_impl_pointer z=y->next();
|
||||
this->final_delete_node_(
|
||||
static_cast<final_node_type*>(node_type::from_impl(y)));
|
||||
y=z;
|
||||
@@ -687,7 +754,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
first_bucket=buckets.size();
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
safe_super::detach_all_iterators();
|
||||
safe_super::detach_dereferenceable_iterators();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -711,16 +778,16 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
|
||||
bool replace_(value_param_type v,node_type* x)
|
||||
{
|
||||
if(eq(key(v),key(x->value))){
|
||||
if(eq(key(v),key(x->value()))){
|
||||
return super::replace_(v,x);
|
||||
}
|
||||
|
||||
hashed_index_node_impl* y=prev(x);
|
||||
node_impl_pointer y=prev(x);
|
||||
unlink_next(y);
|
||||
|
||||
BOOST_TRY{
|
||||
std::size_t buc=find_bucket(v);
|
||||
hashed_index_node_impl* pos=buckets.at(buc);
|
||||
std::size_t buc=find_bucket(v);
|
||||
node_impl_pointer pos=buckets.at(buc);
|
||||
if(link_point(v,pos,Category())&&super::replace_(v,x)){
|
||||
link(x,pos);
|
||||
if(first_bucket>buc){
|
||||
@@ -743,28 +810,65 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
|
||||
bool modify_(node_type* x)
|
||||
{
|
||||
unlink(x);
|
||||
std::size_t buc;
|
||||
bool b;
|
||||
BOOST_TRY{
|
||||
buc=find_bucket(x->value());
|
||||
b=in_place(x->impl(),key(x->value()),buc,Category());
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
erase_(x);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
if(!b){
|
||||
unlink(x);
|
||||
BOOST_TRY{
|
||||
node_impl_pointer pos=buckets.at(buc);
|
||||
if(!link_point(x->value(),pos,Category())){
|
||||
first_bucket=buckets.first_nonempty(first_bucket);
|
||||
super::erase_(x);
|
||||
|
||||
std::size_t buc;
|
||||
hashed_index_node_impl* pos;
|
||||
BOOST_TRY
|
||||
{
|
||||
buc=find_bucket(x->value);
|
||||
pos=buckets.at(buc);
|
||||
if(!link_point(x->value,pos,Category())){
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
detach_iterators(x);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
link(x,pos);
|
||||
if(first_bucket>buc){
|
||||
first_bucket=buc;
|
||||
}
|
||||
else if(first_bucket<buc){
|
||||
first_bucket=buckets.first_nonempty(first_bucket);
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
first_bucket=buckets.first_nonempty(first_bucket);
|
||||
super::erase_(x);
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
detach_iterators(x);
|
||||
#endif
|
||||
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
BOOST_TRY{
|
||||
if(!super::modify_(x)){
|
||||
unlink(x);
|
||||
first_bucket=buckets.first_nonempty(first_bucket);
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
detach_iterators(x);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
else return true;
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
unlink(x);
|
||||
first_bucket=buckets.first_nonempty(first_bucket);
|
||||
super::erase_(x);
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
detach_iterators(x);
|
||||
@@ -773,9 +877,21 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
bool modify_rollback_(node_type* x)
|
||||
{
|
||||
std::size_t buc=find_bucket(x->value());
|
||||
if(in_place(x->impl(),key(x->value()),buc,Category())){
|
||||
return super::modify_rollback_(x);
|
||||
}
|
||||
|
||||
node_impl_pointer y=prev(x);
|
||||
unlink_next(y);
|
||||
|
||||
BOOST_TRY{
|
||||
if(super::modify_(x)){
|
||||
node_impl_pointer pos=buckets.at(buc);
|
||||
if(link_point(x->value(),pos,Category())&&super::modify_rollback_(x)){
|
||||
link(x,pos);
|
||||
if(first_bucket>buc){
|
||||
first_bucket=buc;
|
||||
@@ -785,21 +901,11 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
first_bucket=buckets.first_nonempty(first_bucket);
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
detach_iterators(x);
|
||||
#endif
|
||||
link(x,y);
|
||||
return false;
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
first_bucket=buckets.first_nonempty(first_bucket);
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
detach_iterators(x);
|
||||
#endif
|
||||
|
||||
link(x,y);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
@@ -871,11 +977,11 @@ private:
|
||||
}
|
||||
|
||||
bool link_point(
|
||||
value_param_type v,hashed_index_node_impl*& pos,hashed_unique_tag)
|
||||
value_param_type v,node_impl_pointer& pos,hashed_unique_tag)
|
||||
{
|
||||
hashed_index_node_impl* x=pos->next();
|
||||
node_impl_pointer x=pos->next();
|
||||
while(x!=pos){
|
||||
if(eq(key(v),key(node_type::from_impl(x)->value))){
|
||||
if(eq(key(v),key(node_type::from_impl(x)->value()))){
|
||||
pos=x;
|
||||
return false;
|
||||
}
|
||||
@@ -885,12 +991,12 @@ private:
|
||||
}
|
||||
|
||||
bool link_point(
|
||||
value_param_type v,hashed_index_node_impl*& pos,hashed_non_unique_tag)
|
||||
value_param_type v,node_impl_pointer& pos,hashed_non_unique_tag)
|
||||
{
|
||||
hashed_index_node_impl* prev=pos;
|
||||
hashed_index_node_impl* x=pos->next();
|
||||
node_impl_pointer prev=pos;
|
||||
node_impl_pointer x=pos->next();
|
||||
while(x!=pos){
|
||||
if(eq(key(v),key(node_type::from_impl(x)->value))){
|
||||
if(eq(key(v),key(node_type::from_impl(x)->value()))){
|
||||
pos=prev;
|
||||
return true;
|
||||
}
|
||||
@@ -900,29 +1006,34 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
void link(node_type* x,hashed_index_node_impl* pos)
|
||||
static void link(node_type* x,node_impl_pointer pos)
|
||||
{
|
||||
hashed_index_node_impl::link(x->impl(),pos);
|
||||
node_impl_type::link(x->impl(),pos);
|
||||
};
|
||||
|
||||
void link(hashed_index_node_impl* x,hashed_index_node_impl* pos)
|
||||
static void link(node_impl_pointer x,node_impl_pointer pos)
|
||||
{
|
||||
hashed_index_node_impl::link(x,pos);
|
||||
node_impl_type::link(x,pos);
|
||||
};
|
||||
|
||||
void unlink(node_type* x)
|
||||
static void unlink(node_type* x)
|
||||
{
|
||||
hashed_index_node_impl::unlink(x->impl());
|
||||
node_impl_type::unlink(x->impl());
|
||||
};
|
||||
|
||||
static hashed_index_node_impl* prev(node_type* x)
|
||||
static node_impl_pointer prev(node_type* x)
|
||||
{
|
||||
return hashed_index_node_impl::prev(x->impl());
|
||||
return node_impl_type::prev(x->impl());
|
||||
}
|
||||
|
||||
static void unlink_next(hashed_index_node_impl* x)
|
||||
static node_impl_pointer prev_from(node_type* x,node_impl_pointer y)
|
||||
{
|
||||
hashed_index_node_impl::unlink_next(x);
|
||||
return node_impl_type::prev_from(x->impl(),y);
|
||||
}
|
||||
|
||||
static void unlink_next(node_impl_pointer x)
|
||||
{
|
||||
node_impl_type::unlink_next(x);
|
||||
}
|
||||
|
||||
void calculate_max_load()
|
||||
@@ -948,12 +1059,12 @@ private:
|
||||
auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
|
||||
|
||||
std::size_t i=0;
|
||||
hashed_index_node_impl* x=buckets.begin();
|
||||
hashed_index_node_impl* x_end=buckets.end();
|
||||
node_impl_pointer x=buckets.begin();
|
||||
node_impl_pointer x_end=buckets.end();
|
||||
for(;x!=x_end;++x){
|
||||
hashed_index_node_impl* y=x->next();
|
||||
node_impl_pointer y=x->next();
|
||||
while(y!=x){
|
||||
hashes.data()[i++]=hash(key(node_type::from_impl(y)->value));
|
||||
hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
|
||||
y=y->next();
|
||||
}
|
||||
}
|
||||
@@ -961,11 +1072,11 @@ private:
|
||||
i=0;
|
||||
x=buckets.begin();
|
||||
for(;x!=x_end;++x){
|
||||
hashed_index_node_impl* y=x->next();
|
||||
node_impl_pointer y=x->next();
|
||||
while(y!=x){
|
||||
hashed_index_node_impl* z=y->next();
|
||||
std::size_t buc1=buckets1.position(hashes.data()[i++]);
|
||||
hashed_index_node_impl* x1=buckets1.at(buc1);
|
||||
node_impl_pointer z=y->next();
|
||||
std::size_t buc1=buckets1.position(hashes.data()[i++]);
|
||||
node_impl_pointer x1=buckets1.at(buc1);
|
||||
link(y,x1);
|
||||
y=z;
|
||||
}
|
||||
@@ -976,6 +1087,68 @@ private:
|
||||
first_bucket=buckets.first_nonempty(0);
|
||||
}
|
||||
|
||||
bool in_place(
|
||||
node_impl_pointer x,key_param_type k,std::size_t buc,
|
||||
hashed_unique_tag)const
|
||||
{
|
||||
std::less_equal<node_impl_pointer> leq;
|
||||
node_impl_pointer bbegin=buckets.begin();
|
||||
node_impl_pointer bend=buckets.end();
|
||||
node_impl_pointer pbuc=x->next();
|
||||
|
||||
while(!leq(bbegin,pbuc)||!leq(pbuc,bend))pbuc=pbuc->next();
|
||||
if(buc!=static_cast<std::size_t>(pbuc-bbegin))return false;
|
||||
|
||||
node_impl_pointer y=x;
|
||||
while(y->next()!=x){
|
||||
y=y->next();
|
||||
if(y==pbuc)continue;
|
||||
if(eq(k,key(node_type::from_impl(y)->value())))return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool in_place(
|
||||
node_impl_pointer x,key_param_type k,std::size_t buc,
|
||||
hashed_non_unique_tag)const
|
||||
{
|
||||
std::less_equal<node_impl_pointer> leq;
|
||||
node_impl_pointer bbegin=buckets.begin();
|
||||
node_impl_pointer bend=buckets.end();
|
||||
node_impl_pointer pbuc=x->next();
|
||||
|
||||
while(!leq(bbegin,pbuc)||!leq(pbuc,bend))pbuc=pbuc->next();
|
||||
if(buc!=static_cast<std::size_t>(pbuc-bbegin))return false;
|
||||
|
||||
node_impl_pointer y=x->next();
|
||||
if(y!=pbuc){
|
||||
if(eq(k,key(node_type::from_impl(y)->value()))){
|
||||
/* adjacent to equivalent element -> in place */
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
y=y->next();
|
||||
while(y!=pbuc){
|
||||
if(eq(k,key(node_type::from_impl(y)->value())))return false;
|
||||
y=y->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
while(y->next()!=x){
|
||||
y=y->next();
|
||||
if(eq(k,key(node_type::from_impl(y)->value()))){
|
||||
while(y->next()!=x){
|
||||
y=y->next();
|
||||
if(!eq(k,key(node_type::from_impl(y)->value())))return false;
|
||||
}
|
||||
/* after a group of equivalent elements --> in place */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
void detach_iterators(node_type* x)
|
||||
{
|
||||
@@ -1013,7 +1186,7 @@ void swap(
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
/* sequenced index specifiers */
|
||||
/* hashed index specifiers */
|
||||
|
||||
template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
|
||||
struct hashed_unique
|
||||
@@ -1069,6 +1242,20 @@ struct hashed_non_unique
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
/* Boost.Foreach compatibility */
|
||||
|
||||
template<
|
||||
typename KeyFromValue,typename Hash,typename Pred,
|
||||
typename SuperMeta,typename TagList,typename Category
|
||||
>
|
||||
inline boost::mpl::true_* boost_foreach_is_noncopyable(
|
||||
boost::multi_index::detail::hashed_index<
|
||||
KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>*&,
|
||||
boost::foreach::tag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
|
||||
|
||||
#endif
|
||||
|
||||