initial commit

[SVN r22759]
This commit is contained in:
Joaquín M. López Muñoz 2004-05-07 10:44:23 +00:00
commit b35bef74e4
144 changed files with 22006 additions and 0 deletions

96
.gitattributes vendored Normal file
View File

@ -0,0 +1,96 @@
* text=auto !eol svneol=native#text/plain
*.gitattributes text svneol=native#text/plain
# Scriptish formats
*.bat text svneol=native#text/plain
*.bsh text svneol=native#text/x-beanshell
*.cgi text svneol=native#text/plain
*.cmd text svneol=native#text/plain
*.js text svneol=native#text/javascript
*.php text svneol=native#text/x-php
*.pl text svneol=native#text/x-perl
*.pm text svneol=native#text/x-perl
*.py text svneol=native#text/x-python
*.sh eol=lf svneol=LF#text/x-sh
configure eol=lf svneol=LF#text/x-sh
# Image formats
*.bmp binary svneol=unset#image/bmp
*.gif binary svneol=unset#image/gif
*.ico binary svneol=unset#image/ico
*.jpeg binary svneol=unset#image/jpeg
*.jpg binary svneol=unset#image/jpeg
*.png binary svneol=unset#image/png
*.tif binary svneol=unset#image/tiff
*.tiff binary svneol=unset#image/tiff
*.svg text svneol=native#image/svg%2Bxml
# Data formats
*.pdf binary svneol=unset#application/pdf
*.avi binary svneol=unset#video/avi
*.doc binary svneol=unset#application/msword
*.dsp text svneol=crlf#text/plain
*.dsw text svneol=crlf#text/plain
*.eps binary svneol=unset#application/postscript
*.gz binary svneol=unset#application/gzip
*.mov binary svneol=unset#video/quicktime
*.mp3 binary svneol=unset#audio/mpeg
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
*.ps binary svneol=unset#application/postscript
*.psd binary svneol=unset#application/photoshop
*.rdf binary svneol=unset#text/rdf
*.rss text svneol=unset#text/xml
*.rtf binary svneol=unset#text/rtf
*.sln text svneol=native#text/plain
*.swf binary svneol=unset#application/x-shockwave-flash
*.tgz binary svneol=unset#application/gzip
*.vcproj text svneol=native#text/xml
*.vcxproj text svneol=native#text/xml
*.vsprops text svneol=native#text/xml
*.wav binary svneol=unset#audio/wav
*.xls binary svneol=unset#application/vnd.ms-excel
*.zip binary svneol=unset#application/zip
# Text formats
.htaccess text svneol=native#text/plain
*.bbk text svneol=native#text/xml
*.cmake text svneol=native#text/plain
*.css text svneol=native#text/css
*.dtd text svneol=native#text/xml
*.htm text svneol=native#text/html
*.html text svneol=native#text/html
*.ini text svneol=native#text/plain
*.log text svneol=native#text/plain
*.mak text svneol=native#text/plain
*.qbk text svneol=native#text/plain
*.rst text svneol=native#text/plain
*.sql text svneol=native#text/x-sql
*.txt text svneol=native#text/plain
*.xhtml text svneol=native#text/xhtml%2Bxml
*.xml text svneol=native#text/xml
*.xsd text svneol=native#text/xml
*.xsl text svneol=native#text/xml
*.xslt text svneol=native#text/xml
*.xul text svneol=native#text/xul
*.yml text svneol=native#text/plain
boost-no-inspect text svneol=native#text/plain
CHANGES text svneol=native#text/plain
COPYING text svneol=native#text/plain
INSTALL text svneol=native#text/plain
Jamfile text svneol=native#text/plain
Jamroot text svneol=native#text/plain
Jamfile.v2 text svneol=native#text/plain
Jamrules text svneol=native#text/plain
Makefile* text svneol=native#text/plain
README text svneol=native#text/plain
TODO text svneol=native#text/plain
# Code formats
*.c text svneol=native#text/plain
*.cpp text svneol=native#text/plain
*.h text svneol=native#text/plain
*.hpp text svneol=native#text/plain
*.ipp text svneol=native#text/plain
*.tpp text svneol=native#text/plain
*.jam text svneol=native#text/plain
*.java text svneol=native#text/plain

16
Jamfile Normal file
View File

@ -0,0 +1,16 @@
# Boost.MultiIndex examples and tests Jamfile
#
# Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and distribution
# are subject to 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 ;

124
doc/acknowledgements.html Normal file
View File

@ -0,0 +1,124 @@
<!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 - Acknowledgements</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<h1><img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Acknowledgements</h1>
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
Future work
</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">
</div><br clear="all" style="clear: all;">
<hr>
<p>
Fernando Cacciola, Darren Cook, Beman Dawes, Jeremy Maitin-Shepard and Daryle
Walker from the Boost mailing list provided useful suggestions for improvement
on the first alpha releases of the library. Gang Wang discovered several
bugs in the code. Thomas Wenisch brought out the idea of "sequence sets"
from which sequenced indices were designed. Giovanni Bajo, Chris Little and
Maxim Yegorushkin tested the library on several platforms. Rosa
Bern&aacute;rdez proofread the last version of the tutorial.
</p>
<p>
Pavel Vo&#382;en&iacute;lek has been immensely helpful in thoroughly reviewing
every single bit of the library, and he also suggested several extra
functionalities, most notably range querying, safe mode, polymorphic key
extractors and MPL support. Thank you!
</p>
<p>
The Boost acceptance review took place between March 20th and 30th 2004.
Pavel Vo&#382;en&iacute;lek was the review manager. Thanks to all the people
who participated and specially to those who submitted reviews:
Fredrik Blomqvist, Tom Brinkman, Paul A Bristow, Darren Cook, Jeff Garland,
David B. Held, Brian McNamara, Gary Powell, Rob Stewart, Arkadiy Vertleyb,
J&ouml;rg Walter. Other Boost members also contributed ideas, particularly
in connection with the library's naming scheme: Pavol Droba,
Dave Gomboc, Jeremy Maitin-Shepard, Thorsten Ottosen, Matthew Vogt,
Daryle Walker. My apologies if I inadvertently left somebody out of this
list.
</p>
<p>
Boost.MultiIndex could not have been written without Aleksey Gurtovoy
et al. superb <a href="../../../libs/mpl/doc/index.html">Boost MPL
Library</a>. Also, Aleksey's techniques for dealing with ETI-related
problems in MSVC++ 6.0 helped solve some internal issues of the library.
</p>
<p>
The internal implementation of red-black trees is based on that of SGI STL
<a href="http://www.sgi.com/tech/stl/stl_tree.h">stl_tree.h</a> file:
</p>
<blockquote>
Copyright (c) 1996,1997
Silicon Graphics Computer Systems, Inc.
<br>
Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation. Silicon Graphics makes no
representations about the suitability of this software for any
purpose. It is provided &quot;as is&quot; without express or implied warranty.
<br>
<br>
Copyright (c) 1994
Hewlett-Packard Company
<br>
Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation. Hewlett-Packard Company makes no
representations about the suitability of this software for any
purpose. It is provided &quot;as is&quot; without express or implied warranty.
</blockquote>
<p>
<span style="float:right;"><img src="lopez.jpg" width="160" height="120"></span>
I would like to dedicate this piece of work to Rosa Bern&aacute;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&oacute;pez (2001-2003): he
lived too fast, died too young.
<br style="clear:all;">
</p>
<hr>
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
Future work
</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">
</div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

1321
doc/advanced_topics.html Normal file

File diff suppressed because it is too large Load Diff

314
doc/compiler_specifics.html Normal file
View File

@ -0,0 +1,314 @@
<!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 - Compiler specifics</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<h1><img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Compiler specifics</h1>
<div class="prev_link"><a href="reference/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="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="performance.html"><img src="next.gif" alt="performance" border="0"><br>
Performance
</a></div><br clear="all" style="clear: all;">
<hr>
<p>
Boost.MultiIndex has been tried in different compilers, with
various degrees of success. We list the limitations encountered,
along with suitable workarounds when available. Up to date information
on compatibility of Boost.MultiIndex with several compilers can
be found at the <a href="http://boost.sourceforge.net/regression-logs/">
Boost Compiler Status Summary</a>.
</p>
<h2>Contents</h2>
<ul>
<li><a href="#bcb_64">Borland C++ Builder 6.4</a></li>
<li><a href="#gcc_32_cygwin">GNU GCC 3.3.1 (cygming special)</a></li>
<li><a href="#intel_7_win">Intel C++ Compiler for Windows 32-bit 7.0/7.1</a></li>
<li><a href="#intel_8_win">Intel C++ Compiler for Windows 32-bit 8.0</a></li>
<li><a href="#cw_92_mac">Metrowerks CodeWarrior 9.2 for Mac OS</a></li>
<li><a href="#msvc_60">Microsoft Visual C++ 6.0 Service Pack 5</a></li>
<li><a href="#msvc_60_stlport_462">Microsoft Visual C++ 6.0 Service Pack 5 + STLport 4.6.2</a></li>
<li><a href="#msvc_71">Microsoft Visual C++ 7.1</a></li>
</ul>
<h2><a name="bcb_64">Borland C++ Builder 6.4</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.
</p>
<h2><a name="gcc_32_cygwin">GNU GCC 3.3.1 (cygming special)</a></h2>
<p>
No problems have been detected with this compiler. The tests were
performed under Cygwin 1.5.7. Most likely Boost.MultiIndex will work seamlessly
for GNU GCC 3.3 or later under any platform.
</p>
<h2><a name="intel_7_win">Intel C++ Compiler for Windows 32-bit 7.0/7.1</a></h2>
<p>
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
replace with
<a href="reference/key_extraction.html#member_offset"><code>member_offset</code></a> or
use the cross-platform macro
<a href="reference/key_extraction.html#boost_multi_index_member">
<code>BOOST_MULTI_INDEX_MEMBER</code></a>.
</p>
<hr>
<p>
Altough Koenig lookup seems to be officially supported by this compiler,
some issues have arisen seemingly due to bugs related to this facility.
In these cases you might need to explicitly qualify global names with
<code>::boost::multi_index</code>.
</p>
<h2><a name="intel_8_win">Intel C++ Compiler for Windows 32-bit 8.0</a></h2>
<p>
No problems have been detected with this compiler.
</p>
<h2><a name="cw_92_mac">Metrowerks CodeWarrior 9.2 for Mac OS</a></h2>
<p>
No problems have been detected with this compiler.
</p>
<h2><a name="msvc_60">Microsoft Visual C++ 6.0 Service Pack 5</a></h2>
<p>
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
replace with
<a href="reference/key_extraction.html#member_offset"><code>member_offset</code></a> or
use the cross-platform macro
<a href="reference/key_extraction.html#boost_multi_index_member">
<code>BOOST_MULTI_INDEX_MEMBER</code></a>.
</p>
<p>
<a href="reference/key_extraction.html#const_mem_fun"><code>const_mem_fun</code></a> not
supported, replace with
<a href="reference/key_extraction.html#const_mem_fun_explicit">
<code>const_mem_fun_explicit</code></a>
or use the cross-platform macro
<a href="reference/key_extraction.html#boost_multi_index_const_mem_fun">
<code>BOOST_MULTI_INDEX_CONST_MEM_FUN</code></a>.
</p>
<p>
<a href="reference/key_extraction.html#mem_fun"><code>mem_fun</code></a> is not
supported, replace with
<a href="reference/key_extraction.html#mem_fun_explicit">
<code>mem_fun_explicit</code></a> or
use the cross-platform macro
<a href="reference/key_extraction.html#boost_multi_index_mem_fun">
<code>BOOST_MULTI_INDEX_MEM_FUN</code></a>.
</p>
<hr>
<p>
No support for <a href="reference/multi_index_container.html#index_retrieval">index retrieval</a>
and <a href="reference/multi_index_container.html#projection">projection</a>
nested types and member functions:
<ul>
<li><code>nth_index</code>,</li>
<li><code>index</code>,</li>
<li><code>nth_index_iterator</code>,</li>
<li><code>nth_index_const_iterator</code>,</li>
<li><code>index_iterator</code>,</li>
<li><code>index_const_iterator</code>,</li>
<li><code>get</code>,</li>
<li><code>project</code>.</li>
</ul>
You can use instead their global equivalents. Also, this compiler does not
implement Koenig lookup, so you might need to explicitly qualify these
global names with <code>::boost::multi_index</code>.
</p>
<hr>
<p>
The lack of partial template specialization support in MSVC++ 6.0
results in some inconveniences when using <code>composite_key</code> that
can be remedied as explained in
<a href="advanced_topics.html#composite_key_no_pts">"<code>composite_key</code>
in compilers without partial template specialization"</a> on the advanced
topics section.
</p>
<hr>
<p>
MSVC++ 6.0 presents serious limitations for the maximum length of
symbol names generated by the compiler, which might result in the
linker error
<code><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/lnk1179.asp">LNK1179</a>:
invalid or corrupt file: duplicate comdat
comdat</code>. To overcome this problem, you can restrict the maximum
number of elements accepted by
<a href="reference/indices.html#indexed_by"><code>indexed_by</code></a>,
<a href="reference/indices.html#tag"><code>tag</code></a> and
<a href="reference/key_extraction.html#composite_key"><code>composite_key</code></a>
by globally setting the values of the macros
<ul>
<li><code>BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE</code>
(default in MSVC++ 6.0: 5),</li>
<li><code>BOOST_MULTI_INDEX_LIMIT_TAG_SIZE</code>
(default in MSVC++ 6.0: 3),</li>
<li><code>BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE</code>
(default in MSVC++ 6.0: 5).</li>
</ul>
This operation results in a modest reduction of the lengths of symbol
names.
</p>
<hr>
<p>
Under some circumstances, the compiler emits the error
<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/C2587.asp">
<code>C2587</code></a><code>: '_U' : illegal use of local variable as
default parameter</code>, inside the MSVC internal header
<code>&lt;xlocnum></code>.
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="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
of <code>multi_index_container</code> iterator constructor. Two workarounds exist:
the first consists of avoiding this constructor and replacing
code like:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;...&gt;</span> <span class=identifier>s</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>
with equivalent operations:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;...&gt;</span> <span class=identifier>s</span><span class=special>;</span>
<span class=identifier>s</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=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>
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>&lt;xlocnum></code>
<blockquote><pre>
<span class=preprocessor>#define</span> <span class=identifier>_VIRTUAL</span> <span class=keyword>virtual</span>
</pre></blockquote>
<p>
with the following:
</p>
<blockquote><pre>
<span class=preprocessor>#define</span> <span class=identifier>_VIRTUAL</span>
</pre></blockquote>
</p>
<p>
<b>Warning</b>: it is not known whether this
replacement can result in unexpected side effects in code implicitly
using <code>&lt;xlocnum></code>.
</p>
<hr>
<p>
In general, the extensive use of templates by Boost.MultiIndex puts this compiler
under severe stress, so that several internal limitations may be reached.
The following measures can help alleviate these problems:
<ul>
<li>Set the compiler option <code>/Zm</code> (Specify Memory Allocation Limit)
to increase the amount of memory available for compilation. Usual values for
this option range from 300 to 800.</li>
<li>If in debug mode, try switching from <code>/ZI</code> (Program Database for
Edit and Continue) to a less demanding type of debugging information
(<code>/Zi</code>, <code>/Z7</code> or <code>Zd</code>.)</li>
<li>Play with the precompiled headers options. Usually, turning this feature
off yields the best results.</li>
<li>If the compiler emits the error
<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/c1055.asp">
<code>C1055</code></a><code>: compiler limit : out of keys</code>, try
disabling the option <code>/Gm</code> (Enable Minimal Rebuild.) In these
cases, it is also beneficial to split the project into smaller
subprojects.</li>
</ul>
</p>
<h2>
<a name="msvc_60_stlport_462">Microsoft Visual C++ 6.0 Service Pack 5
+ STLport 4.6.2</a>
</h2>
<p>
Boost.MultiIndex works for this configuration. The same limitations apply as
in MSVC++ 6.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">
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>
<hr>
<div class="prev_link"><a href="reference/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="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="performance.html"><img src="next.gif" alt="performance" border="0"><br>
Performance
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

319
doc/examples.html Normal file
View File

@ -0,0 +1,319 @@
<!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 - Examples</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<h1><img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Examples</h1>
<div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
Performance
</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="tests.html"><img src="next.gif" alt="tests" border="0"><br>
Tests
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<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="#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>
<li><a href="#example5">Example 5: sequenced indices</a></li>
<li><a href="#example6">Example 6: complex searches and foreign keys</a></li>
<li><a href="#example7">Example 7: composite keys</a></li>
</ul>
<h2><a name="example1">Example 1: basic usage</a></h2>
<p>
See <a href="../example/basic.cpp">source code</a>.
</p>
<p>
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>
<p>
See <a href="../example/memfun_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
<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.
</p>
<p>
Keys based on member 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
constraint anyway.
</p>
<h2><a name="example3">Example 3: constructing <code>multi_index_container</code>s
with <code>ctor_args_list</code></a></h2>
<p>
See <a href="../example/non_default_ctor.cpp">source code</a>.
</p>
<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
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>.
</p>
<h2><a name="example4">Example 4: bidirectional map</a></h2>
<p>
See <a href="../example/bimap.cpp">source code</a>.
</p>
<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&lt;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
for both keys. The program features a tiny Spanish-English
dictionary with online query of words in both languages.
</p>
<h2><a name="example5">Example 5: sequenced indices</a></h2>
<p>
See <a href="../example/sequenced.cpp">source code</a>.
</p>
<p>
The combination of a sequenced index with an index of type <code>ordered_non_unique</code>
yields a <code>list</code>-like structure with fast lookup capabilities. The
example performs some operations on a given text, like word counting and
selective deletion of some words.
</p>
<h2><a name="example6">Example 6: complex searches and foreign keys</a></h2>
<p>
See <a href="../example/complex_structs.cpp">source code</a>.
</p>
<p>
This program illustrates some advanced techniques that can be applied
for complex data structures using <code>multi_index_container</code>.
Consider a <code>car_model</code> class for storing information
about automobiles. On a fist approach, <code>car_model</code> can
be defined as:
</p>
<blockquote><pre>
<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=keyword>int</span> <span class=identifier>price</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
<p>
This definition has a design flaw that any reader acquainted with
relational databases can easily spot: The <code>manufacturer</code>
member is duplicated among all cars having the same manufacturer.
This is a waste of space and poses difficulties when, for instance,
the name of a manufacturer has to be changed. Following the usual
principles in relational database design, the appropriate design
involves having the manufactures stored in a separate
<code>multi_index_container</code> and store pointers to these in
<code>car_model</code>:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>car_manufacturer</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=special>};</span>
<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>car_manufacturer</span><span class=special>*</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>
<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
is complex enough that a suitable key extractor has to be defined. The following
utility cascades two key extractors:
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>KeyExtractor1</span><span class=special>,</span><span class=keyword>class</span> <span class=identifier>KeyExtractor2</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>key_from_key</span>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>KeyExtractor1</span><span class=special>::</span><span class=identifier>result_type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=identifier>key_from_key</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>KeyExtractor1</span><span class=special>&amp;</span> <span class=identifier>key1_</span><span class=special>=</span><span class=identifier>KeyExtractor1</span><span class=special>(),</span>
<span class=keyword>const</span> <span class=identifier>KeyExtractor2</span><span class=special>&amp;</span> <span class=identifier>key2_</span><span class=special>=</span><span class=identifier>KeyExtractor2</span><span class=special>()):</span>
<span class=identifier>key1</span><span class=special>(</span><span class=identifier>key1_</span><span class=special>),</span><span class=identifier>key2</span><span class=special>(</span><span class=identifier>key2_</span><span class=special>)</span>
<span class=special>{}</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Arg</span><span class=special>&gt;</span>
<span class=identifier>result_type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Arg</span><span class=special>&amp;</span> <span class=identifier>arg</span><span class=special>)</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>key1</span><span class=special>(</span><span class=identifier>key2</span><span class=special>(</span><span class=identifier>arg</span><span class=special>));</span>
<span class=special>}</span>
<span class=keyword>private</span><span class=special>:</span>
<span class=identifier>KeyExtractor1</span> <span class=identifier>key1</span><span class=special>;</span>
<span class=identifier>KeyExtractor2</span> <span class=identifier>key2</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
<p>
so that access from a <code>car_model</code> to the <code>name</code> field
of its associated <code>car_manufacturer</code> can be accomplished with
</p>
<blockquote><pre>
<span class=identifier>key_from_key</span><span class=special>&lt;</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>car_manufacturer</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>car_manufacturer</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>car_model</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>car_manufacturer</span> <span class=special>*,</span><span class=identifier>car_model</span><span class=special>::</span><span class=identifier>manufacturer</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
The program asks the user for a car manufacturer and a range of prices
and returns the car models satisfying these requirements. This is a complex
search that cannot be performed on a single operation. Broadly sketched,
one procedure for executing the selection is:
<ol>
<li>Select the elements with the given manufacturer by means
of <code>equal_range</code>,
<li>feed these elements into a <code>multi_index_container</code> sorted
by price,
<li>select by price using <code>lower_bound</code> and
<code>upper_bound</code>;
</ol>
or alternatively:
<ol>
<li>Select the elements within the price range with
<code>lower_bound</code> and <code>upper_bound</code>,
<li>feed these elements into a <code>multi_index_container</code> sorted
by manufacturer,
<li>locate the elements with given manufacturer using
<code>equal_range</code>.
</ol>
An interesting technique developed in the example lies in
the construction of the intermediate <code>multi_index_container</code>.
In order to avoid object copying, appropriate <i>view</i> types
are defined with <code>multi_index_container</code>s having as elements
pointers to <code>car_model</code>s instead of actual objects.
These views have to be supplemented with appropriate
dereferencing key extractors.
</p>
<h2><a name="example7">Example 7: composite keys</a></h2>
<p>
See <a href="../example/composite_keys.cpp">source code</a>.
</p>
<p>
Boost.MultiIndex <a href="advanced_topics.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
along with an interactive Unix-like shell. A file entry is represented by
the following structure:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>file_entry</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>unsigned</span> <span class=identifier>size</span><span class=special>;</span>
<span class=keyword>bool</span> <span class=identifier>is_dir</span><span class=special>;</span> <span class=comment>// true if the entry is a directory</span>
<span class=keyword>const</span> <span class=identifier>file_entry</span><span class=special>*</span> <span class=identifier>dir</span><span class=special>;</span> <span class=comment>// directory this entry belongs in</span>
<span class=special>};</span>
</pre></blockquote>
<p>
Entries are kept in a <code>multi_index_container</code> maintaining two indices
with composite keys:
<ul>
<li>A primary index ordered by directory and name,</li>
<li>a secondary index ordered by directory and size.</li>
</ul>
The reason that the order is made firstly by the directory in which
the files are located obeys to the local nature of the shell commands,
like for instance <code>ls</code>. The shell simulation only has three
commands:
<ul>
<li><code>cd [.|..|<i>&lt;directory&gt;</i>]</code></li>
<li><code>ls [-s]</code> (<code>-s</code> orders the output by size)</li>
<li><code>mkdir <i>&lt;directory&gt;</i></code></li>
</ul>
The program exits when the user presses the Enter key at the command prompt.
</p>
<p>
The reader is challenged to add more functionality to the program (for
instance, implementation of the <code>cp</code> command and handling of
absolute paths.)
</p>
<hr>
<div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
Performance
</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="tests.html"><img src="next.gif" alt="tests" border="0"><br>
Tests
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

273
doc/future_work.html Normal file
View File

@ -0,0 +1,273 @@
<!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 - Future work</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<h1><img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Future work</h1>
<div class="prev_link"><a href="tests.html"><img src="prev.gif" alt="tests" border="0"><br>
Tests
</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="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
Acknowledgements
</a></div><br clear="all" style="clear: all;">
<hr>
<p>
A number of new functionalities are considered for inclusion into
future releases of Boost.MultiIndex. Some of them depend on the
potential for extensibility of the library, which has been a guiding
principle driving the current internal design of <code>multi_index_container</code>.
</p>
<h2>Contents</h2>
<ul>
<li><a href="#hashed_indices">Hashed indices</a></li>
<li><a href="#ranked_indices">Ranked 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="#serialization">Serialization support</a></li>
<li><a href="#move_semantics">Move semantics</a></li>
</ul>
<h2><a name="hashed_indices">Hashed indices</a></h2>
<p>
Several STL implementations feature hashed sets as a natural
counterpart to <code>std::set</code> and <code>std::multiset</code>.
<code>multi_index_container</code> can also benefit from the inclusion of hashed
indices. As the exact details of the interfaces of hashed sets differ among
library vendors, a good starting point seems Matt Austern's paper
<a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1456.html">A
Proposal to Add Hash Tables to the Standard Library (revision 4)</a>, which
has been submitted for acceptance into the next revision of the
C++ standard.
</p>
<h2><a name="ranked_indices">Ranked indices</a></h2>
<p>
Ordered indices are implemented using red-black trees; these trees
can be augmented with additional information to obtain a type
of data structure called
<a href="http://pine.cs.yale.edu/pinewiki/OrderStatisticsTree"><i>order-statistics
trees</i></a>, allowing for logarithmic search of the <i>n</i>-th element. It
has been proposed that order-statistics trees be used to devise a new type of
<i>ranked indices</i> that support <code>operator[]</code> while retaining
the functionality of ordered indices.
</p>
<h2><a name="notifying">Notifying indices</a></h2>
<p>
<i>Notifying indices</i> can be implemented as decorators over
preexistent index types, with the added functionality that internal
events of the index (insertion, erasing, modifying of elements) are
signalled to an external entity --for instance, by means of the
<a href="../../../doc/html/signals.html">Boost.Signals</a>
library. This functionality can have applications for:
<ol>
<li>Logging,</li>
<li>interfacing to GUI-based applications,</li>
<li>synchronization between separate data structures.</li>
</ol>
</p>
<p>
The following is a sketch of a possible realization of notifying
indices:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>insert_log</span>
<span class=special>{</span>
<span class=keyword>void</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=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>clog</span><span class=special>&lt;&lt;</span><span class=string>&quot;insert: &quot;</span><span class=special>&lt;&lt;</span><span class=identifier>x</span><span class=special>&lt;&lt;</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=special>};</span>
<span class=keyword>int</span> <span class=identifier>main</span><span class=special>()</span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>notifying</span><span class=special>&lt;</span><span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;,</span> <span class=comment>// notifying index</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>indexed_t</span><span class=special>;</span>
<span class=identifier>indexed_t</span> <span class=identifier>t</span><span class=special>;</span>
<span class=comment>// on_insert is the signal associated to insertions</span>
<span class=identifier>t</span><span class=special>.</span><span class=identifier>on_insert</span><span class=special>.</span><span class=identifier>connect</span><span class=special>(</span><span class=identifier>insert_log</span><span class=special>());</span>
<span class=identifier>t</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>0</span><span class=special>);</span>
<span class=identifier>t</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>1</span><span class=special>);</span>
<span class=keyword>return</span> <span class=number>0</span><span class=special>;</span>
<span class=special>}</span>
<span class=comment>// output:
// insert: 0
// insert: 1</span>
</pre></blockquote>
<h2><a name="constraints">Constraints</a></h2>
<p>
The notifying indices functionality described above exploits a powerful
design pattern based on <i>index adaptors</i>, decorators over preexistent
indices which add some functionality or somehow change the semantics of
the underlying index. This pattern can be used for the implementation
of <i>constraints</i>, adaptors that restrict the elements accepted by an
index according to some validation predicate. The following is a possible
realization of how constraints syntax may look like:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>is_even</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=special>{</span><span class=keyword>return</span> <span class=identifier>x</span><span class=special>%</span><span class=number>2</span><span class=special>==</span><span class=number>0</span><span class=special>;}</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>constrained</span><span class=special>&lt;</span><span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span><span class=identifier>is_even</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>indexed_t</span><span class=special>;</span>
</pre></blockquote>
<h2><a name="user_defined_indices">User-defined indices</a></h2>
<p>
The mechanisms by which Boost.MultiIndex orchestrates the
operations of the indices held by a <code>multi_index_container</code> are
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 an
<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>
<code>multi_index_container</code> is rich enough to provide the basis
for implementation of <i>indexed maps</i>, i.e. maps which
can be looked upon several different keys. The motivation for having
such a container is mainly aesthetic convenience, since it
would not provide any additional feature to similar constructs
based directly on <code>multi_index_container</code>.
</p>
<p>
The main challenge in writing an indexed map lies in the design of a
reasonable interface that resembles that of <code>std::map</code> as
much as possible. There seem to be fundamental difficulties in extending
the syntax of a <code>std::map</code> to multiple keys. For one example,
consider the situation:
</p>
<blockquote><pre>
<span class=identifier>indexed_map</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>,</span><span class=identifier>string</span><span class=special>,</span><span class=keyword>double</span><span class=special>&gt;</span> <span class=identifier>m</span><span class=special>;</span>
<span class=comment>// keys are int and string, double is the mapped to value</span>
<span class=special>...</span>
<span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=identifier>m</span><span class=special>[</span><span class=number>0</span><span class=special>]&lt;&lt;</span><span class=identifier>endl</span><span class=special>;</span> <span class=comment>// OK</span>
<span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=identifier>m</span><span class=special>[</span><span class=string>&quot;zero&quot;</span><span class=special>]&lt;&lt;</span><span class=identifier>endl</span><span class=special>;</span> <span class=comment>// OK</span>
<span class=identifier>m</span><span class=special>[</span><span class=number>1</span><span class=special>]=</span><span class=number>1.0</span><span class=special>;</span> <span class=comment>// !!</span>
</pre></blockquote>
<p>
In the last sentence of the example, the user has no way of
providing the <code>string</code> key mapping to the same value
as <code>m[1]</code>. This and similar problems have to be devoted
a careful study when designing the interface of a potential
indexed map.
</p>
<h2><a name="serialization">Serialization support</a></h2>
<p>
Once <a href="http://www.rrsd.com/boost/index.htm">Robert Ramey's
serialization library</a> gets accepted into Boost, support for
archiving/retrieving <code>multi_index_container</code>s should be added.
</p>
<h2><a name="move_semantics">Move semantics</a></h2>
<p>
Andrei Alexandrescu introduced a technique for simulating move
constructors called Mojo (see his article in C/C++ User Journal
<a href="http://www.cuj.com/documents/s=8246/cujcexp2102alexandr/">
"Generic&lt;Programming>: Move Constructors"</a>.) Move semantics
alleviates the computational load involved in the creation and copying
of temporary objects, specially for heavy classes as
<code>multi_index_container</code>s are. David Abrahams and Gary Powell provide
an alternative implementation of move semantics in their paper
<a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1610.html">
"Clarification of Initialization of Class Objects by rvalues"</a> for
the C++ Evolution Working Group.
</p>
<p>
Adding move semantics to <code>multi_index_container</code> is particularly
beneficial when the container is used as an internal building block in other
libraries (vg. relational database frameworks), enabling the efficient
development of functions returning <code>multi_index_container</code>s. Without support
for move semantics, this scheme is impractical and less elegant syntaxes
should be resorted to.
</p>
<hr>
<div class="prev_link"><a href="tests.html"><img src="prev.gif" alt="tests" border="0"><br>
Tests
</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="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
Acknowledgements
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

74
doc/index.html Normal file
View File

@ -0,0 +1,74 @@
<!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 - Index</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<h1><img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost Multi-index Containers Library</h1>
<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>
Tutorial
</a></div><br clear="all" style="clear: all;">
<hr>
<p>
The Boost Multi-index Containers Library provides a class template named
<code>multi_index_container</code> which enables the construction of containers
maintaining one or more <i>indices</i> with different sorting and access semantics.
Indices provide interfaces similar to those of STL containers, making using them
familiar. The concept of multi-indexing over the same collection of elements is
borrowed from relational database terminology and allows for the specification of
complex data structures in the spirit of multiply indexed relational tables where
simple sets and maps are not enough.
</p>
<p>
Boost.MultiIndex features additional functionalities, like subobject searching,
range querying and in-place updating of elements, which make it a convenient replacement
for <code>std::set</code> and <code>set::multiset</code> even when no multi-indexing
capabilities are needed.
</p>
<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="reference/index.html">Reference</a></li>
<li><a href="compiler_specifics.html">Compiler specifics</a></li>
<li><a href="performance.html">Performance</a></li>
<li><a href="examples.html">Examples</a></li>
<li><a href="tests.html">Tests</a></li>
<li><a href="future_work.html">Future work</a></li>
<li><a href="acknowledgements.html">Acknowledgements</a></li>
</ul>
<hr>
<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>
Tutorial
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

BIN
doc/lopez.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
doc/next.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

BIN
doc/perf_1o.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/perf_1o1s.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
doc/perf_1s.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/perf_2o.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/perf_2o1s.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/perf_3o.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

724
doc/performance.html Normal file
View File

@ -0,0 +1,724 @@
<!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 - Performance</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<h1><img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Performance</h1>
<div class="prev_link"><a href="compiler_specifics.html"><img src="prev.gif" alt="compiler specifics" border="0"><br>
Compiler specifics
</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="examples.html"><img src="next.gif" alt="examples" border="0"><br>
Examples
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#simulation">Manual simulation of a <code>multi_index_container</code></a></li>
<li><a href="#spatial_efficiency">Spatial efficiency</a></li>
<li><a href="#time_efficiency">Time efficiency</a></li>
<li><a href="#tests">Performance tests</a>
<ul>
<li><a href="#test_1r">Results for 1 ordered index</a>
<ul>
<li><a href="#memory_1r">Memory consumption</a></li>
<li><a href="#time_1r">Execution time</a></li>
</ul>
</li>
<li><a href="#test_1s">Results for 1 sequenced index</a>
<ul>
<li><a href="#memory_1s">Memory consumption</a></li>
<li><a href="#time_1s">Execution time</a></li>
</ul>
</li>
<li><a href="#test_2r">Results for 2 ordered indices</a>
<ul>
<li><a href="#memory_2r">Memory consumption</a></li>
<li><a href="#time_2r">Execution time</a></li>
</ul>
</li>
<li><a href="#test_1r1s">Results for 1 ordered index + 1 sequenced index</a>
<ul>
<li><a href="#memory_1r1s">Memory consumption</a></li>
<li><a href="#time_1r1s">Execution time</a></li>
</ul>
</li>
<li><a href="#test_3r">Results for 3 ordered indices</a>
<ul>
<li><a href="#memory_3r">Memory consumption</a></li>
<li><a href="#time_3r">Execution time</a></li>
</ul>
</li>
<li><a href="#test_2r1s">Results for 2 ordered indices + 1 sequenced index</a>
<ul>
<li><a href="#memory_2r1s">Memory consumption</a></li>
<li><a href="#time_2r1s">Execution time</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#conclusions">Conclusions</a></li>
</ul>
<h2><a name="intro">Introduction</a></h2>
<p>
Boost.MultiIndex helps the programmer to avoid the manual construction of cumbersome
compositions of containers when multiindexing capabilities are needed. Furthermore,
it does so in an efficient manner, both in terms of space and time consumption. The
space savings stem from the compact representation of the underlying data structures,
requiring a single node per element. As for time efficiency, Boost.MultiIndex
intensively uses metaprogramming techniques producing very tight implementations
of member functions which take care of the elementary operations for each index:
for <code>multi_index_container</code>s with two or more indices, the running time
can be reduced to half as long as with manual simulations involving several
STL containers.
</p>
<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
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
or more indices with a suitable combination of standard containers.
</p>
<p>
Consider the following instantiation of <code>multi_index_container</code>:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;,</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>greater</span> <span class=special>&gt;,</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>indexed_t</span><span class=special>;</span>
</pre></blockquote>
<p>
<code>indexed_t</code> maintains two internal indices on elements of type
<code>int</code>. In order to simulate this data structure resorting only to
standard STL containers, one can use on a first approach the following types:
</p>
<blockquote><pre>
<span class=comment>// dereferencing compare predicate</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Iterator</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>it_compare</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>Iterator</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>Iterator</span><span class=special>&amp;</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>comp</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=special>}</span>
<span class=keyword>private</span><span class=special>:</span>
<span class=identifier>Compare</span> <span class=identifier>comp</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>&lt;</span><span class=keyword>int</span><span class=special>&gt;</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>&lt;</span>
<span class=keyword>const</span> <span class=keyword>int</span><span class=special>*,</span>
<span class=identifier>it_compare</span><span class=special>&lt;</span>
<span class=keyword>const</span> <span class=keyword>int</span><span class=special>*,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>greater</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</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>
where <code>manual_t1</code> is the "base" container that holds
the actual elements, and <code>manual_t2</code> stores pointers to
elements of <code>manual_t1</code>. This scheme turns out to be quite
inefficient, though: while insertion into the data structure is simple enough:
</p>
<blockquote><pre>
<span class=identifier>manual_t1</span> <span class=identifier>c1</span><span class=special>;</span>
<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>(&amp;*</span><span class=identifier>t1</span><span class=special>);</span>
</pre></blockquote>
deletion, on the other hand, necessitates a logarithmic search, whereas
<code>indexed_t</code> deletes in constant time:
<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>
</pre></blockquote>
<p>
The right approach consists of feeding the second container not with
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>&lt;</span><span class=keyword>int</span><span class=special>&gt;</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>&lt;</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>&lt;</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>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</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>
Now, insertion and deletion can be performed with complexity bounds
equivalent to those of <code>indexed_t</code>:
</p>
<blockquote><pre>
<span class=identifier>manual_t1</span> <span class=identifier>c1</span><span class=special>;</span>
<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=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>
</pre></blockquote>
<p>
The construction can be extended in a straightworward manner to
handle more than two indices. In what follows, we will compare
instantiations of <code>multi_index_container</code> against this sort of
manual simulations.
</p>
<h2><a name="spatial_efficiency">Spatial efficiency</a></h2>
<p>
The gain in space consumption of <code>multi_index_container</code> with
respect to its manual simulations is amenable to a very simple
theoretical analysis. For simplicity, we will ignore alignment
issues (which in general play in favor of <code>multi_index_container</code>.)
</p>
<p>
Nodes of a <code>multi_index_container</code> with <i>N</i> indices hold the value
of the element plus <i>N</i> headers containing linking information for
each index. Thus the node size is
</p>
<blockquote>
<i>S<sub>I</sub></i> = <i>e</i> + <i>h</i><sub>0</sub> + ··· +
<i>h</i><sub><i>N</i>-1</sub>, where<br>
<i>e</i> = size of the element,<br>
<i>h</i><sub><i>i</i></sub> = size of the <i>i</i>-th header.
</blockquote>
<p>
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,
the space allocated per element in a manual simulation is
</p>
<blockquote>
<i>S<sub>M</sub></i> = (<i>e</i> + <i>h</i><sub>0</sub>) +
(<i>p</i> + <i>h</i><sub>1</sub>) + ··· +
(<i>p</i> + <i>h</i><sub><i>N</i>-1</sub>) =
<i>S<sub>I</sub></i> + (<i>N</i>-1)<i>p</i>, where<br>
<i>p</i> = size of a pointer.<br>
</blockquote>
<p>
The relative amount of memory taken up by <code>multi_index_container</code>
with respect to its manual simulation is just
<i>S<sub>I</sub></i>&nbsp;/&nbsp;<i>S<sub>M</sub></i>, which can be expressed
then as:
</p>
<blockquote>
<i>S<sub>I</sub></i>&nbsp;/&nbsp;<i>S<sub>M</sub></i> =
<i>S<sub>I</sub></i>&nbsp;/&nbsp;(<i>S<sub>I</sub></i> + (<i>N</i>-1)<i>p</i>).
</blockquote>
<p>
The formula shows that <code>multi_index_container</code> is more efficient
with regard to memory consumption as the number of indices grow.
</p>
<p>
These considerations have overlooked an aspect of the greatest practical
importance: the fact that <code>multi_index_container</code> allocates a single
node per element, compared to the many nodes of different sizes
built by manual simulations, diminishes memory fragmentation, which
can show up in more usable memory available and better performance.
</p>
<h2><a name="time_efficiency">Time efficiency</a></h2>
<p>
From the point of view of computational complexity (i.e. big-O
characterization), <code>multi_index_container</code> and its corresponding manual
simulations are equivalent: inserting an element into
a <code>multi_index_container</code> reduces to a simple combination of
elementary insertion operations on each of the indices, and
similarly for deletion. Hence, the most we can expect is a reduction
(or increase) of execution time by a roughly constant factor. As we
will see later, the reduction can be very significative for
<code>multi_index_container</code>s with two or more indices.
</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.
</p>
<h2><a name="tests">Performance tests</a></h2>
<p>
See <a href="../perf/test_perf.cpp">source code</a> used for measurements.
<p>
In order to assess the efficiency of <code>multi_index_container</code>, the following
basic algorithm
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;...&gt;</span> <span class=identifier>c</span><span class=special>;</span>
<span class=keyword>for</span><span class=special>(</span><span class=keyword>int</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>&lt;</span><span class=identifier>n</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>insert</span><span class=special>(</span><span class=identifier>i</span><span class=special>);</span>
<span class=keyword>for</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>it</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>it</span><span class=special>!=</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>end</span><span class=special>();)</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it</span><span class=special>++);</span>
</pre></blockquote>
<p>
has been measured for different instantiations of <code>multi_index_container</code>
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.
</p>
<p>
The relative memory consumption (i.e. the amount of memory allocated
by a <code>multi_index_container</code> with respect to its manual simulation)
is determined by dividing the size of a <code>multi_index_container</code> node
by the sum of node sizes of all the containers integrating the
simulating data structure.
</p>
<h3><a name="test_1r">Results for 1 ordered index</a></h3>
<p>
The following instantiation of <code>multi_index_container</code> was tested:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
which is functionally equivalent to <code>std::set&lt;int></code>.
</p>
<h4><a name="memory_1r">Memory consumption</a></h4>
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
</tr>
<tr>
<td align="center">100%</td>
<td align="center">100%</td>
<td align="center">100%</td>
</tr>
</table>
<b>Table 1: Relative memory consumption of <code>multi_index_container</code> with 1
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.
</p>
<h4><a name="time_1r">Execution time</a></h4>
<p align="center">
<img src="perf_1o.png" alt="performance of multi_index_container with 1 ordered index"
width="556" height="372"><br>
<b>Fig. 1: Performance of <code>multi_index_container</code> with 1 ordered index.</b>
</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.
</p>
<h3><a name="test_1s">Results for 1 sequenced index</a></h3>
<p>
The following instantiation of <code>multi_index_container</code> was tested:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
which is functionally equivalent to <code>std::list&lt;int></code>.
</p>
<h4><a name="memory_1s">Memory consumption</a></h4>
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
</tr>
<tr>
<td align="center">100%</td>
<td align="center">100%</td>
<td align="center">100%</td>
</tr>
</table>
<b>Table 2: Relative memory consumption of <code>multi_index_container</code> with 1
sequenced 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::list</code> counterpart.
</p>
<h4><a name="time_1s">Execution time</a></h4>
<p align="center">
<img src="perf_1s.png" alt="performance of multi_index_container with 1 sequenced index"
width="556" height="372"><br>
<b>Fig. 2: Performance of <code>multi_index_container</code> with 1 sequenced index.</b>
</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%.
</p>
<h3><a name="test_2r">Results for 2 ordered indices</a></h3>
<p>
The following instantiation of <code>multi_index_container</code> was tested:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<h4><a name="memory_2r">Memory consumption</a></h4>
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
</tr>
<tr>
<td align="center">90%</td>
<td align="center">90%</td>
<td align="center">90%</td>
</tr>
</table>
<b>Table 3: Relative memory consumption of <code>multi_index_container</code> with 2
ordered indices.</b>
</p>
<p>
These results concinde with the theoretical formula for
<i>S<sub>I</sub></i>=36 and <i>p</i>=4.
</p>
<h4><a name="time_2r">Execution time</a></h4>
<p align="center">
<img src="perf_2o.png" alt="performance of multi_index_container with 2 ordered indices"
width="556" height="372"><br>
<b>Fig. 3: Performance of <code>multi_index_container</code> with 2 ordered indices.</b>
</p>
<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.
</p>
<h3><a name="test_1r1s">Results for 1 ordered index + 1 sequenced index</a></h3>
<p>
The following instantiation of <code>multi_index_container</code> was tested:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<h4><a name="memory_1r1s">Memory consumption</a></h4>
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
</tr>
<tr>
<td align="center">87.5%</td>
<td align="center">87.5%</td>
<td align="center">87.5%</td>
</tr>
</table>
<b>Table 4: Relative memory consumption of <code>multi_index_container</code> with 1
ordered index + 1 sequenced index.</b>
</p>
<p>
These results concinde with the theoretical formula for
<i>S<sub>I</sub></i>=28 and <i>p</i>=4.
</p>
<h4><a name="time_1r1s">Execution time</a></h4>
<p align="center">
<img src="perf_1o1s.png"
alt="performance of multi_index_container with 1 ordered index + 1 sequenced index"
width="556" height="372"><br>
<b>Fig. 4: Performance of <code>multi_index_container</code> with 1 ordered index
+ 1 sequenced index.</b>
</p>
<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.
Curiously enough, this speedup gets even higher when
<i>n</i>=10<sup>5</sup> for two of he 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.)
</p>
<h3><a name="test_3r">Results for 3 ordered indices</a></h3>
<p>
The following instantiation of <code>multi_index_container</code> was tested:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<h4><a name="memory_3r">Memory consumption</a></h4>
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
</tr>
<tr>
<td align="center">86.7%</td>
<td align="center">86.7%</td>
<td align="center">86.7%</td>
</tr>
</table>
<b>Table 5: Relative memory consumption of <code>multi_index_container</code> with 3
ordered indices.</b>
</p>
<p>
These results concinde with the theoretical formula for
<i>S<sub>I</sub></i>=52 and <i>p</i>=4.
</p>
<h4><a name="time_3r">Execution time</a></h4>
<p align="center">
<img src="perf_3o.png" alt="performance of multi_index_container with 3 ordered indices"
width="556" height="372"><br>
<b>Fig. 5: Performance of <code>multi_index_container</code> with 3 ordered indices.</b>
</p>
<p>
Execution time for this case is between 55% and 65% lower than achieved with
an STL-based manual simulation of the same data structure.
</p>
<h3><a name="test_2r1s">Results for 2 ordered indices + 1 sequenced index</a></h3>
<p>
The following instantiation of <code>multi_index_container</code> was tested:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<h4><a name="memory_2r1s">Memory consumption</a></h4>
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
</tr>
<tr>
<td align="center">84.6%</td>
<td align="center">84.6%</td>
<td align="center">84.6%</td>
</tr>
</table>
<b>Table 6: Relative memory consumption of <code>multi_index_container</code> with 2
ordered indices + 1 sequenced index.</b>
</p>
<p>
These results concinde with the theoretical formula for
<i>S<sub>I</sub></i>=44 and <i>p</i>=4.
</p>
<h4><a name="time_2r1s">Execution time</a></h4>
<p align="center">
<img src="perf_2o1s.png"
alt="performance of multi_index_container with 2 ordered indices + 1 sequenced index"
width="556" height="372"><br>
<b>Fig. 6: Performance of <code>multi_index_container</code> with 2 ordered indices
+ 1 sequenced index.</b>
</p>
<p>
In accordance to the expectations, execution time is improved by a fairly constant
factor, which ranges from 45% to 55%.
</p>
<h2><a name="conclusions">Conclusions</a></h2>
<p>
We have shown that <code>multi_index_container</code> outperforms, both in space and
time efficiency, equivalent data structures obtained from the manual
combination of STL containers. This improvement gets larger when the number
of indices increase.
</p>
<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.
</p>
<hr>
<div class="prev_link"><a href="compiler_specifics.html"><img src="prev.gif" alt="compiler specifics" border="0"><br>
Compiler specifics
</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="examples.html"><img src="next.gif" alt="examples" border="0"><br>
Examples
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

BIN
doc/prev.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

116
doc/reference/index.html Normal file
View File

@ -0,0 +1,116 @@
<!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 - Reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
</head>
<body>
<h1><img src="../../../../c++boost.gif" alt="c++boost.gif (8819 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
</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="multi_index_container.html"><img src="../next.gif" alt="multi_index_container reference" border="0"><br>
<code>multi_index_container</code> reference
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#header_dependencies">Header dependencies</a></li>
<li><a href="multi_index_container.html">Template class <code>multi_index_container</code></a></li>
<li><a href="indices.html">Index reference</a></li>
<li><a href="ord_indices.html">Ordered indices</a></li>
<li><a href="seq_indices.html">Sequenced indices</a></li>
<li><a href="key_extraction.html">Key Extraction</a></li>
</ul>
<h2><a name="header_dependencies">Header dependencies</a></h2>
<p>
The following dependencies among headers of Boost.MultiIndex hold:
<ul>
<li><a href="multi_index_container.html#synopsis"><code>"boost/multi_index_container.hpp"</code></a>
includes
<ul>
<li><a href="indices.html#index_list_synopsis">
<code>"boost/multi_index/indexed_by.hpp"</code></a>.</li>
</ul>
</li>
<li><a href="ord_indices.html#synopsis">
<code>"boost/multi_index/ordered_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="seq_indices.html#synopsis">
<code>"boost/multi_index/sequenced_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>
<li><a href="key_extraction.html#identity_synopsis">
<code>"boost/multi_index/identity.hpp"</code></a>,</li>
<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>
<li><a href="key_extraction.html#composite_key_synopsis">
<code>"boost/multi_index/composite_key.hpp"</code></a>.</li>
</ul>
</li>
</ul>
So, a program using Boost.MultiIndex must include
<a href="multi_index_container.html#synopsis">
<code>"boost/multi_index_container.hpp"</code></a>,
the headers defining the index types to be used and possibly one or more key
extraction headers for key-based indices. Note that all the key extractors
provided by Boost.MultiIndex are automatically included with
<a href="key_extraction.html#synopsis">
<code>"boost/multi_index/key_extractors.hpp"</code></a>.
</p>
<p>
Boost.MultiIndex is a header-only library, requiring no linking with additional
object modules.
</p>
<hr>
<div class="prev_link"><a href="../advanced_topics.html"><img src="../prev.gif" alt="advanced topics" border="0"><br>
Advanced topics
</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="multi_index_container.html"><img src="../next.gif" alt="multi_index_container reference" border="0"><br>
<code>multi_index_container</code> reference
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

328
doc/reference/indices.html Normal file
View File

@ -0,0 +1,328 @@
<!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 - Index reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
</head>
<body>
<h1><img src="../../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Index reference</h1>
<div class="prev_link"><a href="multi_index_container.html"><img src="../prev.gif" alt="multi_index_container reference" border="0"><br>
<code>multi_index_container</code> reference
</a></div>
<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="ord_indices.html"><img src="../next.gif" alt="ordered indices" border="0"><br>
Ordered indices
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#index_concepts">Index concepts</a></li>
<li><a href="#complexity_signature">Complexity signature</a></li>
<li><a href="#index_specification">Index specification</a></li>
<li><a href="#index_list_synopsis">Header
<code>"boost/multi_index/indexed_by.hpp"</code> synopsis</a>
<ul>
<li><a href="#indexed_by">Template class <code>indexed_by</code></a></li>
</ul>
</li>
<li><a href="#tags">Tags</a></li>
<li><a href="#tag_synopsis">Header
<code>"boost/multi_index/tag.hpp"</code> synopsis</a>
<ul>
<li><a href="#tag">Template class <code>tag</code></a></li>
</ul>
</li>
<li><a href="#index_catalog">Indices provided by Boost.MultiIndex</a>
<ul>
<li><a href="#key_based_indices">Key-based indices</a></li>
<li><a href="#other_indices">Other types</a></li>
</ul>
</li>
</ul>
<h2><a name="index_concepts">Index concepts</a></h2>
<p>
<code>multi_index_container</code> instantiations comprise one or more indices
specified at compile time. Each index allows read/write access to the elements
contained in a definite manner. For instance,
<a href="ord_indices.html">ordered indices</a>
provide a set-like interface to the elements, whereas
<a href="seq_indices.html">sequenced indices</a> mimic the functionality
of <code>std::list</code>.
</p>
<p>
Indices are not isolated objects, and so cannot be constructed on their
own. Rather they are embedded into a <code>multi_index_container</code> as specified by
means of an <a href="#index_specification">index specifier</a>. The name of
the index class implementation proper is never directly exposed to the user, who
has only access to the associated index specifier.
</p>
<p>
Insertion and erasing of elements are always performed through the
appropriate interface of some index of the <code>multi_index_container</code>;
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:
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
that all of them are synchronized. The global operations performed
in a joint manner among the various indices can be reduced to
six primitives:
<ul>
<li>Copying,</li>
<li>insertion of an element,</li>
<li>hinted insertion, where a preexisting element is suggested in
order to improve the efficiency of the operation,</li>
<li>deletion of an element,</li>
<li>replacement of the value of an element,
which may trigger the rearrangement of this element in one or
more indices, or the banning of the replacement,</li>
<li>modification of an element, and its subsequent
rearrangement/banning by the various indices.
</ul>
The last two primitives deserve some further explanation: in order to
guarantee the invariants associated to each index (e.g. some definite
ordering,) elements of a <code>multi_index_container</code> are not mutable.
To overcome this restriction, indices expose member functions
for updating and modifying, which allow for the mutation of elements
in a controlled fasion. Immutability of elements does not significantly
impact the interface of ordered indices, as it is based upon that of
<code>std::set</code> and <code>std:multiset</code>, and these containers
also have non-mutable elements; but it may come as a surprise when dealing
with sequenced indices, which are designed upon the functionality provided
by <code>std::list</code>.
</p>
<p>
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>
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">
<code>Container</code></a> (without the requirement of being
<a href="http://www.sgi.com/tech/stl/Assignable.html">
<code>Assignable</code></a>.)
</p>
<h2><a name="complexity_signature">Complexity signature</a></h2>
<p>
Some member functions of an index interface are implemented by
global primitives from the list above. Complexity of these operations
thus depends on all indices of a given <code>multi_index_container</code>, not just
the currently used index.
</p>
<p>
In order to establish complexity estimates, an index is characterized
by its <i>complexity signature</i>, consisting of the following
associated functions on the number of elements:
<ul>
<li><code>c(n)</code>: copying,
<li><code>i(n)</code>: insertion,
<li><code>h(n)</code>: hinted insertion,
<li><code>d(n)</code>: deletion,
<li><code>r(n)</code>: replacement,
<li><code>m(n)</code>: modifying.
</ul>
</p>
Each function yields the complexity estimate of the contribution of the index
to the corresponding global primitive. Let us consider
an instantiation of <code>multi_index_container</code>
with <code>N</code> indices labelled <code>0</code>,...,<code>N-1</code>
whose complexity signatures are
(<code>c<sub>i</sub></code>,<code>i<sub>i</sub></code>,<code>h<sub>i</sub></code>,<code>d<sub>i</sub></code>,<code>r<sub>i</sub></code>,<code>m<sub>i</sub></code>);
the insertion of an element in such a set is then of complexity
<code>O(I<sub>0</sub>(n)+···+I<sub>N-1</sub>(n))</code> where <code>n</code>
is the number of elements. To abbreviate notation, we adopt the
following definitions:
<ul>
<li><code>C(n)=c<sub>0</sub>(n)+···+c<sub>N-1</sub>(n)</code>,</li>
<li><code>I(n)=i<sub>0</sub>(n)+···+i<sub>N-1</sub>(n)</code>,</li>
<li><code>H(n)=h<sub>0</sub>(n)+···+h<sub>N-1</sub>(n)</code>,</li>
<li><code>D(n)=d<sub>0</sub>(n)+···+d<sub>N-1</sub>(n)</code>,</li>
<li><code>R(n)=r<sub>0</sub>(n)+···+r<sub>N-1</sub>(n)</code>,</li>
<li><code>M(n)=m<sub>0</sub>(n)+···+m<sub>N-1</sub>(n)</code>.</li>
</ul>
For instance, consider a <code>multi_index_container</code> with two ordered indices,
for which <code>i(n)=log(n)</code>, and a sequenced index with <code>i(n)=1</code>
(constant time insertion). Insertion of an element into this <code>multi_index_container</code>
is then of complexity
<blockquote>
<code>O(I(n))=O(2*log(n)+1)=O(log(n))</code>.
</blockquote>
</p>
<h2><a name="index_specification">Index specification</a></h2>
<p>
Index specifiers are passed as instantiation arguments to
<code>multi_index_container</code> and provide the information needed to incorporate
the corresponding indices. Future releases of Boost.MultiIndex may allow for
specification of user-defined indices. Meanwhile, the requirements for an index
specifier remain implementation defined. Currently, Boost.MultiIndex provides the
index specifiers
<a href="ord_indices.html#unique_non_unique"><code>ordered_unique</code> and
<code>ordered_non_unique</code></a> for
<a href="ord_indices.html">ordered indices</a> and
<a href="seq_indices.html#sequenced"><code>sequenced</code></a> for
<a href="seq_indices.html">sequenced indices</a>.
</p>
<h2>
<a name="index_list_synopsis">Header
<a href="../../../../boost/multi_index/indexed_by.hpp">
<code>"boost/multi_index/indexed_by.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>&lt;</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>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>indexed_by</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="indexed_by">Template class <code>indexed_by</code></a></h3>
<p>
<code>indexed_by</code> is a
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> meant to be used to specify a
compile-time list of indices as the <code>IndexSpecifierList</code> of
<code>multi_index_container</code>.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>indexed_by</span><span class=special>;</span>
</pre></blockquote>
<p>
Each user-provided element of <code>indexed_list</code> must be an index
specifier. At least an element must be provided. The maximum number of elements
of an <code>indexed_by</code> sequence is implementation defined.
</p>
<h2><a name="tags">Tags</a></h2>
<p>
Tags are just conventional types used as mnemonics for indices of an
<code>multi_index_container</code>, as for instance in member function <code>get</code>.
Each index can have none, one or more tags associated. The way tags are assigned
to a given index is dependent on the particular index specifier. However,
for convenience all indices of Boost.MultiIndex support tagging through the
class template <a href="#tag"><code>tag</code></a>.
</p>
<h2>
<a name="tag_synopsis">Header
<a href="../../../../boost/multi_index/tag.hpp">
<code>"boost/multi_index/tag.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>&lt;</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>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>tag</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="tag">Template class <code>tag</code></a></h3>
<p>
<code>tag</code> is a typelist construct used to specify a compile-time
sequence of tags to be assigned to an index in instantiation time.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>tag</span><span class=special>;</span>
</pre></blockquote>
<p>
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.
</p>
<h2><a name="index_catalog">Indices provided by Boost.MultiIndex</a></h2>
<h3><a name="key_based_indices">Key-based indices</a></h3>
<p>
Indices of this type are organized around <i>keys</i> obtained from the
elements, as described in the <a href="key_extraction.html">key extraction
reference</a>.
<ul>
<li><a href="ord_indices.html">Ordered indices</a> sort the elements
on the key and provide fast lookup capabilites.</li>
<li>Hashed indices (<b>not currently implemented</b>) offer high
efficiency access through hashing techniques.</li>
</ul>
</p>
<h3><a name="other_indices">Other types</a></h3>
<p>
<ul>
<li><a href="seq_indices.html">Sequenced indices</a> allow to arrange
elements as in a bidirectional list. </li>
</ul>
</p>
<hr>
<div class="prev_link"><a href="multi_index_container.html"><img src="../prev.gif" alt="multi_index_container reference" border="0"><br>
<code>multi_index_container</code> reference
</a></div>
<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="ord_indices.html"><img src="../next.gif" alt="ordered indices" border="0"><br>
Ordered indices
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,831 @@
<!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 - multi_index_container reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
</head>
<body>
<h1><img src="../../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex
<code>multi_index_container</code> reference</h1>
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.MultiIndex reference" border="0"><br>
Boost.MultiIndex reference
</a></div>
<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="indices.html"><img src="../next.gif" alt="index reference" border="0"><br>
Index reference
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#multi_index_container_fwd_synopsis">Header
<code>"boost/multi_index_container_fwd.hpp"</code> synopsis</a></li>
<li><a href="#synopsis">Header
<code>"boost/multi_index_container.hpp"</code> synopsis</a>
<ul>
<li><a href="#multi_index_container">Template class <code>multi_index_container</code></a>
<ul>
<li><a href="#complexity">Complexity</a></li>
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#types">Nested types</a></li>
<li><a href="#nested_templates">Nested class templates</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#index_retrieval">Index retrieval operations</a></li>
<li><a href="#projection">Projection operations</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>
<a name="multi_index_container_fwd_synopsis">Header
<a href="../../../../boost/multi_index_container_fwd.hpp"><code>"boost/multi_index_container_fwd.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>&lt;</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=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>multi_index_container</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index</span>
<span class=keyword>using</span> <span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>multi_index_container</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
<code>multi_index_container_fwd.hpp</code> forward declares the class template
<a href="#multi_index_container"><code>multi_index_container</code></a> and specifies its default parameters.
</p>
<h2>
<a name="synopsis">Header
<a href="../../../../boost/multi_index_container.hpp"><code>"boost/multi_index_container.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>&lt;</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>&gt;</span>
<span class=keyword>class</span> <span class=identifier>multi_index_container</span><span class=special>;</span>
<span class=comment>// multi_index_container associated global class templates:</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</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>&lt;</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>&gt;</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>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index_iterator</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index_const_iterator</span><span class=special>;</span>
<span class=comment>// multi_index_container global functions for index retrieval:</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>int</span> <span class=identifier>N</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span>
<span class=identifier>get</span><span class=special>(</span><span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>m</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>int</span> <span class=identifier>N</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>&gt;</span>
<span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span>
<span class=identifier>get</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>m</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Tag</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span>
<span class=identifier>get</span><span class=special>(</span><span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>m</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Tag</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>&gt;</span>
<span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span>
<span class=identifier>get</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>m</span><span class=special>);</span>
<span class=comment>// multi_index_container global functions for projection of iterators:</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</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=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</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>&lt;</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>&gt;&amp;</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=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</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=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</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>&lt;</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>&gt;&amp;</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=comment>// comparison:</span>
<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Value1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator1</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value2</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList2</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator2</span>
<span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value1</span><span class=special>,</span><span class=identifier>IndexSpecifierList1</span><span class=special>,</span><span class=identifier>Allocator1</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value2</span><span class=special>,</span><span class=identifier>IndexSpecifierList2</span><span class=special>,</span><span class=identifier>Allocator2</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=comment>// specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index</span>
<span class=keyword>using</span> <span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>multi_index_container</span><span class=special>;</span>
<span class=keyword>using</span> <span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>get</span><span class=special>;</span>
<span class=keyword>using</span> <span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>project</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="multi_index_container">
Template class <code>multi_index_container</code>
</a></h3>
<p>
This is the main component of Boost.MultiIndex. A <code>multi_index_container</code>
is a container class template holding a compile-time user-defined list of
<a href="indices.html">indices</a>. These indices provide different interfaces
for the management of the elements of the <code>multi_index_container</code>. By itself,
<code>multi_index_container</code> only provides basic functionality for construction
and for access to the indices held.
</p>
<p>
A <code>multi_index_container</code> type is instantiated with the type of the
elements contained and a non-empty
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> specifying which indices conform the
class.
</p>
<p>
For convenience of use, all public methods and types of the first index
specified are inherited by <code>multi_index_container</code>. This also includes global
operators and functions associated with the index (vg. comparison and
<code>swap</code>.)
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</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=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=keyword>class</span> <span class=identifier>multi_index_container</span>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=comment>// types:</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>ctor_args_list</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>index_specifier_type_list</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>index_type_list</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>iterator_type_list</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>const_iterator_type_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=comment>// nested class templates:</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</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>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</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>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</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=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>&amp;</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>&amp;</span> <span class=identifier>al</span><span class=special>=</span><span class=identifier>allocator_type</span><span class=special>());</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>&gt;</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>
<span class=keyword>const</span> <span class=identifier>ctor_args_list</span><span class=special>&amp;</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>&amp;</span> <span class=identifier>al</span><span class=special>=</span><span class=identifier>allocator_type</span><span class=special>());</span>
<span class=identifier>multi_index_container</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=special>~</span><span class=identifier>multi_index_container</span><span class=special>();</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=keyword>operator</span><span class=special>=(</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>allocator_type</span> <span class=identifier>get_allocator</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// retrieval of indices</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span> <span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span> <span class=identifier>get</span><span class=special>();</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span> <span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span> <span class=identifier>get</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span> <span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span> <span class=identifier>get</span><span class=special>()</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span> <span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span> <span class=identifier>get</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// projection of iterators</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</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>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</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>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</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>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</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=special>};</span>
<span class=comment>// multi_index_container associated global class templates:</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index</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</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</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>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index</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</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</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>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index_iterator</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>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</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>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</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>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</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>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index_iterator</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>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</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>&lt;</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>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index_const_iterator</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>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
<span class=special>};</span>
<span class=comment>// multi_index_container global functions for index retrieval:</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>int</span> <span class=identifier>N</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span>
<span class=identifier>get</span><span class=special>(</span><span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>m</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>get</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;();</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>int</span> <span class=identifier>N</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>&gt;</span>
<span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span>
<span class=identifier>get</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>m</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>get</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;();</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Tag</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span>
<span class=identifier>get</span><span class=special>(</span><span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>m</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>get</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;();</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Tag</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>&gt;</span>
<span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&amp;</span>
<span class=identifier>get</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>m</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>get</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;();</span>
<span class=special>}</span>
<span class=comment>// multi_index_container global functions for projection of iterators:</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</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>&lt;</span><span class=identifier>N</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</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>&lt;</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>&gt;&amp;</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>&lt;</span><span class=identifier>N</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</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>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</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>&lt;</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>&gt;&amp;</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>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=special>}</span>
<span class=comment>// comparison:</span>
<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Value1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator1</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value2</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList2</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator2</span>
<span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value1</span><span class=special>,</span><span class=identifier>IndexSpecifierList1</span><span class=special>,</span><span class=identifier>Allocator1</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value2</span><span class=special>,</span><span class=identifier>IndexSpecifierList2</span><span class=special>,</span><span class=identifier>Allocator2</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>get</span><span class=special>&lt;</span><span class=number>0</span><span class=special>&gt;(</span><span class=identifier>x</span><span class=special>)</span> <b><i>OP</i></b> <span class=identifier>get</span><span class=special>&lt;</span><span class=number>0</span><span class=special>&gt;(</span><span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=comment>// specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</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>&gt;</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</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>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=identifier>x</span><span class=special>.</span><span class=identifier>swap</span><span class=special>(</span><span class=identifier>y</span><span class=special>);</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>
<h4><a name="complexity">Complexity</a></h4>
<p>
In the descriptions of operations of <code>multi_index_container</code>, we adopt the
scheme outlined in the
<a href="indices.html#complexity_signature">complexity signature section</a>.
</p>
<h4><a name="instantiation_types">Instantiation types</a></h4>
<p>
<code>multi_index_container</code> is instantiated with the following types:
<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>
<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/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> of index specifiers. For
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>.
</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
index or in two different indices.
</p>
<h4><a name="types">Nested types</a></h4>
<code>ctor_args_list</code>
<blockquote>
Although the exact definition of <code>ctor_args_list</code> is
implementation defined, from the user point of view this type can be
treated as equivalent to
<code>::boost::tuple&lt;C<sub>0</sub>,...,C<sub>I-1</sub>></code>,
where <code>C<sub>i</sub></code> is the <code>ctor_args</code> type of the
<code>i</code>-th index held by the <code>multi_index_container</code>, in the
same order as they were specified. Strictly speaking, there is an
implicit conversion from
<code>const ::boost::tuple&lt;C<sub>0</sub>,...,C<sub>I-1</sub>>&amp;</code>
to <code>const ctor_args_list&amp;</code>. This type is used for
providing the construction arguments of the indices of the
<code>multi_index_container</code>. <code>ctor_args_list</code> is
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>Default
Constructible</code></a>, provided that all <code>ctor_args</code> types
involved are default constructible.
</blockquote>
<code>index_specifier_type_list</code>
<blockquote>
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> containing the types of the index specifiers
used in the instantiation of the <code>multi_index_container</code>, in the same order as
they were provided.
</blockquote>
<code>index_type_list</code>
<blockquote>
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> containing the types of the indices held by
the <code>multi_index_container</code>, in the same order as they were specified.
</blockquote>
<code>iterator_type_list</code>
<blockquote>
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> containing the types of the iterators of
the indices held by the <code>multi_index_container</code>, in the same order as they were
specified.
</blockquote>
<code>const_iterator_type_list</code>
<blockquote>
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> containing the types of the constant
iterators of the indices held by the <code>multi_index_container</code>, in the same order
as they were specified.
</blockquote>
<h4><a name="nested_templates">Nested class templates</a></h4>
<code>template&lt;int N> struct nth_index</code>
<blockquote>
<code>nth_index&lt;N>::type</code> yields the type of the
<code>N</code>-th (0-based) index held by the <code>multi_index_container</code>, in
the same order as they were specified.<br>
<b>Requires:</b> <code>0 &lt;= N &lt; I</code>.
</blockquote>
<code>template&lt;typename Tag> struct index</code>
<blockquote>
<code>index&lt;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>
<b>Requires:</b> Some index of the <code>multi_index_container</code> has <code>Tag</code>
as an associated tag type.
</blockquote>
<code>template&lt;int N> struct nth_index_iterator</code>
<blockquote>
<code>nth_index_iterator&lt;N>::type</code> is equivalent to
<code>nth_index&lt;N>::type::iterator</code>.<br>
</blockquote>
<code>template&lt;int N> struct nth_index_const_iterator</code>
<blockquote>
<code>nth_index_const_iterator&lt;N>::type</code> is equivalent to
<code>nth_index&lt;N>::type::const_iterator</code>.<br>
</blockquote>
<code>template&lt;typename Tag> struct index_iterator</code>
<blockquote>
<code>index_iterator&lt;Tag>::type</code> is equivalent to
<code>index&lt;Tag>::type::iterator</code>.<br>
</blockquote>
<code>template&lt;typename Tag> struct index_const_iterator</code>
<blockquote>
<code>index_const_iterator&lt;Tag>::type</code> is equivalent to
<code>index&lt;Tag>::type::const_iterator</code>.<br>
</blockquote>
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
<code>explicit multi_index_container(<br>
&nbsp;&nbsp;const ctor_args_list&amp; comp=ctor_args_list(),<br>
&nbsp;&nbsp;const allocator_type&amp; al=allocator_type());</code>
<blockquote>
<b>Effects:</b> Constructs an empty <code>multi_index_container</code> using the
specified argument list and allocator.<br>
<b>Complexity:</b> Constant.
</blockquote>
<code>template&lt;typename InputIterator><br>
multi_index_container(<br>
&nbsp;&nbsp;InputIterator first,InputIterator last,<br>
&nbsp;&nbsp;const ctor_args_list&amp; comp=ctor_args_list(),<br>
&nbsp;&nbsp;const allocator_type&amp; al=allocator_type());</code>
<blockquote>
<b>Requires:</b> <code>InputIterator</code> is a model of
<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>
<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>).
Insertion of each element may or may not succeed depending
on the acceptance by all the indices of the <code>multi_index_container</code>.<br>
<b>Complexity:</b> <code>O(m*H(m))</code>, where <code>m</code> is
the number of elements in [<code>first</code>,<code>last</code>).<br>
</blockquote>
<code>multi_index_container(<br>
&nbsp;&nbsp;const multi_index_container&lt;Value,IndexSpecifierList,Allocator>&amp; x);</code>
<blockquote>
<b>Effects:</b> Constructs a copy of <code>x</code>, copying its
elements as well as its internal objects (key extractors, comparison objects,
allocator.)<br>
<b>Postconditions:</b> <code>*this==x</code>. The order on every index
of the <code>multi_index_container</code> is preserved as well.<br>
<b>Complexity:</b> <code>O(x.size()*log(x.size()) + C(x.size()))</code>.
</blockquote>
<code>~multi_index_container()</code>
<blockquote>
<b>Effects:</b> Destroys the <code>multi_index_container</code> and all the elements
contained. The order in which the elements are destroyed is not specified.<br>
<b>Complexity:</b> <code>O(n*D(n))</code>.
</blockquote>
<code>multi_index_container&lt;Value,IndexSpecifierList,Allocator>&amp; operator=(<br>
&nbsp;&nbsp;const multi_index_container&lt;Value,IndexSpecifierList,Allocator>&amp; x);</code>
<blockquote>
Replaces the elements and internal objects of the <code>multi_index_container</code>
with copies from <code>x</code>.<br>
<b>Postconditions:</b> <code>*this==x</code>. The order on every index
of the <code>multi_index_container</code> is preserved as well.<br>
<b>Returns:</b> <code>*this</code>.<br>
<b>Complexity:</b> <code>O(n*D(n) + x.size()*log(x.size()) +
C(x.size()))</code>.<br>
<b>Exception safety:</b> Strong, provided the copy and assignment operations
of the types of <code>ctor_args_list</code> do not throw.
</blockquote>
<code>allocator_type get_allocator()const;</code>
<blockquote>
Returns a copy of the <code>allocator_type</code> object used to construct
the <code>multi_index_container</code>.<br>
<b>Complexity:</b> Constant.
</blockquote>
<h4><a name="index_retrieval">Index retrieval operations</a></h4>
<code>template&lt;int N> typename nth_index&lt;N>::type&amp; get();</code>
<blockquote>
<b>Requires:</b> <code>0 &lt;= N &lt; I</code>.<br>
<b>Effects:</b> Returns a reference to the
<code>nth_index&lt;N>::type</code> index held by <code>*this</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>template&lt;int N> const typename nth_index&lt;N>::type&amp; get()const;</code>
<blockquote>
<b>Requires:</b> <code>0 &lt;= N &lt; I</code>.<br>
<b>Effects:</b> Returns a <code>const</code> reference to the
<code>nth_index&lt;N>::type</code> index held by <code>*this</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>template&lt;typename Tag> typename index&lt;Tag>::type&amp; get()</code>
<blockquote>
<b>Requires:</b> <code>Tag</code> is such that <code>index&lt;Tag>::type</code>
is valid.<br>
<b>Effects:</b> Returns a reference to the
<code>index&lt;Tag>::type</code> index held by
<code>*this</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>template&lt;typename Tag> const typename index&lt;Tag>::type&amp; get()const;</code>
<blockquote>
<b>Requires:</b> <code>Tag</code> is such that <code>index&lt;Tag>::type</code>
is valid.<br>
<b>Effects:</b> Returns a <code>const</code> reference to the
<code>index&lt;Tag>::type</code> index held by
<code>*this</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<h4><a name="projection">Projection operations</a></h4>
<p>
Given a <code>multi_index_container</code> with indices <code>i1</code>
and <code>i2</code>, we say than an <code>i1</code>-iterator
<code>it1</code> and an <code>i2</code>-iterator <code>it2</code>
are <i>equivalent</i> if:
<ul>
<li> <code>it1==i1.end()</code> AND <code>it2==i2.end()</code>,</li>
<li> OR <code>it1</code> and <code>it2</code> point to the
same element.</li>
</ul>
</p>
<code>template&lt;int N,typename IteratorType><br>
typename nth_index_iterator&lt;N>::type project(IteratorType it);</code>
<blockquote>
<b>Requires:</b> <code>0 &lt;= N &lt; 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&lt;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&lt;int N,typename IteratorType><br>
typename nth_index_const_iterator&lt;N>::type project(IteratorType it)const;</code>
<blockquote>
<b>Requires:</b> <code>0 &lt;= N &lt; I</code>. <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>nth_index_const_iterator&lt;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&lt;typename Tag,typename IteratorType><br>
typename index_iterator&lt;Tag>::type project(IteratorType it);</code>
<blockquote>
<b>Requires:</b> <code>Tag</code> is such that
<code>index_iterator&lt;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&lt;Tag>::type</code> iterator
equivalent to <code>it</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>template&lt;typename Tag,typename IteratorType><br>
typename index_const_iterator&lt;Tag>::type project(IteratorType it)const;</code>
<blockquote>
<b>Requires:</b> <code>Tag</code> is such that
<code>index_const_iterator&lt;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&lt;Tag>::type</code>
iterator equivalent to <code>it</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<hr>
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.MultiIndex reference" border="0"><br>
Boost.MultiIndex reference
</a></div>
<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="indices.html"><img src="../next.gif" alt="index reference" border="0"><br>
Index reference
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

View File

@ -0,0 +1,909 @@
<!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 - Ordered indices reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
</head>
<body>
<h1><img src="../../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Ordered indices reference</h1>
<div class="prev_link"><a href="indices.html"><img src="../prev.gif" alt="index reference" border="0"><br>
Index reference
</a></div>
<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="seq_indices.html"><img src="../next.gif" alt="sequenced indices" border="0"><br>
Sequenced indices
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#ord_index_fwd_synopsis">Header
<code>"boost/multi_index/ordered_index_fwd.hpp"</code> synopsis</a></li>
<li><a href="#synopsis">Header
<code>"boost/multi_index/ordered_index.hpp"</code> synopsis</a>
<ul>
<li><a href="#unique_non_unique">
Index specifiers <code>ordered_unique</code> and <code>ordered_non_unique</code>
</a></li>
<li><a href="#ord_indices">Ordered indices</a>
<ul>
<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="#modifiers">Modifiers</a></li>
<li><a href="#observers">Observers</a></li>
<li><a href="#set_operations">Set operations</a></li>
<li><a href="#range_operations">Range operations</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>
<a name="ord_index_fwd_synopsis">Header
<a href="../../../../boost/multi_index/ordered_index_fwd.hpp">
<code>"boost/multi_index/ordered_index_fwd.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=comment>// index specifiers unique and ordered_non_unique</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult ordered_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>ordered_unique</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult ordered_non_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>ordered_non_unique</span><span class=special>;</span>
<span class=comment>// indices</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span> <span class=keyword>class</span> <b>index name is implementation defined</b><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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>
<p>
<code>index_fwd.hpp</code> provides forward declarations for index specifiers
<a href="#unique_non_unique"><code>ordered_unique</code> and <code>ordered_non_unique</code></a> and
their associated <a href="#ord_indices">ordered index</a> classes.
</p>
<h2>
<a name="synopsis">Header
<a href="../../../../boost/multi_index/ordered_index.hpp">
<code>"boost/multi_index/ordered_index.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=comment>// index specifiers unique and ordered_non_unique</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult ordered_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>ordered_unique</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult ordered_non_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>ordered_non_unique</span><span class=special>;</span>
<span class=comment>// indices</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span> <span class=keyword>class</span> <b>index class name implementation defined</b><span class=special>;</span>
<span class=comment>// index comparison:</span>
<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=comment>// index specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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="unique_non_unique">
Index specifiers <code>ordered_unique</code> and <code>ordered_non_unique</code>
</a></h3>
<p>
These <a href="indices.html#index_specification">index specifiers</a> allow
for insertion of <a href="#ord_indices">ordered indices</a> without and with
allowance of duplicate elements, respectively. The syntax of <code>ordered_unique</code>
and <code>ordered_non_unique</code> coincide, thus we describe them in a grouped manner.
<code>ordered_unique</code> and <code>ordered_non_unique</code> can be instantiated in
two different forms, according to whether a tag list for the index is provided or not:
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>KeyFromValue</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=special>(</span><span class=identifier>ordered_unique</span> <span class=special>|</span> <span class=identifier>ordered_non_unique</span><span class=special>)</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>KeyFromValue</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=special>(</span><span class=identifier>ordered_unique</span> <span class=special>|</span> <span class=identifier>ordered_non_unique</span><span class=special>)</span><span class=special>;</span>
</pre></blockquote>
<p>
If provided, <code>TagList</code> must be an instantiation of the class template
<a href="#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.
</p>
<h3><a name="ord_indices">Ordered indices</a></h3>
<p>
An ordered index provides a set-like interface to the underlying heap of
elements contained in a <code>multi_index_container</code>. An ordered index is
particularized according to a given
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
that retrieves keys from elements of <code>multi_index_container</code> and a comparison
predicate.
</p>
<p>
There are two variants of ordered indices: <i>unique</i>, which do
not allow duplicate elements (with respect to its associated comparison
predicate) and <i>non-unique</i>, which accept those duplicates.
The interface of these two variants is the same, so they are documented
together, with minor differences explicitly stated when they exist.
</p>
<p>
Except where noted, ordered indices (both unique and non-unique) are models of
<a href="http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">
<code>Sorted Associative Container</code></a> and
<a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">
<code>Unique Associative Container</code></a>, much as <code>std::set</code>s
are. Accordingly, validity of iterators and references to elements is
preserved. We only provide descriptions 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>
<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=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>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined: dependent on types Value, Allocator,
TagList, KeyFromValue, Compare</b><span class=special>&gt;</span>
<span class=keyword>class</span> <b>name is implementation defined</b>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=comment>// types:</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span> <span class=identifier>key_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>Value</span> <span class=identifier>value_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>KeyFromValue</span> <span class=identifier>key_from_value</span><span class=special>;</span>
<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>&lt;</span><span class=identifier>key_from_value</span><span class=special>,</span><span class=identifier>key_compare</span><span class=special>&gt;</span> <span class=identifier>ctor_args</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>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>const_iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>size_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>difference_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>
<span class=keyword>typedef</span> <b>equivalent to
std::reverse_iterator&lt;iterator&gt;</b> <span class=identifier>reverse_iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>equivalent to
std::reverse_iterator&lt;const_iterator&gt;</b> <span class=identifier>const_reverse_iterator</span><span class=special>;</span>
<span class=comment>// construct/copy/destroy:</span>
<b>index class name</b><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>allocator_type</span> <span class=identifier>get_allocator</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// iterators:</span>
<span class=identifier>iterator</span> <span class=identifier>begin</span><span class=special>();</span>
<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>reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>();</span>
<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=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>
<span class=identifier>size_type</span> <span class=identifier>size</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>size_type</span> <span class=identifier>max_size</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>&lt;</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>iterator</span> <span class=identifier>insert</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>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>&gt;</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>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>&amp;</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=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>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</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>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</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>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
<span class=comment>// observers:</span>
<span class=identifier>key_from_value</span> <span class=identifier>key_extractor</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>key_compare</span> <span class=identifier>key_comp</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>value_compare</span> <span class=identifier>value_comp</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// set operations:</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>find</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>find</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>size_type</span> <span class=identifier>count</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>size_type</span> <span class=identifier>count</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>lower_bound</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>lower_bound</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>upper_bound</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>upper_bound</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>&gt;</span> <span class=identifier>equal_range</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>&gt;</span> <span class=identifier>equal_range</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// range:</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>LowerBounder</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>UpperBounder</span><span class=special>&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>&gt;</span> <span class=identifier>range</span><span class=special>(</span>
<span class=identifier>LowerBounder</span> <span class=identifier>lower</span><span class=special>,</span><span class=identifier>UpperBounder</span> <span class=identifier>upper</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
<span class=comment>// index comparison:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>==(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>x</span><span class=special>.</span><span class=identifier>size</span><span class=special>()==</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>size</span><span class=special>()&amp;&amp;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>equal</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>begin</span><span class=special>());</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>lexicographical_compare</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>!=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</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>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&gt;(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>y</span><span class=special>&lt;</span><span class=identifier>x</span><span class=special>;</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&gt;=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>!(</span><span class=identifier>x</span><span class=special>&lt;</span><span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>!(</span><span class=identifier>x</span><span class=special>&gt;</span><span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=comment>// index specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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>
<h4><a name="complexity_signature">Complexity signature</a></h4>
<p>
Here and in the descriptions of operations of ordered indices, we adopt the
scheme outlined in the
<a href="indices.html#complexity_signature">complexity signature
section</a>. The complexity signature of ordered indices is:
<ul>
<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>
<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
change, <code>m(n)=log(n)</code> otherwise.</li>
</ul>
</p>
<h4><a name="instantiation_types">Instantiation types</a></h4>
<p>Ordered indices are instantiated internally to <code>multi_index_container</code> and
specified by means of <a href="indices.html#indexed_by"><code>indexed_by</code></a>
with <a href="#unique_non_unique"> index specifiers <code>ordered_unique</code>
and <code>ordered_non_unique</code></a>. 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>KeyFromValue</code> from the index specifier,</li>
<li><code>Compare</code> from the index specifier.</li>
</ul>
<code>TagList</code> must be an instantiation of
<a href="indices.html#tag"><code>tag</code></a>. The type <code>KeyFromValue</code>,
which determines the mechanism for extracting a key from <code>Value</code>,
must be a model of <a href="key_extraction.html#key_extractors">
<code>Key Extractor</code></a> from <code>Value</code>. <code>Compare</code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> on elements of
<code>KeyFromValue::result_type</code>.
</p>
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
<p>
As explained in the <a href="indices.html#index_concepts">index
concepts section</a>, indices do not have public constructors or destructors.
Assignment, on the other hand, is provided.
</p>
<code><b>index class name</b>&amp; operator=(const <b>index class name</b>&amp; x);</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>a</span><span class=special>=</span><span class=identifier>b</span><span class=special>;</span>
</pre></blockquote>
where <code>a</code> and <code>b</code> are the <code>multi_index_container</code>
objects to which <code>*this</code> and <code>x</code> belongs, respectively.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>std::pair&lt;iterator,bool> insert(const value_type&amp; x);</code>
<blockquote>
<b>Effects:</b> Inserts <code>x</code> into the <code>multi_index_container</code> to which
the index belongs if
<ul>
<li>the index is non-unique OR no other element exists with
equivalent key,</li>
<li>AND insertion is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
<b>Returns:</b> The return value is a pair <code>p</code>. <code>p.second</code>
is <code>true</code> if and only if insertion took place. On successful insertion,
<code>p.first</code> points to the element inserted; otherwise, <code>p.first</code>
points to an element that caused the insertion to be banned. Note that more than
one element can be causing insertion not to be allowed.<br>
<b>Complexity:</b> <code>O(I(n))</code>.<br>
<b>Exception safety:</b> Strong.<br>
</blockquote>
<code>iterator insert(iterator position,const value_type&amp; x);</code>
<blockquote>
<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>
<li>the index is non-unique OR no other element exists with
equivalent key,</li>
<li>AND insertion is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
<code>position</code> is used as a hint to improve the efficiency of the
operation.<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
allowed.<br>
<b>Complexity:</b> <code>O(H(n))</code>.<br>
<b>Exception safety:</b> Strong.<br>
</blockquote>
<code>template&lt;typename InputIterator><br>
void insert(InputIterator first,InputIterator last);</code>
<blockquote>
<b>Requires:</b> <code>InputIterator</code> is a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
<code>Input Iterator</code></a> over elements of type
<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>
<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>
<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>hint</span><span class=special>=</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>hint</span><span class=special>,*</span><span class=identifier>first</span><span class=special>++);</span>
</pre></blockquote>
<b>Complexity:</b> <code>O(m*H(n+m))</code>, where
<code>m</code> is the number of elements in [<code>first</code>,
<code>last</code>).<br>
<b>Exception safety:</b> Basic.<br>
</blockquote>
<code>void erase(iterator position);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
of the index.</br>
<b>Effects:</b> Deletes the element pointed to by <code>position</code>.<br>
<b>Complexity:</b> <code>O(D(n))</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<code>size_type erase(const key_type&amp; x);</code>
<blockquote>
<b>Effects:</b> Deletes the elements with key equivalent to <code>x</code>.<br>
<b>Returns:</b> Number of elements deleted.<br>
<b>Complexity:</b> <code>O(log(n) + m*D(n))</code>, where <code>m</code> is
the number of elements deleted.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<code>void 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>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>
</blockquote>
<a name="replace"><code>bool replace(iterator position,const value_type&amp; x);</code></a>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
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>
<ul>
<li>the index is non-unique OR no other element exists
(except possibly <code>*position</code>) with equivalent key,</li>
<li>AND replacing is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
<b>Postconditions:</b> Validity of <code>position</code> is preserved
in all cases.<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>
<b>Exception safety:</b> Strong. If an exception is thrown by some
user-provided operation the <code>multi_index_container</code> to which the index
belongs remains in its original state.
</blockquote>
<a name="modify">
<code>template&lt;typename Modifier> bool modify(iterator position,Modifier mod);</code></a>
<blockquote>
<b>Requires:</b> <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>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
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
<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.
</blockquote>
<a name="modify_key">
<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
<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> 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&amp;</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.
</blockquote>
<h4><a name="observers">Observers</a></h4>
<p>Apart from standard <code>key_comp</code> and <code>value_comp</code>,
ordered indices have a member function for retrieving the internal key extractor
used.
</p>
<code>key_from_value key_extractor()const;</code>
<blockquote>
Returns a copy of the <code>key_from_value</code> object used to construct
the index.<br>
<b>Complexity:</b> Constant.
</blockquote>
<h4><a name="set_operations">Set operations</a></h4>
<p>
Ordered indices provide the full lookup functionality required by
<a href="http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">
<code>Sorted Associative Containers</code></a> and
<a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">
<code>Unique Associative Containers</code></a>, namely <code>find</code>,
<code>count</code>, <code>lower_bound</code>, <code>upper_bound</code>
and <code>equal_range</code>. Additionally, these member functions are
templatized to allow for non-standard arguments, so extending
the types of search operations allowed. The kind of arguments permissible
when invoking the lookup member functions is defined by the following
concept.
</p>
<p>
Consider a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> <code>Compare</code> over values
of type <code>Key</code>. A pair of types (<code>CompatibleKey</code>,
<code>CompatibleCompare</code>) is said to be a <i>compatible extension</i>
of <code>Compare</code> if
<ol>
<li><code>CompatibleCompare</code> is a
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">
<code>Binary Predicate</code></a> over (<code>Key</code>,
<code>CompatibleKey</code>),</li>
<li><code>CompatibleCompare</code> is a
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">
<code>Binary Predicate</code></a> over (<code>CompatibleKey</code>,
<code>Key</code>),</li>
<li>if <code>c_comp(ck,k1)</code> then <code>!c_comp(k1,ck)</code>,</li>
<li>if <code>!c_comp(ck,k1)</code> and <code>!comp(k1,k2)</code> then
<code>!c_comp(ck,k2)</code>,</li>
<li>if <code>!c_comp(k1,ck)</code> and <code>!comp(k2,k1)</code> then
<code>!c_comp(k2,ck)</code>,</li>
</ol>
for every <code>c_comp</code> of type <code>CompatibleCompare</code>,
<code>comp</code> of type <code>Compare</code>, <code>ck</code> of type
<code>CompatibleKey</code> and <code>k1</code>, <code>k2</code> of type
<code>Key</code>.
</p>
<p>Additionally, a type <code>CompatibleKey</code> is said to be a
<i>compatible key</i> of <code>Compare</code> if (<code>CompatibleKey</code>,
<code>Compare</code>) is a compatible extension of <code>Compare</code>.
This implies that <code>Compare</code>, as well as being a strict
weak ordering, accepts arguments of type <code>CompatibleKey</code>,
which usually means it has several overloads of <code>operator()</code>.
</p>
<p>
In the context of a compatible extension or a compatible key, the expressions
"equivalent", "less than" and "greater than" take on their obvious
interpretations.
</p>
<code>template&lt;typename CompatibleKey> const_iterator find(const CompatibleKey&amp; x)const;
</code>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key 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>
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
const_iterator find(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
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>
</blockquote>
<code>template&lt;typename CompatibleKey> size_type<br>
count(const CompatibleKey&amp; x)const;
</code>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key 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))</code>.<br>
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
size_type count(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
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>
<code>template&lt;typename CompatibleKey><br>
const_iterator lower_bound(const CompatibleKey&amp; x)const;
</code>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key 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>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
const_iterator lower_bound(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
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>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
</blockquote>
<code>template&lt;typename CompatibleKey><br>
const_iterator upper_bound(const CompatibleKey&amp; x)const;
</code>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key 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>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
const_iterator upper_bound(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
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>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
</blockquote>
<code>template&lt;typename CompatibleKey><br>
std::pair&lt;const_iterator,const_iterator> equal_range(<br>
&nbsp;&nbsp;const CompatibleKey&amp; x)const;
</code>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
<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&lt;typename CompatibleKey,typename CompatibleCompare><br>
std::pair&lt;const_iterator,const_iterator> equal_range(</br>
&nbsp;&nbsp;const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
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>
</blockquote>
<h4><a name="range_operations">Range operations</a></h4>
<p>
The member function <code>range</code> is not defined for sorted associative
containers, but ordered indices provide it as a convenient utility. A range
or interval is defined by two conditions for the lower and upper bounds, which
are modeled after the following concepts.
</p>
<p>
Consider a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> <code>Compare</code> over values
of type <code>Key</code>. A type <code>LowerBounder</code> is said to be
a <i>lower bounder</i> of <code>Compare</code> if
<ol>
<li><code>LowerBounder</code> is a
<a href="http://www.sgi.com/tech/stl/Predicate.html">
<code>Predicate</code></a> over <code>Key</code>,</li>
<li>if <code>lower(k1)</code> and <code>!comp(k2,k1)</code> then
<code>lower(k2)</code>,</li>
</ol>
for every <code>lower</code> of type <code>LowerBounder</code>,
<code>comp</code> of type <code>Compare</code>, and <code>k1</code>,
<code>k2</code> of type <code>Key</code>. Similarly, an <i>upper bounder</i>
is a type <code>UpperBounder</code> such that
<ol>
<li><code>UpperBounder</code> is a
<a href="http://www.sgi.com/tech/stl/Predicate.html">
<code>Predicate</code></a> over <code>Key</code>,</li>
<li>if <code>upper(k1)</code> and <code>!comp(k1,k2)</code> then
<code>upper(k2)</code>,</li>
</ol>
for every <code>upper</code> of type <code>UpperBounder</code>,
<code>comp</code> of type <code>Compare</code>, and <code>k1</code>,
<code>k2</code> of type <code>Key</code>.
</p>
<code>template&lt;typename LowerBounder,typename UpperBounder><br>
std::pair&lt;const_iterator,const_iterator> range(<br>
&nbsp;&nbsp;LowerBounder lower,UpperBounder upper)const;
</code>
<blockquote>
<b>Requires:</b> <code>LowerBounder</code> and <code>UpperBounder</code> are
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
both point to the first element satisfying <code>lower</code>, or else
are equal to <code>end()</code> if this latter element does not exist.<br>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
<b>Variants:</b> In place of <code>lower</code> or <code>upper</code> (or both),
the singular value <code>boost::multi_index::unbounded</code> can be
provided. This acts as a predicate which all values of type <code>key_type</code>
satisfy.<br>
</blockquote>
<hr>
<div class="prev_link"><a href="indices.html"><img src="../prev.gif" alt="index reference" border="0"><br>
Index reference
</a></div>
<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="seq_indices.html"><img src="../next.gif" alt="sequenced indices" border="0"><br>
Sequenced indices
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

View File

@ -0,0 +1,837 @@
<!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 - Sequenced indices reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
</head>
<body>
<h1><img src="../../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Sequenced indices reference</h1>
<div class="prev_link"><a href="ord_indices.html"><img src="../prev.gif" alt="ordered indices" border="0"><br>
Ordered 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
</a></div>
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key extraction" border="0"><br>
Key extraction
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#seq_index_fwd_synopsis">Header
<code>"boost/multi_index/sequenced_index_fwd.hpp"</code> synopsis</a></li>
<li><a href="#synopsis">Header
<code>"boost/multi_index/sequenced_index.hpp"</code> synopsis</a>
<ul>
<li><a href="#sequenced"><code>sequenced</code> index specifier</a></li>
<li><a href="#seq_indices">Sequenced indices</a>
<ul>
<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="#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>
</ul>
</li>
</ul>
</li>
</ul>
<h2>
<a name="seq_index_fwd_synopsis">Header
<a href="../../../../boost/multi_index/sequenced_index_fwd.hpp">
<code>"boost/multi_index/sequenced_index_fwd.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=comment>// sequenced index specifier</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>sequenced</span><span class=special>;</span>
<span class=comment>// indices</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span> <span class=keyword>class</span> <b>index class name implementation defined</b><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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>
<p>
<code>sequenced_index_fwd.hpp</code> provides forward declarations for the
<a href="#sequenced"><code>sequenced</code></a> index specifier and
its associated <a href="#seq_indices">sequenced index</a> class.
</p>
<h2>
<a name="synopsis">Header
<a href="../../../../boost/multi_index/sequenced_index.hpp">
<code>"boost/multi_index/sequenced_index.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=comment>// sequenced index specifier</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>sequenced</span><span class=special>;</span>
<span class=comment>// indices</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span> <span class=keyword>class</span> <b>index class name implementation defined</b><span class=special>;</span>
<span class=comment>// index comparison:</span>
<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=comment>// index specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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="sequenced">
<code>sequenced</code> index specifier
</a></h3>
<p>
This index specifier allows for insertion of a <a href="#seq_indices">sequenced
index</a>.</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>sequenced</span><span class=special>;</span>
</pre></blockquote>
<p>If provided, <code>TagList</code> must be an instantiation of
<a href="indices.html#tag"><code>tag</code></a>.
</p>
<h3><a name="seq_indices">Sequenced indices</a></h3>
<p>
Sequenced indices are modeled after the semantics of a bidirectional list
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.
</p>
<p>
There are a number of differences with respect to <code>std::lists</code>:
<ul>
<li>Sequenced indices are not <a href="http://www.sgi.com/tech/stl/Assignable.html">
<code>Assignable</code></a> (like any other index.)</li>
<li>Unlike as in <code>std::list</code>, insertions into a sequenced index
may fail due to clashings with other indices. This alters the semantics
of the operations provided with respect to their analogues in
<code>std::list</code>.
</li>
<li>Elements in a sequenced index are not mutable, and can only be changed
by means of <a href="#replace"><code>replace</code></a> and
<a href="#modify"><code>modify</code></a> member functions.
</li>
</ul>
Having these restrictions into account, sequenced indices are models
of <a href="http://www.sgi.com/tech/stl/ReversibleContainer.html">
<code>Reversible Container</code></a>,
<a href="http://www.sgi.com/tech/stl/FrontInsertionSequence.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
concepts modeled or do not exactly conform to the requirements for these
types of containers.
</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>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined: dependent on types Value, Allocator, TagList</b><span class=special>&gt;</span>
<span class=keyword>class</span> <b>name is implementation defined</b>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=comment>// types:</span>
<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=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>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>const_iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>size_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>ptrdiff_t</span> <span class=identifier>difference_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>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_type</span><span class=special>::</span><span class=identifier>const_pointer</span> <span class=identifier>const_pointer</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>equivalent to
std::reverse_iterator&lt;iterator&gt;</b> <span class=identifier>reverse_iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>equivalent to
std::reverse_iterator&lt;const_iterator&gt;</b> <span class=identifier>const_reverse_iterator</span><span class=special>;</span>
<span class=comment>// construct/copy/destroy:</span>
<b>index class name</b><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span> <span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>InputIterator</span><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>assign</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>assign</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=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>value</span><span class=special>);</span>
<span class=identifier>allocator_type</span> <span class=identifier>get_allocator</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// iterators:</span>
<span class=identifier>iterator</span> <span class=identifier>begin</span><span class=special>();</span>
<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>reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>();</span>
<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=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>
<span class=identifier>size_type</span> <span class=identifier>size</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>size_type</span> <span class=identifier>max_size</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>void</span> <span class=identifier>resize</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=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>=</span><span class=identifier>value_type</span><span class=special>());</span>
<span class=comment>// access:</span>
<span class=identifier>const_reference</span> <span class=identifier>front</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reference</span> <span class=identifier>back</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>&lt;</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>push_front</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>pop_front</span><span class=special>();</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>push_back</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>pop_back</span><span class=special>();</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>insert</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>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>insert</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>n</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>insert</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</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=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=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>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</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>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
<span class=comment>// list operations:</span>
<span class=keyword>void</span> <span class=identifier>splice</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>splice</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</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>splice</span><span class=special>(</span>
<span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</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>void</span> <span class=identifier>remove</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>value</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Predicate</span><span class=special>&gt;</span> <span class=keyword>void</span> <span class=identifier>remove_if</span><span class=special>(</span><span class=identifier>Predicate</span> <span class=identifier>pred</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>ordered_unique</span><span class=special>();</span>
<span class=keyword>template</span> <span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>BinaryPredicate</span><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>ordered_unique</span><span class=special>(</span><span class=identifier>BinaryPredicate</span> <span class=identifier>binary_pred</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>merge</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span> <span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>&gt;</span> <span class=keyword>void</span> <span class=identifier>merge</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=identifier>Compare</span> <span class=identifier>comp</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>sort</span><span class=special>();</span>
<span class=keyword>template</span> <span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>&gt;</span> <span class=keyword>void</span> <span class=identifier>sort</span><span class=special>(</span><span class=identifier>Compare</span> <span class=identifier>comp</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>reverse</span><span class=special>();</span>
<span class=comment>// relocate 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=special>}</span>
<span class=comment>// index comparison:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>==(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>x</span><span class=special>.</span><span class=identifier>size</span><span class=special>()==</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>size</span><span class=special>()&amp;&amp;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>equal</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>begin</span><span class=special>());</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>lexicographical_compare</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>!=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</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>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&gt;(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span>
<span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>y</span><span class=special>&lt;</span><span class=identifier>x</span><span class=special>;</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&gt;=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>!(</span><span class=identifier>x</span><span class=special>&lt;</span><span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>!(</span><span class=identifier>x</span><span class=special>&gt;</span><span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=comment>// index specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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>
<h4><a name="complexity_signature">Complexity signature</a></h4>
<p>
Here and in the descriptions of operations of sequenced indices, we adopt the
scheme outlined in the
<a href="indices.html#complexity_signature">complexity signature
section</a>. The complexity signature of sequenced indices is:
<ul>
<li>copying: <code>c(n)=n*log(n)</code>,</li>
<li>insertion: <code>i(n)=1</code> (constant),</li>
<li>hinted insertion: <code>h(n)=1</code> (constant),</li>
<li>deletion: <code>d(n)=1</code> (constant),</li>
<li>replacement: <code>r(n)=1</code> (constant),</li>
<li>modifying: <code>m(n)=1</code> (constant).</li>
</ul>
</p>
<h4><a name="instantiation_types">Instantiation types</a></h4>
<p>Sequenced indices are instantiated internally to <code>multi_index_container</code>
and specified by means of <a href="indices.html#indexed_by">
<code>indexed_by</code></a> with the <a href="#sequenced"><code>sequenced</code></a>
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>
</ul>
<code>TagList</code> must be an instantiation of
<a href="indices.html#tag"><code>tag</code></a>.
</p>
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
<p>
As explained in the <a href="indices.html#index_concepts">index
concepts section</a>, indices do not have public constructors or destructors.
Assignment, on the other hand, is provided.
</p>
<code><b>index class name</b>&amp; operator=(const <b>index class name</b>&amp; x);</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>a</span><span class=special>=</span><span class=identifier>b</span><span class=special>;</span>
</pre></blockquote>
where <code>a</code> and <code>b</code> are the <code>multi_index_container</code>
objects to which <code>*this</code> and <code>x</code> belongs, respectively.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<code>template &lt;class InputIterator><br>
void assign(InputIterator first,InputIterator last);</code>
<blockquote>
<b>Requires:</b> <code>InputIterator</code> is a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
<code>Input Iterator</code></a> over elements of type
<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>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>clear</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>first</span><span class=special>,</span><span class=identifier>last</span><span class=special>);</span>
</pre></blockquote>
</blockquote>
<code>void assign(size_type n,const value_type&amp; value);</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>clear</span><span class=special>();</span>
<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>&lt;</span><span class=identifier>n</span><span class=special>;++</span><span class=identifier>n</span><span class=special>)</span><span class=identifier>push_back</span><span class=special>(</span><span class=identifier>v</span><span class=special>);</span>
</pre></blockquote>
</blockquote>
<h4><a name="capacity">Capacity operations</a></h4>
<code>void resize(size_type n,const value_type&amp; x=value_type());</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=keyword>if</span><span class=special>(</span><span class=identifier>n</span><span class=special>&gt;</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>&lt;</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>
</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.)
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>std::pair&lt;iterator,bool> push_front(const value_type&amp; x);</code>
<blockquote>
<b>Effects:</b> Inserts <code>x</code> at the beginning of the sequence if
no other index of the <code>multi_index_container</code> bans the insertion.<br>
<b>Returns:</b> The return value is a pair <code>p</code>. <code>p.second</code>
is <code>true</code> if and only if insertion took place. On successful
insertion, <code>p.first</code> points to the element inserted; otherwise,
<code>p.first</code> points to an element that caused the insertion to be banned.
Note that more than one element can be causing insertion not to be allowed.<br>
<b>Complexity:</b> <code>O(I(n))</code>.<br>
<b>Exception safety:</b> Strong.
</blockquote>
<code>std::pair&lt;iterator,bool> push_back(const value_type&amp; x);</code>
<blockquote>
<b>Effects:</b> Inserts <code>x</code> at the end of the sequence if
no other index of the <code>multi_index_container</code> bans the insertion.<br>
<b>Returns:</b> The return value is a pair <code>p</code>. <code>p.second</code>
is <code>true</code> if and only if insertion took place. On successful
insertion, <code>p.first</code> points to the element inserted; otherwise,
<code>p.first</code> points to an element that caused the insertion to be banned.
Note that more than one element can be causing insertion not to be allowed.<br>
<b>Complexity:</b> <code>O(I(n))</code>.<br>
<b>Exception safety:</b> Strong.
</blockquote>
<code>iterator insert(iterator position,const value_type&amp; x);</code>
<blockquote>
<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> 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
allowed.<br>
<b>Complexity:</b> <code>O(I(n))</code>.<br>
<b>Exception safety:</b> Strong.
</blockquote>
<code>void insert(iterator position,size_type n,const value_type&amp; x);</code>
<blockquote>
<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>&lt;</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>
</pre></blockquote>
</blockquote>
<code>template&lt;typename InputIterator><br>
void insert(iterator position,InputIterator first,InputIterator last);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>InputIterator</code> is a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
<code>Input Iterator</code></a> over elements of type
<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>
<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>
</pre></blockquote>
<b>Complexity:</b> <code>O(m*I(n+m))</code>, where <code>m</code> is the
number of elements in [<code>first</code>,<code>last</code>).<br>
<b>Exception safety:</b> Basic.
</blockquote>
<code>void erase(iterator position);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
of the index.</br>
<b>Effects:</b> Deletes the element pointed to by <code>position</code>.<br>
<b>Complexity:</b> <code>O(D(n))</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<code>void 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>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>
</blockquote>
<a name="replace"><code>bool replace(iterator position,const value_type&amp; x);</code></a>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
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
<code>multi_index_container</code>.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved
in all cases.<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>
<b>Exception safety:</b> Strong. If an exception is thrown by some
user-provided operation the <code>multi_index_container</code> to which the index
belongs remains in its original state.
</blockquote>
<a name="modify">
<code>template&lt;typename Modifier> bool modify(iterator position,Modifier mod);</code></a>
<blockquote>
<b>Requires:</b> <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>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
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
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.
</blockquote>
<h4><a name="list_operations">List operations</a></h4>
<p>
Sequenced indices provides the full set of list operations provided by
<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
of the operations may depend on the other indices belonging to the
same <code>multi_index_container</code>.
</p>
<code>void splice(iterator position,<b>index class name</b>&amp; x);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>&amp;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>
<b>Complexity:</b> <code>O(x.size()*I(n+x.size()) + x.size()*D(x.size()))</code>.<br>
<b>Exception safety:</b> Basic.<br>
</blockquote>
<code>void splice(iterator position,<b>index class name</b>&amp; x,iterator i);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>i</code> is a valid dereferenceable iterator <code>x</code>.<br>
<b>Effects:</b> Inserts the element pointed to by <code>i</code> before
<code>position</code>: if insertion is succesful, the element is erased from
<code>x</code>. In the special case <code>&amp;x==this</code>, no copy or
deletion is performed, and the operation is always succesful. If
<code>position==i</code>, no operation is performed.<br>
<b>Postconditions:</b> If <code>&amp;x==this</code>, no iterator or reference
is invalidated.<br>
<b>Complexity:</b> If <code>&amp;x==this</code>, constant; otherwise
<code>O(I(n) + D(n))</code>.<br>
<b>Exception safety:</b> If <code>&amp;x==this</code>, <code>nothrow</code>;
otherwise, strong.<br>
</blockquote>
<code>void splice(iterator position,<b>index class name&amp;</b> x,iterator first,iterator last);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>first</code> and <code>last</code> are valid iterators of <code>x</code>.
<code>last</code> is reachable from <code>first</code>. <code>position</code>
is not in the range [<code>first</code>,<code>last</code>).<br>
<b>Effects:</b> For each element in the range [<code>first</code>,<code>last</code>),
insertion is tried before <code>position</code>; if the operation is succesful,
the element is erased from <code>x</code>. In the special case
<code>&amp;x==this</code>, no copy or deletion is performed, and insertions are
always succesful.<br>
<b>Postconditions:</b> If <code>&amp;x==this</code>, no iterator or reference
is invalidated.<br>
<b>Complexity:</b> If <code>&amp;x==this</code>, constant; otherwise
<code>O(m*I(n+m) + m*D(x.size()))</code> where <code>m</code> is the number
of elements in [<code>first</code>,<code>last</code>).<br>
<b>Exception safety:</b> If <code>&amp;x==this</code>, <code>nothrow</code>;
otherwise, basic.<br>
</blockquote>
<code>void remove(const value_type&amp; value);</code>
<blockquote>
<b>Effects:</b> Erases all elements of the index which compare equal to
<code>value</code>.<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.
</blockquote>
<code>template&lt;typename Predicate> void remove_if(Predicate pred);</code>
<blockquote>
<b>Effects:</b> Erases all elements <code>x</code> of the index for which
<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.
</blockquote>
<code>void unique();</code>
<blockquote>
<b>Effects:</b> Eliminates all but the first element from every consecutive
group of equal elements referred to by the iterator <code>i</code> in the range
[<code>first+1</code>,<code>last</code>) for which <code>*i==*(i-1)</code>.<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.
</blockquote>
<code>template &lt;class BinaryPredicate> void unique(BinaryPredicate binary_pred);</code>
<blockquote>
<b>Effects:</b> Eliminates all but the first element from every consecutive
group of elements referred to by the iterator <code>i</code> in the range
[<code>first+1</code>,<code>last</code>) for which
<code>binary_pred(*i,*(i-1))</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.
</blockquote>
<code>void merge(index class name&amp; x);</code>
<blockquote>
<b>Requires:</b> <code>std::less&lt;value_type></code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> over <code>value_type</code>.
Both the index and <code>x</code> are sorted according to
<code>std::less&lt;value_type></code>.<br>
<b>Effects:</b> Attempts to insert every element of <code>x</code> into the
corresponding position of the index (according to the order). Elements
successfully inserted are erased from <code>x</code>. The resulting sequence
is stable, i.e. equivalent elements of either container preserve their
relative position. In the special case <code>&amp;x==this</code>, no operation
is performed.<br>
<b>Postconditions:</b> Elements in the index and remaining elements in
<code>x</code> are sorted.
Validity of iterators to the index and of non-erased elements of <code>x</code>
references is preserved.<br>
<b>Complexity:</b> If <code>&amp;x==this</code>, constant; otherwise
<code>O(n + x.size()*I(n+x.size()) + x.size()*D(x.size()))</code>.<br>
<b>Exception safety:</b> If <code>&amp;x==this</code>, <code>nothrow</code>;
otherwise, basic.<br>
</blockquote>
<code>template &lt;typename Compare> void merge(index class name&amp; x,Compare comp);</code>
<blockquote>
<b>Requires:</b> <code>Compare</code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> over <code>value_type</code>.
Both the index and <code>x</code> are sorted according to <code>comp</code>.<br>
<b>Effects:</b> Attempts to insert every element of <code>x</code> into the
corresponding position of the index (according to <code>comp</code>).
Elements successfully inserted are erased from <code>x</code>. The resulting
sequence is stable, i.e. equivalent elements of either container preserve
their relative position. In the special case <code>&amp;x==this</code>, no
operation is performed.<br>
<b>Postconditions:</b> Elements in the index and remaining elements in
<code>x</code> are sorted according to <code>comp</code>.
Validity of iterators to the index and of non-erased elements of <code>x</code>
references is preserved.<br>
<b>Complexity:</b> If <code>&amp;x==this</code>, constant; otherwise
<code>O(n + x.size()*I(n+x.size()) + x.size()*D(x.size()))</code>.<br>
<b>Exception safety:</b> If <code>&amp;x==this</code>, <code>nothrow</code>;
otherwise, basic.<br>
</blockquote>
<code>void sort();</code>
<blockquote>
<b>Requires:</b> <code>std::less&lt;value_type></code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> over <code>value_type</code>.<br>
<b>Effects:</b> Sorts the index according to
<code>std::less&lt;value_type></code>. The sorting is stable, i.e.
equivalent elements preserve their relative position.<br>
<b>Postconditions:</b> Validity of iterators and references is preserved.<br>
<b>Complexity:</b> <code>O(n*log(n))</code>.<br>
<b>Exception safety:</b> <code>nothrow</code> if
<code>std::less&lt;value_type></code> does not throw; otherwise, basic.
</blockquote>
<code>template &lt;typename Compare> void sort(Compare comp);</code>
<blockquote>
<b>Requires:</b> <code>Compare</code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> over <code>value_type</code>.<br>
<b>Effects:</b> Sorts the index according to <code>comp</code>. The sorting
is stable, i.e. equivalent elements preserve their relative position.<br>
<b>Postconditions:</b> Validity of iterators and references is preserved.<br>
<b>Complexity:</b> <code>O(n*log(n))</code>.<br>
<b>Exception safety:</b> <code>nothrow</code> if <code>comp</code> does
not throw; otherwise, basic.
</blockquote>
<code>void reverse();</code>
<blockquote>
<b>Effects:</b> Reverses the order of the elements in the index.<br>
<b>Postconditions:</b> Validity of iterators and references is preserved.<br>
<b>Complexity:</b> <code>O(n)</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<h4><a name="special_list_operations">Special list 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.
</p>
<code>void relocate(iterator position,iterator i);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>i</code> is a valid dereferenceable iterator of the index.<br>
<b>Effects:</b> Inserts the element pointed to by <code>i</code> before
<code>position</code>. If <code>position==i</code>, no operation is
performed.<br>
<b>Postconditions:</b> No iterator or reference is invalidated.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<code>void relocate(iterator position,iterator first,iterator last);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>first</code> and <code>last</code> are valid iterators of the index.
<code>last</code> is reachable from <code>first</code>. <code>position</code>
is not in the range [<code>first</code>,<code>last</code>).<br>
<b>Effects:</b> The range of elements [<code>first</code>,<code>last</code>)
is repositioned just before <code>position</code>.<br>
<b>Postconditions:</b> No iterator or reference is invalidated.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<hr>
<div class="prev_link"><a href="ord_indices.html"><img src="../prev.gif" alt="ordered indices" border="0"><br>
Ordered 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
</a></div>
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key extraction" border="0"><br>
Key extraction
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

48
doc/style.css Normal file
View File

@ -0,0 +1,48 @@
pre{
BORDER-RIGHT: gray 1pt solid;
PADDING-RIGHT: 2pt;
BORDER-TOP: gray 1pt solid;
DISPLAY: block;
PADDING-LEFT: 2pt;
PADDING-BOTTOM: 2pt;
BORDER-LEFT: gray 1pt solid;
MARGIN-RIGHT: 32pt;
PADDING-TOP: 2pt;
BORDER-BOTTOM: gray 1pt solid;
FONT-FAMILY: "Courier New", Courier, mono;
background-color: #EEEEEE;
}
table{
PADDING-RIGHT: 2pt;
BORDER-TOP: gray 1pt solid;
DISPLAY: block;
PADDING-LEFT: 2pt;
PADDING-BOTTOM: 2pt;
BORDER-LEFT: gray 1pt solid;
MARGIN-RIGHT: 32pt;
PADDING-TOP: 2pt;
background-color: #EEEEEE;
}
td{
BORDER-STYLE: solid;
BORDER-WIDTH: 1pt;
BORDER-LEFT: ;
BORDER-RIGHT: gray 1pt solid;
BORDER-TOP: ;
BORDER-BOTTOM: gray 1pt solid;
}
th{color: #ffffff; background-color: #000000;}
.odd_tr{background-color: #ffffff;}
.keyword{color: #0000FF;}
.identifier{}
.comment{font-style: italic; color: #008000;}
.special{color: #800040;}
.preprocessor{color: #3F007F;}
.string{font-style: italic; color: #666666;}
.literal{font-style: italic; color: #666666;}
.prev_link{width: 30%; float: left; text-align: left;}
.up_link{width: 39.9%; float: left; text-align: center;}
.next_link{width: 30%; float: left; text-align: right;}

146
doc/tests.html Normal file
View File

@ -0,0 +1,146 @@
<!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 - Tests</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<h1><img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tests</h1>
<div class="prev_link"><a href="examples.html"><img src="prev.gif" alt="examples" border="0"><br>
Examples
</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="future_work.html"><img src="next.gif" alt="future work" border="0"><br>
Future work
</a></div><br clear="all" style="clear: all;">
<hr>
<p>
The Boost.MultiIndex test suite exercises the whole spectrum of
functionalities provided by the library. Although the tests are not meant
to serve as a learning guide, the interested reader may find it
useful to inspect the source code to gain familiarity
with some of the least common features offered by Boost.MultiIndex.
</p>
<p align="center">
<table cellspacing="0" cellpadding="5">
<caption><b>Boost.MultiIndex test suite.</b></caption>
<tr>
<th>Program</th>
<th>Description</th>
</tr>
<tr>
<td><a href="../test/test_basic.cpp"><code>test_basic.cpp</code></a></td>
<td>Simple program along the lines of the employees example studied in the
tutorial.</td>
</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>
</tr>
<tr>
<td><a href="../test/test_comparison.cpp"><code>test_comparison.cpp</code></a></td>
<td>Comparison between indices.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_composite_key.cpp"><code>test_composite_key.cpp</code></a></td>
<td><code>composite_key</code> and <code>composite_key_compare</code>.</td>
</tr>
<tr>
<td><a href="../test/test_conv_iterators.cpp"><code>test_conv_iterators.cpp</code></a></td>
<td>Checks convertibility of constant to non-constant iterators.</td>
</tr>
<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> .
</tr>
<tr>
<td><a href="../test/test_iterators.cpp"><code>test_iterators.cpp</code></a></td>
<td>Constant and non-constant iterators and their reverse variants.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_key_extractors.cpp"><code>test_key_extractors.cpp</code></a></td>
<td>Covers all use cases of key extractors shipped with the library.</td>
</tr>
<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>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_modifiers.cpp"><code>test_modifiers.cpp</code></a></td>
<td>Checks the family of insertion and erasing operations.</td>
</tr>
<tr>
<td><a href="../test/test_mpl_ops.cpp"><code>test_mpl_ops.cpp</code></a></td>
<td>Shows how to take advantage of <code>mpl_index_list</code> in a
metaprogram.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_projection.cpp"><code>test_projection.cpp</code></a></td>
<td>Projection of iterators among indices.</td>
</tr>
<tr>
<td><a href="../test/test_range.cpp"><code>test_range.cpp</code></a></td>
<td>Exercises the <code>range</code> facility (ordered indices only).</td>
</tr>
<tr class="odd_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_set_ops.cpp"><code>test_set_ops.cpp</code></a></td>
<td>Set-like operations particular to ordered indices.</td>
</tr>
<tr class="odd_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>
<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>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_update.cpp"><code>test_update.cpp</code></a></td>
<td><code>replace</code>, <code>modify</code> and <code>modify_key</code>.</td>
</tr>
</table>
</p>
<hr>
<div class="prev_link"><a href="examples.html"><img src="prev.gif" alt="examples" border="0"><br>
Examples
</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="future_work.html"><img src="next.gif" alt="future work" border="0"><br>
Future work
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised May 7th 2004</p>
<p>Copyright &copy; 2003-2004 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Use, modification, and distribution are subject to 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">
www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

1260
doc/tutorial.html Normal file

File diff suppressed because it is too large Load Diff

BIN
doc/up.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

44
example/Jamfile Normal file
View File

@ -0,0 +1,44 @@
# Boost.MultiIndex examples Jamfile
#
# Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and distribution
# are subject to 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)
;
exe bimap
: bimap.cpp
: <include>$(BOOST_ROOT)
;
exe complex_structs
: complex_structs.cpp
: <include>$(BOOST_ROOT)
;
exe composite_keys
: composite_keys.cpp
: <include>$(BOOST_ROOT)
;
exe memfun_key
: memfun_key.cpp
: <include>$(BOOST_ROOT)
;
exe non_default_ctor
: non_default_ctor.cpp
: <include>$(BOOST_ROOT)
;
exe sequenced
: sequenced.cpp
: <include>$(BOOST_ROOT)
;

122
example/basic.cpp Normal file
View File

@ -0,0 +1,122 @@
/* Boost.MultiIndex basic example.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
using boost::multi_index_container;
using namespace boost::multi_index;
/* an employee record holds its ID, name and age */
struct employee
{
int id;
std::string name;
int age;
employee(int id_,std::string name_,int age_):id(id_),name(name_),age(age_){}
friend std::ostream& operator<<(std::ostream& os,const employee& e)
{
os<<e.id<<" "<<e.name<<" "<<e.age<<std::endl;
return os;
}
};
/* tags for accessing the corresponding indices of employee_set */
struct id{};
struct name{};
struct age{};
/* see Advanced topics: Use of member_offset for info on
* BOOST_MULTI_INDEX_MEMBER
*/
/* Define a multi_index_container of employees with following indices:
* - a unique index sorted by employee::int,
* - a non-unique index sorted by employee::name,
* - a non-unique index sorted by employee::age.
*/
typedef multi_index_container<
employee,
indexed_by<
ordered_unique<
tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
ordered_non_unique<
tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>,
ordered_non_unique<
tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >
> employee_set;
template<typename Tag,typename MultiIndexContainer>
void print_out_by(
const MultiIndexContainer& s,
Tag* =0 /* fixes a MSVC++ 6.0 bug with implicit template function parms */
)
{
/* obtain a reference to the index tagged by Tag */
const typename boost::multi_index::index<MultiIndexContainer,Tag>::type& i=
get<Tag>(s);
typedef typename MultiIndexContainer::value_type value_type;
/* dump the elements of the index to cout */
std::copy(i.begin(),i.end(),std::ostream_iterator<value_type>(std::cout));
}
int main()
{
employee_set es;
es.insert(employee(0,"Joe",31));
es.insert(employee(1,"Robert",27));
es.insert(employee(2,"John",40));
/* next insertion will fail, as there is an employee with
* the same ID
*/
es.insert(employee(2,"Aristotle",2387));
es.insert(employee(3,"Albert",20));
es.insert(employee(4,"John",57));
/* list the employees sorted by ID, name and age */
std::cout<<"by ID"<<std::endl;
print_out_by<id>(es);
std::cout<<std::endl;
std::cout<<"by name"<<std::endl;
print_out_by<name>(es);
std::cout<<std::endl;
std::cout<<"by age"<<std::endl;
print_out_by<age>(es);
std::cout<<std::endl;
return 0;
}

142
example/bimap.cpp Normal file
View File

@ -0,0 +1,142 @@
/* Boost.MultiIndex example of a bidirectional map.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream>
#include <string>
#include <utility>
using boost::multi_index_container;
using namespace boost::multi_index;
/* tags for accessing both sides of a bidirectional map */
struct from{};
struct to{};
/* The class template bidirectional_map wraps the specification
* of a bidirectional map based on multi_index_container.
*/
template<typename FromType,typename ToType>
struct bidirectional_map
{
typedef std::pair<FromType,ToType> value_type;
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\
defined(BOOST_MSVC)&&(BOOST_MSVC<1300) ||\
defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\
(BOOST_INTEL_CXX_VERSION<=700)
/* see Advanced topics: Use of member_offset for info on member<> and
* member_offset<>
*/
BOOST_STATIC_CONSTANT(unsigned,from_offset=offsetof(value_type,first));
BOOST_STATIC_CONSTANT(unsigned,to_offset =offsetof(value_type,second));
typedef multi_index_container<
value_type,
indexed_by<
ordered_unique<
tag<from>,member_offset<value_type,FromType,from_offset> >,
ordered_unique<
tag<to>, member_offset<value_type,ToType,to_offset> >
>
> type;
#else
/* A bidirectional map can be simulated as a multi_index_container
* of pairs of (FromType,ToType) with two unique indices, one
* for each member of the pair.
*/
typedef multi_index_container<
value_type,
indexed_by<
ordered_unique<
tag<from>,member<value_type,FromType,&value_type::first> >,
ordered_unique<
tag<to>, member<value_type,ToType,&value_type::second> >
>
> type;
#endif
};
/* a dictionary is a bidirectional map from strings to strings */
typedef bidirectional_map<std::string,std::string>::type dictionary;
int main()
{
dictionary d;
/* Fill up our microdictionary. first members Spanish, second members
* English.
*/
d.insert(dictionary::value_type("hola","hello"));
d.insert(dictionary::value_type("adios","goodbye"));
d.insert(dictionary::value_type("rosa","rose"));
d.insert(dictionary::value_type("mesa","table"));
std::cout<<"enter a word"<<std::endl;
std::string word;
std::getline(std::cin,word);
#if defined(BOOST_NO_MEMBER_TEMPLATES) /* use global get<> and family instead */
dictionary::iterator it=get<from>(d).find(word);
if(it!=d.end()){
std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
}
else{
nth_index_iterator<dictionary,1>::type it2=get<1>(d).find(word);
if(it2!=get<1>(d).end()){
std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
}
else std::cout<<"No such word in the dictionary"<<std::endl;
}
#else
/* search the queried word on the from index (Spanish) */
dictionary::iterator it=d.get<from>().find(word);
if(it!=d.end()){ /* found */
/* the second part of the element is the equivalent in English */
std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
}
else{
/* word not found in Spanish, try our luck in English */
dictionary::index_iterator<to>::type it2=d.get<to>().find(word);
if(it2!=d.get<to>().end()){
std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
}
else std::cout<<"No such word in the dictionary"<<std::endl;
}
#endif
return 0;
}

315
example/complex_structs.cpp Normal file
View File

@ -0,0 +1,315 @@
/* Boost.MultiIndex example: complex searches and foreign keys.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/tuple/tuple.hpp>
#include <iostream>
#include <string>
using boost::multi_index_container;
using namespace boost::multi_index;
/* This small utility that cascades two key extractors will be
* used througout the example.
*/
template<class KeyExtractor1,class KeyExtractor2>
struct key_from_key
{
public:
typedef typename KeyExtractor1::result_type result_type;
key_from_key(
const KeyExtractor1& key1_=KeyExtractor1(),
const KeyExtractor2& key2_=KeyExtractor2()):
key1(key1_),key2(key2_)
{}
template<typename Arg>
result_type operator()(Arg& arg)const
{
return key1(key2(arg));
}
private:
KeyExtractor1 key1;
KeyExtractor2 key2;
};
/* tags for accessing several indices defined below */
struct model{};
struct manufacturer{};
struct price{};
/* a manufacturer struct just holds the name of the manufacturer */
struct car_manufacturer
{
std::string name;
car_manufacturer(const std::string& name_):name(name_){}
};
/* car_model holds the model of car, its price and a pointer to the
* manufacturer. The pointer thing eliminates duplication of the same
* data among cars of the same manufacturer.
*/
struct car_model
{
std::string model;
const car_manufacturer* manufacturer;
int price;
car_model(
const std::string& model_,const car_manufacturer* manufacturer_,int price_):
model(model_),manufacturer(manufacturer_),price(price_)
{}
friend std::ostream& operator<<(std::ostream& os,const car_model& c)
{
os<<c.manufacturer->name<<" "<<c.model<<" $"<<c.price<<std::endl;
return os;
}
};
/* see Advanced topics: Use of member_offset for info on
* BOOST_MULTI_INDEX_MEMBER
*/
/* Car manufacturers are stored in a multi_index_container with one single
* index on the name member. This is functionally equivalent to an std::set,
* though in this latter case we woud have to define a non-default comparison
* predicate (with multi_index_container, member<> does the work for us.)
*/
typedef multi_index_container<
car_manufacturer,
indexed_by<
ordered_unique<
BOOST_MULTI_INDEX_MEMBER(car_manufacturer,std::string,name)
>
>
> car_manufacturer_table;
/* Define a multi_index_container of car_models with following indices:
* - a unique index sorted by car_model::model,
* - a non-unique index sorted by car_model::manufacturer; note the
* non-standard manufacturer_extractor used.
* - a non-unique index sorted by car_model::price.
*/
typedef multi_index_container<
car_model,
indexed_by<
ordered_unique<
tag<model>,BOOST_MULTI_INDEX_MEMBER(car_model,std::string,model)
>,
ordered_non_unique<
tag<manufacturer>,
key_from_key<
BOOST_MULTI_INDEX_MEMBER(car_manufacturer,const std::string,name),
BOOST_MULTI_INDEX_MEMBER(
car_model,const car_manufacturer *,manufacturer)
>
>,
ordered_non_unique<
tag<price>,BOOST_MULTI_INDEX_MEMBER(car_model,int,price)
>
>
> car_table;
/* We call a *view* to a multi_index_container storing pointers instead of
* actual objects. These views are used in the complex search performed
* in the program. Resorting to multi_index of pointers eliminates
* unnecessary copying of objects, and provides us with an opportunity
* to show how BOOST_MULTI_INDEX_MEMBER can be used with pointer
* type elements.
* car_table_price_view indexes (pointers to) car_models by price.
*/
typedef multi_index_container<
const car_model*,
indexed_by<
ordered_non_unique<BOOST_MULTI_INDEX_MEMBER(car_model,const int,price)>
>
> car_table_price_view;
/* car_table_manufacturer_view indexes (pointers to) car_models by
* manufacturer
*/
typedef multi_index_container<
const car_model*,
indexed_by<
ordered_non_unique<
key_from_key<
BOOST_MULTI_INDEX_MEMBER(car_manufacturer,const std::string,name),
BOOST_MULTI_INDEX_MEMBER(
car_model,const car_manufacturer * const,manufacturer)
>
>
>
> car_table_manufacturer_view;
int main()
{
car_manufacturer_table cmt;
/* Fill the car_manufacturer table and keep pointers to the
* elements inserted.
*/
const car_manufacturer * cadillac=
&*(cmt.insert(car_manufacturer("Cadillac")).first);
const car_manufacturer * ford =
&*(cmt.insert(car_manufacturer("Ford")).first);
const car_manufacturer * bmw =
&*(cmt.insert(car_manufacturer("BMW")).first);
const car_manufacturer * audi =
&*(cmt.insert(car_manufacturer("Audi")).first);
car_table ct;
/* Fill the car_model_table. We use the previously initialized
* pointers to the elements of cmt.
*/
ct.insert(car_model("XLR",cadillac,76200));
ct.insert(car_model("SRX",cadillac,38690));
ct.insert(car_model("CTS",cadillac,30695));
ct.insert(car_model("Escalade",cadillac,54770));
ct.insert(car_model("ESV",cadillac,57195));
ct.insert(car_model("EXT",cadillac,52045));
ct.insert(car_model("Deville",cadillac,45195));
ct.insert(car_model("Seville",cadillac,46330));
ct.insert(car_model("ZX2",ford,15355));
ct.insert(car_model("Thunderbird",ford,43995));
ct.insert(car_model("Windstar",ford,35510));
ct.insert(car_model("Focus",ford,19630));
ct.insert(car_model("Taurus",ford,24290));
ct.insert(car_model("Mustang",ford,39900));
ct.insert(car_model("Crown Victoria",ford,30370));
ct.insert(car_model("325i",bmw,27800));
ct.insert(car_model("545i",bmw,54300));
ct.insert(car_model("745i",bmw,68500));
ct.insert(car_model("M3 coupe",bmw,46500));
ct.insert(car_model("Z4 roadster 3.0i",bmw,40250));
ct.insert(car_model("X5 4.4i",bmw,49950));
ct.insert(car_model("A4 1.8T",audi,25940));
ct.insert(car_model("TT Coupe",audi,33940));
ct.insert(car_model("A6 3.0",audi,36640));
ct.insert(car_model("Allroad quattro 2.7T",audi,40640));
ct.insert(car_model("A8 L",audi,69190));
std::cout<<"enter a car manufacturer"<<std::endl;
std::string cm;
std::getline(std::cin,cm);
/* check for manufacturer */
car_manufacturer_table::iterator icm=cmt.find(cm);
if(icm==cmt.end()){
std::cout<<"no such manufacturer in the table"<<std::endl;
return 0;
}
std::cout<<"enter a minimum price"<<std::endl;
int min_price;
std::cin>>min_price;
std::cout<<"enter a maximum price"<<std::endl;
int max_price;
std::cin>>max_price;
{
/* method 1 */
/* find all the cars for the manufacturer given */
index_iterator<car_table,manufacturer>::type ic0,ic1;
boost::tuples::tie(ic0,ic1)=get<manufacturer>(ct).equal_range(cm);
/* construct a view (indexed by price) with these */
car_table_price_view ctpv;
while(ic0!=ic1){
ctpv.insert(&*ic0);
++ic0;
}
/* select the cars in the range given */
car_table_price_view::iterator ictpv0=ctpv.lower_bound(min_price);
car_table_price_view::iterator ictpv1=ctpv.upper_bound(max_price);
if(ictpv0==ictpv1){
std::cout<<"no cars in the range given"<<std::endl;
return 0;
}
/* list them */
std::cout<<"listing by method 1"<<std::endl;
while(ictpv0!=ictpv1){
std::cout<<**ictpv0;
++ictpv0;
}
std::cout<<std::endl;
}
{
/* method 2 will give the same results */
/* find the cars in the range given */
index_iterator<car_table,price>::type ic0,ic1;
ic0=get<price>(ct).lower_bound(min_price);
ic1=get<price>(ct).upper_bound(max_price);
/* construct a view with these */
car_table_manufacturer_view ctmv;
while(ic0!=ic1){
ctmv.insert(&*ic0);
++ic0;
}
/* select the cars with given manufacturer */
car_table_manufacturer_view::iterator ictmv0,ictmv1;
boost::tuples::tie(ictmv0,ictmv1)=ctmv.equal_range(cm);
if(ictmv0==ictmv1){
std::cout<<"no cars in the range given"<<std::endl;
return 0;
}
/* list them */
std::cout<<"listing by method 2"<<std::endl;
while(ictmv0!=ictmv1){
std::cout<<**ictmv0;
++ictmv0;
}
std::cout<<std::endl;
}
return 0;
}

295
example/composite_keys.cpp Normal file
View File

@ -0,0 +1,295 @@
/* Boost.MultiIndex example of composite keys.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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/call_traits.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/tokenizer.hpp>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
using namespace boost::multi_index;
/* A file record maintains some info on name and size as well
* as a pointer to the directory it belongs (null meaning the root
* directory.)
*/
struct file_entry
{
file_entry(
std::string name_,unsigned size_,bool is_dir_,const file_entry* dir_):
name(name_),size(size_),is_dir(is_dir_),dir(dir_)
{}
std::string name;
unsigned size;
bool is_dir;
const file_entry* dir;
friend std::ostream& operator<<(std::ostream& os,const file_entry& f)
{
os<<f.name<<"\t"<<f.size;
if(f.is_dir)os<<"\t <dir>";
return os;
}
};
/* A file system is just a multi_index_container of entries with indices on
* file and size. These indices are firstly ordered by directory, as commands
* work on a current directory basis. Composite keys are just fine to model
* this.
* NB: We use derivation here instead of simple typedef's as MSVC++ 6.0
* chokes otherwise. Seems to be related with the complexity of the type
* generated.
*/
struct name_key:composite_key<
file_entry,
BOOST_MULTI_INDEX_MEMBER(file_entry,const file_entry*,dir),
BOOST_MULTI_INDEX_MEMBER(file_entry,std::string,name)
>{};
struct size_key:composite_key<
file_entry,
BOOST_MULTI_INDEX_MEMBER(file_entry,const file_entry* const,dir),
BOOST_MULTI_INDEX_MEMBER(file_entry,unsigned,size)
>{};
/* see Advanced topics: composite_key in compilers without partial template
* specialization, for info on composite_key_result_less
*/
typedef multi_index_container<
file_entry,
indexed_by<
/* primary index sorted by name (inside the same directory) */
ordered_unique<
name_key
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
,composite_key_result_less<name_key::result_type>
#endif
>,
/* secondary index sorted by size (inside the same directory) */
ordered_non_unique<
size_key
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
,composite_key_result_less<size_key::result_type>
#endif
>
>
> file_system;
/* typedef's of the two indices of file_system */
typedef nth_index<file_system,0>::type file_system_by_name;
typedef nth_index<file_system,1>::type file_system_by_size;
/* We build a rudimentary file system simulation out of some global
* info and a map of commands provided to the user.
*/
static file_system fs; /* the one and only file system */
static file_system_by_name& fs_by_name=fs; /* name index to fs */
static file_system_by_size& fs_by_size=get<1>(fs); /* size index to fs */
static const file_entry* current_dir=0; /* root directory */
/* command framework */
/* A command provides an execute memfun fed with the corresponding params
* (first param is stripped off as it serves to identify the command
* currently being used.)
*/
typedef boost::tokenizer<boost::char_separator<char> > command_tokenizer;
class command
{
public:
virtual ~command(){}
virtual void execute(
command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)=0;
};
/* available commands */
/* cd: syntax cd [.|..|<directory>] */
class command_cd:public command
{
public:
virtual void execute(
command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)
{
if(tok1==tok2)return;
std::string dir=*tok1++;
if(dir==".")return;
if(dir==".."){
if(current_dir)current_dir=current_dir->dir;
return;
}
file_system_by_name::iterator it=fs.find(
boost::make_tuple(current_dir,dir));
if(it==fs.end()){
std::cout<<"non-existent directory"<<std::endl;
return;
}
if(!it->is_dir){
std::cout<<dir<<" is not a directory"<<std::endl;
return;
}
current_dir=&*it;
}
};
static command_cd cd;
/* ls: syntax ls [-s] */
class command_ls:public command
{
public:
virtual void execute(
command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)
{
std::string option;
if(tok1!=tok2)option=*tok1++;
if(!option.empty()){
if(option!="-s"){
std::cout<<"incorrect parameter"<<std::endl;
return;
}
/* list by size */
file_system_by_size::iterator it0,it1;
boost::tie(it0,it1)=fs_by_size.equal_range(
boost::make_tuple(current_dir));
std::copy(it0,it1,std::ostream_iterator<file_entry>(std::cout,"\n"));
return;
}
/* list by name */
file_system_by_name::iterator it0,it1;
boost::tie(it0,it1)=fs.equal_range(boost::make_tuple(current_dir));
std::copy(it0,it1,std::ostream_iterator<file_entry>(std::cout,"\n"));
}
};
static command_ls ls;
/* mkdir: syntax mkdir <directory> */
class command_mkdir:public command
{
public:
virtual void execute(
command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)
{
std::string dir;
if(tok1!=tok2)dir=*tok1++;
if(dir.empty()){
std::cout<<"missing parameter"<<std::endl;
return;
}
if(dir=="."||dir==".."){
std::cout<<"incorrect parameter"<<std::endl;
return;
}
if(!fs.insert(file_entry(dir,0,true,current_dir)).second){
std::cout<<"directory already exists"<<std::endl;
return;
}
}
};
static command_mkdir mkdir;
/* table of commands, a map from command names to class command pointers */
typedef std::map<std::string,command*> command_table;
static command_table cmt;
int main()
{
/* fill the file system with some data */
file_system::iterator it0,it1;
fs.insert(file_entry("usr.cfg",240,false,0));
fs.insert(file_entry("memo.txt",2430,false,0));
it0=fs.insert(file_entry("dev",0,true,0)).first;
fs.insert(file_entry("tty0",128,false,&*it0));
fs.insert(file_entry("tty1",128,false,&*it0));
it0=fs.insert(file_entry("usr",0,true,0)).first;
it1=fs.insert(file_entry("bin",0,true,&*it0)).first;
fs.insert(file_entry("bjam",172032,false,&*it1));
it0=fs.insert(file_entry("home",0,true,0)).first;
it1=fs.insert(file_entry("andy",0,true,&*it0)).first;
fs.insert(file_entry("logo.jpg",5345,false,&*it1)).first;
fs.insert(file_entry("foo.cpp",890,false,&*it1)).first;
fs.insert(file_entry("foo.hpp",93,false,&*it1)).first;
fs.insert(file_entry("foo.html",750,false,&*it1)).first;
fs.insert(file_entry("a.obj",12302,false,&*it1)).first;
fs.insert(file_entry(".bash_history",8780,false,&*it1)).first;
it1=fs.insert(file_entry("rachel",0,true,&*it0)).first;
fs.insert(file_entry("test.py",650,false,&*it1)).first;
fs.insert(file_entry("todo.txt",241,false,&*it1)).first;
fs.insert(file_entry(".bash_history",9510,false,&*it1)).first;
/* fill the command table */
cmt["cd"] =&cd;
cmt["ls"] =&ls;
cmt["mkdir"]=&mkdir;
/* main looop */
for(;;){
/* print out the current directory and the prompt symbol */
if(current_dir)std::cout<<current_dir->name;
std::cout<<">";
/* get an input line from the user: if empty, exit the program */
std::string com;
std::getline(std::cin,com);
command_tokenizer tok(com,boost::char_separator<char>(" \t\n"));
if(tok.begin()==tok.end())break; /* null command, exit */
/* select the corresponding command and execute it */
command_table::iterator it=cmt.find(*tok.begin());
if(it==cmt.end()){
std::cout<<"invalid command"<<std::endl;
continue;
}
it->second->execute(++tok.begin(),tok.end());
}
return 0;
}

76
example/memfun_key.cpp Normal file
View File

@ -0,0 +1,76 @@
/* Boost.MultiIndex example of member functions used as key extractors.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream>
#include <string>
using namespace boost::multi_index;
/* A name record consists of the given name (e.g. "Charlie")
* and the family name (e.g. "Brown"). The full name, calculated
* by name_record::name() is laid out in the "phonebook order"
* family name + given_name.
*/
struct name_record
{
name_record(std::string given_name,std::string family_name):
given_name(given_name),family_name(family_name)
{}
std::string name()const
{
std::string str=family_name;
str+=" ";
str+=given_name;
return str;
}
private:
std::string given_name;
std::string family_name;
};
/* multi_index_container with only one index based on name_record::name() */
typedef multi_index_container<
name_record,
indexed_by<
ordered_unique<
BOOST_MULTI_INDEX_CONST_MEM_FUN(name_record,std::string,name)
>
>
> name_record_set;
int main()
{
name_record_set ns;
ns.insert(name_record("Joe","Smith"));
ns.insert(name_record("Robert","Nightingale"));
ns.insert(name_record("Robert","Brown"));
ns.insert(name_record("Marc","Tuxedo"));
/* list the names in ns in phonebook order */
for(name_record_set::iterator it=ns.begin();it!=ns.end();++it){
std::cout<<it->name()<<std::endl;
}
return 0;
}

View File

@ -0,0 +1,96 @@
/* Boost.MultiIndex example of use of multi_index_container::ctor_args_list.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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 <algorithm>
#include <iostream>
#include <iterator>
using boost::multi_index_container;
using namespace boost::multi_index;
/* modulo_less order numbers according to their division residual.
* For instance, if modulo==10 then 22 is less than 15 as 22%10==2 and
* 15%10==5.
*/
template<typename IntegralType>
struct modulo_less
{
modulo_less(IntegralType m):modulo(m){}
bool operator()(IntegralType x,IntegralType y)const
{
return (x%modulo)<(y%modulo);
}
private:
IntegralType modulo;
};
/* multi_index_container of unsigned ints holding a "natural" index plus
* an ordering based on modulo_less.
*/
typedef multi_index_container<
unsigned int,
indexed_by<
ordered_unique<identity<unsigned int> >,
ordered_non_unique<identity<unsigned int>, modulo_less<unsigned int> >
>
> modulo_indexed_set;
int main()
{
/* define a modulo_indexed_set with modulo==10 */
modulo_indexed_set::ctor_args_list args_list=
boost::make_tuple(
/* ctor_args for index #0 is default constructible */
nth_index<modulo_indexed_set,0>::type::ctor_args(),
/* first parm is key_from_value, second is our sought for key_compare */
boost::make_tuple(identity<unsigned int>(),modulo_less<unsigned int>(10))
);
modulo_indexed_set m(args_list);
/* this could have be written online without the args_list variable,
* left as it is for explanatory purposes. */
/* insert some numbers */
unsigned int numbers[]={0,1,20,40,33,68,11,101,60,34,88,230,21,4,7,17};
const std::size_t numbers_length(sizeof(numbers)/sizeof(numbers[0]));
m.insert(&numbers[0],&numbers[numbers_length]);
/* lists all numbers in order, along with their "equivalence class", that is,
* the equivalent numbers under modulo_less
*/
for(modulo_indexed_set::iterator it=m.begin();it!=m.end();++it){
std::cout<<*it<<" -> ( ";
nth_index<modulo_indexed_set,1>::type::iterator it0,it1;
boost::tie(it0,it1)=get<1>(m).equal_range(*it);
std::copy(it0,it1,std::ostream_iterator<unsigned int>(std::cout," "));
std::cout<<")"<<std::endl;
}
return 0;
}

101
example/sequenced.cpp Normal file
View File

@ -0,0 +1,101 @@
/* Boost.MultiIndex example of use of sequenced indices.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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/sequenced_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/tokenizer.hpp>
#include <algorithm>
#include <iomanip>
#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<
sequenced<>,
ordered_non_unique<identity<std::string> >
>
> text_container;
/* ordered index */
typedef nth_index<text_container,1>::type ordered_text;
typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
int main()
{
std::string text=
"Alice was beginning to get very tired of sitting by her sister on the "
"bank, and of having nothing to do: once or twice she had peeped into the "
"book her sister was reading, but it had no pictures or conversations in "
"it, 'and what is the use of a book,' thought Alice 'without pictures or "
"conversation?'";
/* feed the text into the container */
text_container tc;
text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
std::copy(tok.begin(),tok.end(),std::back_inserter(tc));
/* list all words in alphabetical order along with their number
* of occurrences
*/
ordered_text& ot=get<1>(tc);
for(ordered_text::iterator it=ot.begin();it!=ot.end();){
std::cout<<std::left<<std::setw(14)<<*it<<":"; /* print the word */
ordered_text::iterator it2=ot.upper_bound(*it); /* jump to next */
std::cout<<std::right<<std::setw(3) /* and compute the distance */
<<std::distance(it,it2)<<" times"<<std::endl;
it=it2;
}
/* reverse the text and print it out */
tc.reverse();
std::cout<<std::endl;
std::copy(
tc.begin(),tc.end(),std::ostream_iterator<std::string>(std::cout," "));
std::cout<<std::endl;
tc.reverse(); /* undo */
/* delete most common English words and print the result */
std::string common_words[]=
{"the","of","and","a","to","in","is","you","that","it",
"he","for","was","on","are","as","with","his","they","at"};
for(std::size_t n=0;n<sizeof(common_words)/sizeof(common_words[0]);++n){
ot.erase(common_words[n]);
}
std::cout<<std::endl;
std::copy(
tc.begin(),tc.end(),std::ostream_iterator<std::string>(std::cout," "));
std::cout<<std::endl;
return 0;
}

View File

@ -0,0 +1,948 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_COMPOSITE_KEY_HPP
#define BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/control/expr_if.hpp>
#include <boost/preprocessor/list/at.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/static_assert.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/is_same.hpp>
#include <functional>
/* 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
* key extractors are lazily performed on comparison time.
* As the other key extractors in Boost.MultiIndex, composite_key<T,...>
* is overloaded to work on chained pointers to T and reference_wrappers
* of T.
* composite_key_compare is overloaded to enable comparisons between
* composite_key_results and tuples of values. Comparison is done
* lexicographically on on the maximum common number of elements of the
* operands. This allows searching for incomplete keys
*/
/* This user_definable macro limits the number of elements of a composite
* key; useful for shortening resulting symbol names (MSVC++ 6.0, for
* instance has problems coping with very long symbol names.)
* NB: This cannot exceed the maximum number of arguments of
* boost::tuple. In Boost 1.31, the limit is 10.
*/
#if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
#define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 5
#else
#define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
#endif
#endif
/* maximum number of key extractors in a composite key */
#if BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE<10 /* max length of a tuple */
#define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE \
BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE
#else
#define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE 10
#endif
/* BOOST_PP_ENUM of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
#define BOOST_MULTI_INDEX_CK_ENUM(macro,data) \
BOOST_PP_ENUM(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,macro,data)
/* BOOST_PP_ENUM_PARAMS of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
#define BOOST_MULTI_INDEX_CK_ENUM_PARAMS(param) \
BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,param)
/* if n==0 -> text0
* otherwise -> textn=tuples::null_type
*/
#define BOOST_MULTI_INDEX_CK_TEMPLATE_PARM(z,n,text) \
typename BOOST_PP_CAT(text,n) BOOST_PP_EXPR_IF(n,=tuples::null_type)
/* const textn& kn=textn() */
#define BOOST_MULTI_INDEX_CK_CTOR_ARG(z,n,text) \
const BOOST_PP_CAT(text,n)& BOOST_PP_CAT(k,n) = BOOST_PP_CAT(text,n)()
/* typename list(0)<list(1),n>::type */
#define BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N(z,n,list) \
BOOST_DEDUCED_TYPENAME BOOST_PP_LIST_AT(list,0)< \
BOOST_PP_LIST_AT(list,1),n \
>::type
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
namespace multi_index{
namespace detail{
/* nth_composite_key_less<CompositeKey,N>:: yields std::less<result_type>
* where result_type is the result_type of the nth key extractor of
* CompositeKey. If N >= the length of CompositeKey, it yields
* tuples::null_type.
* Similar thing for nth_composite_key_greater.
*/
template<typename CompositeKey,int N>
struct nth_key_from_value
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename prevent_eti<
tuples::element<N,key_extractor_tuple>,
typename mpl::apply_if_c<
N<tuples::length<key_extractor_tuple>::value,
tuples::element<N,key_extractor_tuple>,
mpl::identity<tuples::null_type>
>::type
>::type type;
};
template<typename KeyFromValue>
struct key_std_less
{
typedef std::less<typename KeyFromValue::result_type> type;
};
template<>
struct key_std_less<tuples::null_type>
{
typedef tuples::null_type type;
};
template<typename CompositeKey,int N>
struct nth_composite_key_less
{
typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;
typedef typename key_std_less<key_from_value>::type type;
};
template<typename KeyFromValue>
struct key_std_greater
{
typedef std::greater<typename KeyFromValue::result_type> type;
};
template<>
struct key_std_greater<tuples::null_type>
{
typedef tuples::null_type type;
};
template<typename CompositeKey,int N>
struct nth_composite_key_greater
{
typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;
typedef typename key_std_greater<key_from_value>::type type;
};
/* Metaprogramming machinery to compare composite_key_results between
* them and with tuples of values.
* equals_* computes equality of two tuple objects x,y with the same
* length, defined as
*
* xi==yi for all i in [0,...,min(length(x),length(y))).
*
* less_* accepts operands of different lenghts and computes the
* following less-than relation:
*
* !(xi<yi) && !(yi<xi) && xj<yj
* for all i in [0,j) and some j in [0,...,min(length(x),length(y)).
*
* compare_* computes the same algorithm than less_*, but taking a tuple
* of comparison predicates instead of operator<.
*/
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct equals_ckey_ckey; /* fwd decl. */
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct equals_ckey_ckey_terminal
{
static bool compare(
const KeyCons1&,const Value1&,
const KeyCons2&,const Value2&)
{
return true;
}
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct equals_ckey_ckey_normal
{
static bool compare(
const KeyCons1& c0,const Value1& v0,
const KeyCons2& c1,const Value2& v1)
{
if(!(c0.get_head()(v0)==c1.get_head()(v1)))return false;
return equals_ckey_ckey<
BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2
>::compare(c0.get_tail(),v0,c1.get_tail(),v1);
}
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct equals_ckey_ckey:
mpl::if_<
mpl::or_<
is_same<KeyCons1,tuples::null_type>,
is_same<KeyCons2,tuples::null_type>
>,
equals_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2>,
equals_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2>
>::type
{
};
template<typename KeyCons,typename Value,typename ValCons>
struct equals_ckey_cval; /* fwd decl. */
template<typename KeyCons,typename Value,typename ValCons>
struct equals_ckey_cval_terminal
{
static bool compare(const KeyCons&,const Value&,const ValCons&)
{
return true;
}
static bool compare(const ValCons&,const KeyCons&,const Value&)
{
return true;
}
};
template<typename KeyCons,typename Value,typename ValCons>
struct equals_ckey_cval_normal
{
static bool compare(const KeyCons& c,const Value& v,const ValCons& vc)
{
if(!(c.get_head()(v)==vc.get_head()))return false;
return equals_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type
>::compare(c.get_tail(),v,vc.get_tail());
}
static bool compare(const ValCons& vc,const KeyCons& c,const Value& v)
{
if(!(vc.get_head()==c.get_head()(v)))return false;
return equals_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type
>::compare(vc.get_tail(),c.get_tail(),v);
}
};
template<typename KeyCons,typename Value,typename ValCons>
struct equals_ckey_cval:
mpl::if_<
mpl::or_<
is_same<KeyCons,tuples::null_type>,
is_same<ValCons,tuples::null_type>
>,
equals_ckey_cval_terminal<KeyCons,Value,ValCons>,
equals_ckey_cval_normal<KeyCons,Value, ValCons>
>::type
{
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct less_ckey_ckey; /* fwd decl. */
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct less_ckey_ckey_terminal
{
static bool compare(
const KeyCons1&,const Value1&,const KeyCons2&,const Value2&)
{
return false;
}
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct less_ckey_ckey_normal
{
static bool compare(
const KeyCons1& c0,const Value1& v0,
const KeyCons2& c1,const Value2& v1)
{
if(c0.get_head()(v0)<c1.get_head()(v1))return true;
if(c1.get_head()(v1)<c0.get_head()(v0))return false;
return less_ckey_ckey<
BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2
>::compare(c0.get_tail(),v0,c1.get_tail(),v1);
}
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct less_ckey_ckey:
mpl::if_<
mpl::or_<
is_same<KeyCons1,tuples::null_type>,
is_same<KeyCons2,tuples::null_type>
>,
less_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2>,
less_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2>
>::type
{
};
template<typename KeyCons,typename Value,typename ValCons>
struct less_ckey_cval; /* fwd decl. */
template<typename KeyCons,typename Value,typename ValCons>
struct less_ckey_cval_terminal
{
static bool compare(const KeyCons&,const Value&,const ValCons&)
{
return false;
}
static bool compare(const ValCons&,const KeyCons&,const Value&)
{
return false;
}
};
template<typename KeyCons,typename Value,typename ValCons>
struct less_ckey_cval_normal
{
static bool compare(const KeyCons& c,const Value& v,const ValCons& vc)
{
if(c.get_head()(v)<vc.get_head())return true;
if(vc.get_head()<c.get_head()(v))return false;
return less_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type
>::compare(c.get_tail(),v,vc.get_tail());
}
static bool compare(const ValCons& vc,const KeyCons& c,const Value& v)
{
if(vc.get_head()<c.get_head()(v))return true;
if(c.get_head()(v)<vc.get_head())return false;
return less_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type
>::compare(vc.get_tail(),c.get_tail(),v);
}
};
template<typename KeyCons,typename Value,typename ValCons>
struct less_ckey_cval:
mpl::if_<
mpl::or_<
is_same<KeyCons,tuples::null_type>,
is_same<ValCons,tuples::null_type>
>,
less_ckey_cval_terminal<KeyCons,Value,ValCons>,
less_ckey_cval_normal<KeyCons,Value,ValCons>
>::type
{
};
template
<
typename KeyCons1,typename Value1,
typename KeyCons2, typename Value2,
typename CompareCons
>
struct compare_ckey_ckey; /* fwd decl. */
template
<
typename KeyCons1,typename Value1,
typename KeyCons2, typename Value2,
typename CompareCons
>
struct compare_ckey_ckey_terminal
{
static bool compare(
const KeyCons1&,const Value1&,
const KeyCons2&,const Value2&,
const CompareCons&)
{
return false;
}
};
template
<
typename KeyCons1,typename Value1,
typename KeyCons2, typename Value2,
typename CompareCons
>
struct compare_ckey_ckey_normal
{
static bool compare(
const KeyCons1& c0,const Value1& v0,
const KeyCons2& c1,const Value2& v1,
const CompareCons& comp)
{
if(comp.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return true;
if(comp.get_head()(c1.get_head()(v1),c0.get_head()(v0)))return false;
return compare_ckey_ckey<
BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
BOOST_DEDUCED_TYPENAME CompareCons::tail_type
>::compare(c0.get_tail(),v0,c1.get_tail(),v1,comp.get_tail());
}
};
template
<
typename KeyCons1,typename Value1,
typename KeyCons2, typename Value2,
typename CompareCons
>
struct compare_ckey_ckey:
mpl::if_<
mpl::or_<
is_same<KeyCons1,tuples::null_type>,
is_same<KeyCons2,tuples::null_type>
>,
compare_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>,
compare_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>
>::type
{
};
template
<
typename KeyCons,typename Value,
typename ValCons,typename CompareCons
>
struct compare_ckey_cval; /* fwd decl. */
template
<
typename KeyCons,typename Value,
typename ValCons,typename CompareCons
>
struct compare_ckey_cval_terminal
{
static bool compare(
const KeyCons&,const Value&,const ValCons&,const CompareCons&)
{
return false;
}
static bool compare(
const ValCons&,const KeyCons&,const Value&,const CompareCons&)
{
return false;
}
};
template
<
typename KeyCons,typename Value,
typename ValCons,typename CompareCons
>
struct compare_ckey_cval_normal
{
static bool compare(
const KeyCons& c,const Value& v,const ValCons& vc,
const CompareCons& comp)
{
if(comp.get_head()(c.get_head()(v),vc.get_head()))return true;
if(comp.get_head()(vc.get_head(),c.get_head()(v)))return false;
return compare_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type,
BOOST_DEDUCED_TYPENAME CompareCons::tail_type
>::compare(c.get_tail(),v,vc.get_tail(),comp.get_tail());
}
static bool compare(
const ValCons& vc,const KeyCons& c,const Value& v,
const CompareCons& comp)
{
if(comp.get_head()(vc.get_head(),c.get_head()(v)))return true;
if(comp.get_head()(c.get_head()(v),vc.get_head()))return false;
return compare_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type,
BOOST_DEDUCED_TYPENAME CompareCons::tail_type
>::compare(vc.get_tail(),c.get_tail(),v,comp.get_tail());
}
};
template
<
typename KeyCons,typename Value,
typename ValCons,typename CompareCons
>
struct compare_ckey_cval:
mpl::if_<
mpl::or_<
is_same<KeyCons,tuples::null_type>,
is_same<ValCons,tuples::null_type>
>,
compare_ckey_cval_terminal<KeyCons,Value,ValCons,CompareCons>,
compare_ckey_cval_normal<KeyCons,Value,ValCons,CompareCons>
>::type
{
};
} /* namespace multi_index::detail */
/* composite_key_result */
template<typename CompositeKey>
struct composite_key_result
{
typedef CompositeKey composite_key_type;
typedef typename composite_key_type::value_type value_type;
composite_key_result(
const composite_key_type& composite_key_,const value_type& value_):
composite_key(composite_key_),value(value_)
{}
const composite_key_type& composite_key;
const value_type& value;
};
/* composite_key */
template<
typename Value,
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,KeyFromValue)
>
struct composite_key:
private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)>
{
private:
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)> super;
public:
typedef super key_extractor_tuple;
typedef Value value_type;
typedef composite_key_result<composite_key> result_type;
composite_key(
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,KeyFromValue)):
super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
{}
composite_key(const key_extractor_tuple& x):super(x){}
const key_extractor_tuple& key_extractors()const{return *this;}
key_extractor_tuple& key_extractors(){return *this;}
template<typename ChainedPtr>
result_type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
result_type operator()(const value_type& x)const
{
return result_type(*this,x);
}
result_type operator()(const reference_wrapper<const value_type>& x)const
{
return result_type(*this,x.get());
}
result_type operator()(const reference_wrapper<value_type>& x)const
{
return result_type(*this,x.get());
}
};
/* comparison operators */
/* == */
template<typename CompositeKey1,typename CompositeKey2>
inline bool operator==(
const composite_key_result<CompositeKey1>& x,
const composite_key_result<CompositeKey2>& y)
{
typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
typedef typename CompositeKey1::value_type value_type1;
typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
typedef typename CompositeKey2::value_type value_type2;
BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple1>::value==
tuples::length<key_extractor_tuple2>::value);
return detail::equals_ckey_ckey<
key_extractor_tuple1,value_type1,
key_extractor_tuple2,value_type2
>::compare(
x.composite_key.key_extractors(),x.value,
y.composite_key.key_extractors(),y.value);
}
template<
typename CompositeKey,
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
>
inline bool operator==(
const composite_key_result<CompositeKey>& x,
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple>::value==
tuples::length<key_tuple>::value);
return detail::equals_ckey_cval<key_extractor_tuple,value_type,key_tuple>::
compare(x.composite_key.key_extractors(),x.value,y);
}
template
<
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
typename CompositeKey
>
inline bool operator==(
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
const composite_key_result<CompositeKey>& y)
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple>::value==
tuples::length<key_tuple>::value);
return detail::equals_ckey_cval<key_extractor_tuple,value_type,key_tuple>::
compare(x,y.composite_key.key_extractors(),y.value);
}
/* < */
template<typename CompositeKey1,typename CompositeKey2>
inline bool operator<(
const composite_key_result<CompositeKey1>& x,
const composite_key_result<CompositeKey2>& y)
{
typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
typedef typename CompositeKey1::value_type value_type1;
typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
typedef typename CompositeKey2::value_type value_type2;
return detail::less_ckey_ckey<
key_extractor_tuple1,value_type1,
key_extractor_tuple2,value_type2
>::compare(
x.composite_key.key_extractors(),x.value,
y.composite_key.key_extractors(),y.value);
}
template
<
typename CompositeKey,
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
>
inline bool operator<(
const composite_key_result<CompositeKey>& x,
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
return detail::less_ckey_cval<key_extractor_tuple,value_type,key_tuple>::
compare(x.composite_key.key_extractors(),x.value,y);
}
template
<
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
typename CompositeKey
>
inline bool operator<(
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
const composite_key_result<CompositeKey>& y)
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
return detail::less_ckey_cval<key_extractor_tuple,value_type,key_tuple>::
compare(x,y.composite_key.key_extractors(),y.value);
}
/* rest of comparison operators */
#define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2) \
template<t1,t2> inline bool operator!=(const a1& x,const a2& y) \
{ \
return !(x==y); \
} \
\
template<t1,t2> inline bool operator>(const a1& x,const a2& y) \
{ \
return y<x; \
} \
\
template<t1,t2> inline bool operator>=(const a1& x,const a2& y) \
{ \
return !(x<y); \
} \
\
template<t1,t2> inline bool operator<=(const a1& x,const a2& y) \
{ \
return !(y<x); \
}
BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
typename CompositeKey1,
typename CompositeKey2,
composite_key_result<CompositeKey1>,
composite_key_result<CompositeKey2>
)
BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
typename CompositeKey,
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
composite_key_result<CompositeKey>,
tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>
)
BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
typename CompositeKey,
tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>,
composite_key_result<CompositeKey>
)
/* composite_key_compare */
template
<
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Compare)
>
struct composite_key_compare:
private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)>
{
private:
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)> super;
public:
typedef super key_comp_tuple;
composite_key_compare(
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Compare)):
super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
{}
composite_key_compare(const key_comp_tuple& x):super(x){}
const key_comp_tuple& key_comps()const{return *this;}
key_comp_tuple& key_comps(){return *this;}
template<typename CompositeKey1,typename CompositeKey2>
bool operator()(
const composite_key_result<CompositeKey1> & x,
const composite_key_result<CompositeKey2> & y)const
{
typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
typedef typename CompositeKey1::value_type value_type1;
typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
typedef typename CompositeKey2::value_type value_type2;
BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple1>::value<=
tuples::length<key_comp_tuple>::value||
tuples::length<key_extractor_tuple2>::value<=
tuples::length<key_comp_tuple>::value);
return detail::compare_ckey_ckey<
key_extractor_tuple1,value_type1,
key_extractor_tuple2,value_type2,
key_comp_tuple
>::compare(
x.composite_key.key_extractors(),x.value,
y.composite_key.key_extractors(),y.value,
key_comps());
}
template
<
typename CompositeKey,
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
>
bool operator()(
const composite_key_result<CompositeKey>& x,
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple>::value<=
tuples::length<key_comp_tuple>::value||
tuples::length<key_tuple>::value<=
tuples::length<key_comp_tuple>::value);
return detail::compare_ckey_cval<
key_extractor_tuple,value_type,
key_tuple,key_comp_tuple
>::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
}
template
<
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
typename CompositeKey
>
bool operator()(
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
const composite_key_result<CompositeKey>& y)const
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
BOOST_STATIC_ASSERT(
tuples::length<key_tuple>::value<=
tuples::length<key_comp_tuple>::value||
tuples::length<key_extractor_tuple>::value<=
tuples::length<key_comp_tuple>::value);
return detail::compare_ckey_cval<
key_extractor_tuple,value_type,
key_tuple,key_comp_tuple
>::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
}
};
/* composite_key_compare_less is merely a composite_key_compare
* instantiation with the corresponding std::less<> comparison
* predicates for each key extractor. Useful as a substitute for
* std::less<CompositeKey::result_type> when the compiler does not
* support partial specialization.
* Same with composite_key_compare_greater.
*/
#define BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER \
composite_key_compare< \
BOOST_MULTI_INDEX_CK_ENUM( \
BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
/* the argument is a PP list */ \
(detail::nth_composite_key_less, \
(BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
BOOST_PP_NIL))) \
>
template<typename CompositeKeyResult>
struct composite_key_result_less:
BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
{
private:
typedef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER super;
public:
typedef CompositeKeyResult first_argument_type;
typedef first_argument_type second_argument_type;
typedef bool result_type;
using super::operator();
};
#define BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER \
composite_key_compare< \
BOOST_MULTI_INDEX_CK_ENUM( \
BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
/* the argument is a PP list */ \
(detail::nth_composite_key_greater, \
(BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
BOOST_PP_NIL))) \
>
template<typename CompositeKeyResult>
struct composite_key_result_greater:
BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
{
private:
typedef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER super;
public:
typedef CompositeKeyResult first_argument_type;
typedef first_argument_type second_argument_type;
typedef bool result_type;
using super::operator();
};
} /* namespace multi_index */
} /* namespace boost */
/* Specialization of std::less and std::greater for composite_key_results
* enabling comparison with tuples of values.
*/
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace std{
template<typename CompositeKey>
struct less<boost::multi_index::composite_key_result<CompositeKey> >:
boost::multi_index::composite_key_result_less<
boost::multi_index::composite_key_result<CompositeKey>
>
{
};
template<typename CompositeKey>
struct greater<boost::multi_index::composite_key_result<CompositeKey> >:
boost::multi_index::composite_key_result_greater<
boost::multi_index::composite_key_result<CompositeKey>
>
{
};
} /* namespace std */
#endif
#undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
#undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
#undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
#undef BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N
#undef BOOST_MULTI_INDEX_CK_CTOR_ARG
#undef BOOST_MULTI_INDEX_CK_TEMPLATE_PARM
#undef BOOST_MULTI_INDEX_CK_ENUM_PARAMS
#undef BOOST_MULTI_INDEX_CK_ENUM
#undef BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE
#endif

View File

@ -0,0 +1,39 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_ACCESS_SPECIFIER_HPP
#define BOOST_MULTI_INDEX_DETAIL_ACCESS_SPECIFIER_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
/* In those compilers that do not accept the member template friend syntax,
* some protected and private sections might need to be specified as
* public.
*/
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
#define BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS protected
#define BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS private
#else
#define BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS public
#define BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS public
#endif
/* GCC does not correctly support in-class using declarations for template
* functions. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9810
*/
#if BOOST_WORKAROUND(__GNUC__, <3)||\
BOOST_WORKAROUND(__GNUC__,==3)&&(__GNUC_MINOR__<4)
#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
#endif
#endif

View File

@ -0,0 +1,213 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_ALLOCATOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_ALLOCATOR_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <cstddef>
#include <new>
namespace boost{
namespace multi_index{
namespace detail{
/* allocator adaption layer */
namespace allocator{
/* Detects whether a given allocator is from old Dinkumware's stdlib,
* which lacks rebind and uses an ugly _Charalloc memfun as a poor
* replacement.
* Note that it does not suffice to check the Boost.Config stdlib
* macros, as the user might have passed a custom, compliant allocator.
*/
#if defined(BOOST_DINKUMWARE_STDLIB)&&defined(BOOST_NO_STD_ALLOCATOR)
template<typename Allocator>
struct dinkumware_defective_allocator
{
BOOST_STATIC_CONSTANT(bool,
value=(
is_same<
Allocator,
std::allocator<BOOST_DEDUCED_TYPENAME Allocator::value_type>
>::value));
};
#else
template<typename Allocator>
struct dinkumware_defective_allocator
{
BOOST_STATIC_CONSTANT(bool,value=false);
};
#endif
/* allocator ops for Dinkumware's defective allocator */
template<typename Allocator,typename Type>
struct dinkumware_defective_allocator_ops
{
typedef Allocator rebound_type;
static Type* allocate(Allocator& al,typename Allocator::size_type n)
{
return static_cast<Type*>(
static_cast<void*>(al._Charalloc(n*sizeof(Type))));
}
static void deallocate(Allocator& al,Type* p,typename Allocator::size_type n)
{
al.deallocate(p,n);
}
static void construct(Allocator&,Type* p,const Type& t)
{
new(static_cast<void*>(p))Type(t);
}
static void destroy(Allocator&,Type* p)
{
(static_cast<Type*>(p))->~Type();
}
};
/* allocator ops for compliant allocators */
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
/* Workaround for a problem in MSVC with dependent template typedefs
* when doing rebinding of allocators.
* Modeled after <boost/mpl/aux_/msvc_dtw.hpp> (thanks, Aleksey!)
*/
template<typename Allocator>
struct msvc_rebind
{
template<bool> struct fake_allocator:Allocator{};
template<> struct fake_allocator<true>
{
template<typename Typename> struct rebind{};
};
template<typename Type>
struct result:
fake_allocator<mpl::aux::msvc_never_true<Allocator>::value>::
template rebind<Type>
{
};
};
#endif
template<typename Allocator,typename Type>
struct compliant_allocator_ops
{
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef typename msvc_rebind<Allocator>::
template result<Type>::other rebound_type;
#else
typedef typename Allocator::
BOOST_NESTED_TEMPLATE rebind<Type>::other rebound_type;
#endif
static Type* allocate(Allocator& al,typename Allocator::size_type n)
{
return al.allocate(n);
}
static void deallocate(Allocator& al,Type* p,typename Allocator::size_type n)
{
al.deallocate(p,n);
}
static void construct(Allocator& al,Type *p,const Type& t)
{
al.construct(p,t);
}
static void destroy(Allocator& al,Type* p)
{
al.destroy(p);
}
};
template<typename Allocator,typename Type>
struct allocator_ops:
mpl::if_c<
dinkumware_defective_allocator<Allocator>::value,
dinkumware_defective_allocator_ops<Allocator,Type>,
compliant_allocator_ops<Allocator,Type>
>::type
{
};
/* allocator ops front end */
template<typename Allocator,typename Type>
struct rebind_to
{
typedef typename allocator_ops<Allocator,Type>::rebound_type type;
};
template<typename Type,typename Allocator>
Type* allocate(
Allocator& al,typename Allocator::size_type n
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Type))
{
return allocator_ops<Allocator,Type>::allocate(al,n);
}
template<typename Allocator,typename Type>
void deallocate(Allocator& al,Type* p,typename Allocator::size_type n)
{
allocator_ops<Allocator,Type>::deallocate(al,p,n);
}
template<typename Allocator,typename Type>
void construct(Allocator& al,Type* p,const Type& t)
{
allocator_ops<Allocator,Type>::construct(al,p,t);
}
template<typename Allocator,typename Type>
void destroy(Allocator& al,Type* p)
{
allocator_ops<Allocator,Type>::destroy(al,p);
}
/* allocator-independent versions of construct and destroy */
template<typename Type>
void construct(void* p,const Type& t)
{
new (p) Type(t);
}
template<typename Type>
void destroy(const Type* p)
{
p->~Type();
}
} /* namespace multi_index::detail::allocator */
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,64 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_AUTO_SPACE_HPP
#define BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_HPP
#include <boost/noncopyable.hpp>
#include <boost/multi_index/detail/allocator.hpp>
#include <memory>
namespace boost{
namespace multi_index{
namespace detail{
/* auto_space provides uninitialized space suitably to store
* a given number of elements of a given type.
*/
/* NB: it is not clear whether using an allocator to handle
* zero-sized arrays of elements is conformant or not. GCC 3.3.1
* and prior fail here, other stdlibs handle the issue gracefully.
* To be on the safe side, the case n==0 is given special treatment.
* References:
* GCC Bugzilla, "standard allocator crashes when deallocating segment
* "of zero length", http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14176
* C++ Standard Library Defect Report List (Revision 28), issue 199
* "What does allocate(0) return?",
* http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#199
*/
template<typename T,typename Allocator=std::allocator<T> >
struct auto_space:private noncopyable
{
explicit auto_space(const Allocator& al=Allocator(),std::size_t n=1):
al_(al),n_(n),data_(n_?allocator::allocate<T>(al_,n_):0)
{}
~auto_space()
{
if(n_)allocator::deallocate(al_,data_,n_);
}
T* data()const{return data_;}
private:
typename allocator::rebind_to<Allocator,T>::type al_;
std::size_t n_;
T* data_;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,81 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_BASE_TYPE_HPP
#define BOOST_MULTI_INDEX_DETAIL_BASE_TYPE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#include <boost/mpl/bind.hpp>
#include <boost/mpl/iter_fold_backward.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/multi_index/detail/header_holder.hpp>
#include <boost/multi_index/detail/index_base.hpp>
#include <boost/multi_index/detail/is_index_list.hpp>
#include <boost/multi_index/detail/msvc_index_specifier.hpp>
#include <boost/multi_index/ordered_index_fwd.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/static_assert.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* MPL machinery to construct a linear hierarchy of indices out of
* a index list.
*/
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
struct index_applier
{
template<typename IndexSpecifierIterator,typename Super>
struct apply:
msvc_index_specifier<IndexSpecifierIterator::type>::
template result_index_class<Super>
{
};
};
#else
struct index_applier
{
template<typename IndexSpecifierIterator,typename Super>
struct apply:IndexSpecifierIterator::type::
BOOST_NESTED_TEMPLATE index_class<Super>
{
};
};
#endif
template<typename Value,typename IndexSpecifierList,typename Allocator>
struct multi_index_base_type
{
BOOST_STATIC_ASSERT(detail::is_index_list<IndexSpecifierList>::value);
typedef typename prevent_eti<
multi_index_container<Value,IndexSpecifierList,Allocator>,
typename mpl::iter_fold_backward<
IndexSpecifierList,
index_base<Value,IndexSpecifierList,Allocator>,
mpl::bind2<
index_applier,
mpl::_2,
mpl::_1
>
>::type
>::type type;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,48 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_CONVERTER_HPP
#define BOOST_MULTI_INDEX_DETAIL_CONVERTER_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* converter offers means to access indices of a given multi_index_container
* and for convertibilty between index iterators, so providing a
* localized access point for get() and project() functions.
*/
template<typename MultiIndexContainer,typename Index>
struct converter
{
static const Index& index(const MultiIndexContainer& x){return x;}
static Index& index(MultiIndexContainer& x){return x;}
static typename Index::const_iterator const_iterator(
const MultiIndexContainer& x,typename MultiIndexContainer::node_type* node)
{
return x.Index::make_iterator(node);
}
static typename Index::iterator iterator(
MultiIndexContainer& x,typename MultiIndexContainer::node_type* node)
{
return x.Index::make_iterator(node);
}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,127 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_COPY_MAP_HPP
#define BOOST_MULTI_INDEX_DETAIL_COPY_MAP_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
/* copy_map is used as an auxiliary structure during copy_() operations.
* When a container with n nodes is replicated, node_map holds the pairings
* between original and copied nodes, and provides a fast way to find a
* copied node from an original one.
* The semantics of the class are not simple, and no attempt has been made
* to enforce it: multi_index_container handles it right. On the other hand,
* the const interface, which is the one provided to index implementations,
* only allows for:
* - Enumeration of pairs of (original,copied) nodes (excluding the headers),
* - fast retrieval of copied nodes (including the headers.)
*/
template <typename Node>
struct copy_map_entry
{
copy_map_entry(Node* f,Node* s):first(f),second(s){}
Node* first;
Node* second;
bool operator<(const copy_map_entry<Node>& x)const
{
return std::less<Node*>()(first,x.first);
}
};
template <typename Node,typename Allocator>
class copy_map:private noncopyable
{
public:
typedef const copy_map_entry<Node>* const_iterator;
copy_map(
const Allocator al,std::size_t size,Node* header_org,Node* header_cpy):
al_(al),size_(size),spc(al_,size_),n(0),
header_org_(header_org),header_cpy_(header_cpy),released(false)
{}
~copy_map()
{
if(!released){
for(std::size_t i=0;i<n;++i){
allocator::destroy(&spc.data()[i].second->value);
deallocate(spc.data()[i].second);
}
}
}
const_iterator begin()const{return &spc.data()[0];}
const_iterator end()const{return &spc.data()[n];}
void clone(Node* node)
{
spc.data()[n].first=node;
spc.data()[n].second=allocator::allocate<Node>(al_,1);
BOOST_TRY{
allocator::construct(&spc.data()[n].second->value,node->value);
}
BOOST_CATCH(...){
deallocate(spc.data()[n].second);
BOOST_RETHROW;
}
BOOST_CATCH_END
++n;
if(n==size_)std::sort(&spc.data()[0],&spc.data()[size_]);
}
Node* find(Node* node)const
{
if(node==header_org_)return header_cpy_;
return std::lower_bound(
&spc.data()[0],&spc.data()[n],copy_map_entry<Node>(node,0))->second;
};
void release()
{
released=true;
}
private:
typename 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;
void deallocate(Node* node)
{
allocator::deallocate(al_,node,1);
}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,55 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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
#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

View File

@ -0,0 +1,38 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_HAS_TAG_HPP
#define BOOST_MULTI_INDEX_DETAIL_HAS_TAG_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/contains.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* determines whether an index type has a given tag in its tag list */
template<typename Tag>
struct has_tag
{
template<typename Index>
struct apply:mpl::contains<BOOST_DEDUCED_TYPENAME Index::tag_list,Tag>
{
};
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,49 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_HEADER_HOLDER_HPP
#define BOOST_MULTI_INDEX_DETAIL_HEADER_HOLDER_HPP
#include <boost/noncopyable.hpp>
#include <boost/utility/base_from_member.hpp>
namespace boost{
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
* 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
{
header_holder():super(final().allocate_node()){}
~header_holder(){final().deallocate_node(super::member);}
private:
typedef base_from_member<NodeType*> super;
Final& final(){return *static_cast<Final*>(this);}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,133 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_BASE_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_BASE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/call_traits.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/multi_index/detail/copy_map.hpp>
#include <boost/multi_index/detail/node_type.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/tuple/tuple.hpp>
#include <utility>
namespace boost{
namespace multi_index{
namespace detail{
/* The role of this class is threefold:
* - tops the linear hierarchy of indices.
* - terminates some cascading backbone function calls (insert_, etc.),
* - grants access to the backbone functions of the final
* multi_index_container class (for access restriction reasons, these
* cannot be called directly from the index classes.)
*/
template<typename Value,typename IndexSpecifierList,typename Allocator>
class index_base
{
protected:
typedef index_node_base<Value> node_type;
typedef typename multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type final_node_type;
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> final_type;
typedef tuples::null_type ctor_args_list;
typedef Allocator final_allocator_type;
typedef mpl::vector0<> index_type_list;
typedef mpl::vector0<> iterator_type_list;
typedef mpl::vector0<> const_iterator_type_list;
typedef copy_map<final_node_type,Allocator> copy_map_type;
private:
typedef typename call_traits<Value>::param_type value_param_type;
protected:
explicit index_base(const ctor_args_list&,const Allocator&){}
void copy_(
const index_base<Value,IndexSpecifierList,Allocator>&,const copy_map_type&)
{}
node_type* insert_(value_param_type v,node_type* x)
{
detail::allocator::construct(&x->value,v);
return x;
}
node_type* insert_(value_param_type v,node_type*,node_type* x)
{
detail::allocator::construct(&x->value,v);
return x;
}
void erase_(node_type* x)
{
detail::allocator::destroy(&x->value);
}
void swap_(index_base<Value,IndexSpecifierList,Allocator>&){}
bool replace_(value_param_type v,node_type* x)
{
x->value=v;
return true;
}
bool modify_(node_type*){return true;}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
bool invariant_()const{return true;}
#endif
/* access to backbone memfuns of Final class */
final_type& final(){return *static_cast<final_type*>(this);}
const final_type& final()const{return *static_cast<const final_type*>(this);}
final_node_type* final_header()const{return final().header();}
bool final_empty_()const{return final().empty_();}
std::size_t final_size_()const{return final().size_();}
std::size_t final_max_size_()const{return final.max_size_();}
std::pair<final_node_type*,bool> final_insert_(value_param_type x)
{return final().insert_(x);}
std::pair<final_node_type*,bool> final_insert_(
value_param_type x,final_node_type* position)
{return final().insert_(x,position);}
void final_erase_(final_node_type* x){final().erase_(x);}
void final_swap_(final_type& x){final().swap_(x);}
bool final_replace_(
value_param_type k,final_node_type* x)
{return final().replace_(k,x);}
template<typename Modifier>
bool final_modify_(Modifier mod,final_node_type* x)
{return final().modify_(mod,x);}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
void final_check_invariant_()const{final().check_invariant_();}
#endif
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,140 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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
#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>
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)
{
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;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,40 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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
#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

View File

@ -0,0 +1,39 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_NODE_BASE_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_NODE_BASE_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* index_node_base tops the node hierarchy of multi_index_container. It holds
* the value of the element contained.
*/
template<typename Value>
struct index_node_base
{
typedef Value value_type;
value_type value;
private:
index_node_base();
/* this class is not intended to be cted, merely allocated */
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,78 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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(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

View File

@ -0,0 +1,17 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_INVARIANT_ASSERT_HPP
#define BOOST_MULTI_INDEX_DETAIL_INVARIANT_ASSERT_HPP
#if !defined(BOOST_MULTI_INDEX_INVARIANT_ASSERT)
#include <boost/assert.hpp>
#define BOOST_MULTI_INDEX_INVARIANT_ASSERT BOOST_ASSERT
#endif
#endif

View File

@ -0,0 +1,36 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_IS_INDEX_LIST_HPP
#define BOOST_MULTI_INDEX_DETAIL_IS_INDEX_LIST_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/empty.hpp>
#include <boost/mpl/is_sequence.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename T>
struct is_index_list
{
BOOST_STATIC_CONSTANT(bool,mpl_sequence=mpl::is_sequence<T>::value);
BOOST_STATIC_CONSTANT(bool,non_empty=!mpl::empty<T>::value);
BOOST_STATIC_CONSTANT(bool,value=mpl_sequence&&non_empty);
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,45 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_MODIFY_KEY_ADAPTOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_MODIFY_KEY_ADAPTOR_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* Functional adaptor to resolve modify_key as a call to modify.
* Preferred over compose_f_gx and stuff cause it eliminates problems
* with references to references, dealing with function pointers, etc.
*/
template<typename Modifier,typename Value,typename KeyFromValue>
struct modify_key_adaptor
{
modify_key_adaptor(Modifier mod_,KeyFromValue kfv_):mod(mod_),kfv(kfv_){}
void operator()(Value& x)
{
mod(kfv(x));
}
private:
Modifier mod;
KeyFromValue kfv;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,65 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_MSVC_INDEX_SPECIFIER_HPP
#define BOOST_MULTI_INDEX_DETAIL_MSVC_INDEX_SPECIFIER_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
/* Workaround for a problem in MSVC with dependent template typedefs
* when accesing index specifiers.
* Modeled after <boost/mpl/aux_/msvc_dtw.hpp> (thanks, Aleksey!)
*/
#include <boost/mpl/aux_/msvc_never_true.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename IndexSpecifier>
struct msvc_index_specifier
{
template<bool> struct fake_index_type:IndexSpecifier{};
template<> struct fake_index_type<true>
{
template<typename Super>
struct node_class{};
template<typename Super>
struct index_class{};
};
template<typename Super>
struct result_node_class:
fake_index_type<mpl::aux::msvc_never_true<IndexSpecifier>::value>::
template node_class<Super>
{
};
template<typename Super>
struct result_index_class:
fake_index_type<mpl::aux::msvc_never_true<IndexSpecifier>::value>::
template index_class<Super>
{
};
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* workaround */
#endif

View File

@ -0,0 +1,93 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_NO_DUPLICATE_TAGS_HPP
#define BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/fold.hpp>
#include <boost/mpl/set/set0.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* no_duplicate_tags check at compile-time that a tag list
* has no duplicate tags.
* The algorithm deserves some explanation: tags
* are sequentially inserted into a mpl::set if they were
* not already present. Due to the magic of mpl::set
* (mpl::has_key is contant time), this operation takes linear
* time, and even MSVC++ 6.5 handles it gracefully (other obvious
* solutions are quadratic.)
*/
struct duplicate_tag_mark{};
struct duplicate_tag_marker
{
template <typename MplSet,typename Tag>
struct apply
{
typedef mpl::s_item<
typename mpl::if_<mpl::has_key<MplSet,Tag>,duplicate_tag_mark,Tag>::type,
MplSet
> type;
};
};
template<typename TagList>
struct no_duplicate_tags
{
typedef typename mpl::fold<
TagList,
mpl::set0<>,
duplicate_tag_marker
>::type aux;
BOOST_STATIC_CONSTANT(
bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value));
};
/* Variant for an index list: duplication is checked
* across all the indices.
*/
struct duplicate_tag_list_marker
{
template <typename MplSet,typename Index>
struct apply:mpl::fold<
BOOST_DEDUCED_TYPENAME Index::tag_list,
MplSet,
duplicate_tag_marker>
{
};
};
template<typename IndexList>
struct no_duplicate_tags_in_index_list
{
typedef typename mpl::fold<
IndexList,
mpl::set0<>,
duplicate_tag_list_marker
>::type aux;
BOOST_STATIC_CONSTANT(
bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value));
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,73 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_NODE_TYPE_HPP
#define BOOST_MULTI_INDEX_DETAIL_NODE_TYPE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#include <boost/mpl/bind.hpp>
#include <boost/mpl/iter_fold_backward.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/multi_index/detail/header_holder.hpp>
#include <boost/multi_index/detail/index_node_base.hpp>
#include <boost/multi_index/detail/is_index_list.hpp>
#include <boost/multi_index/detail/msvc_index_specifier.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/static_assert.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* MPL machinery to construct the internal node type associated to an
* index list.
*/
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
struct index_node_applier
{
template<typename IndexSpecifierIterator,typename Super>
struct apply:
msvc_index_specifier<IndexSpecifierIterator::type>::
template result_node_class<Super>
{
};
};
#else
struct index_node_applier
{
template<typename IndexSpecifierIterator,typename Super>
struct apply:IndexSpecifierIterator::type::
BOOST_NESTED_TEMPLATE node_class<Super>
{
};
};
#endif
template<typename Value,typename IndexSpecifierList,typename Allocator>
struct multi_index_node_type
{
BOOST_STATIC_ASSERT(detail::is_index_list<IndexSpecifierList>::value);
typedef typename mpl::iter_fold_backward<
IndexSpecifierList,
index_node_base<Value>,
mpl::bind2<index_node_applier,mpl::_2,mpl::_1>
>::type type;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,86 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_ORD_INDEX_ARGS_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_ARGS_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
/* Oredered index specifiers can be instantiated in two forms:
*
* (ordered_unique|ordered_non_unique)<
* KeyFromValue,Compare=std::less<KeyFromValue::result_type> >
* (ordered_unique|ordered_non_unique)<
* TagList,KeyFromValue,Compare=std::less<KeyFromValue::result_type> >
*
* index_args implements the machinery to accept this argument-dependent
* polymorphism.
*/
struct null_arg{};
template<typename T>
struct not_is_null_arg
{
BOOST_STATIC_CONSTANT(bool,value=!(is_same<null_arg,T>::value));
};
template<typename KeyFromValue>
struct index_args_default_compare
{
typedef std::less<typename KeyFromValue::result_type> type;
};
template<typename Arg1,typename Arg2,typename Arg3>
struct ordered_index_args
{
typedef is_tag<Arg1> full_form;
typedef typename mpl::if_<
full_form,
Arg1,
tag< > >::type tag_list_type;
typedef typename mpl::if_<
full_form,
Arg2,
Arg1>::type key_from_value_type;
typedef typename mpl::if_<
full_form,
Arg3,
Arg2>::type supplied_compare_type;
typedef typename mpl::apply_if<
is_same<supplied_compare_type,null_arg>,
index_args_default_compare<key_from_value_type>,
mpl::identity<supplied_compare_type>
>::type compare_type;
BOOST_STATIC_ASSERT(is_tag<tag_list_type>::value);
BOOST_STATIC_ASSERT(not_is_null_arg<key_from_value_type>::value);
BOOST_STATIC_ASSERT(not_is_null_arg<compare_type>::value);
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,457 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*
* The internal implementation of red-black trees is based on that of SGI STL
* stl_tree.h file:
*
* Copyright (c) 1996,1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
#include <algorithm>
#include <cstddef>
namespace boost{
namespace multi_index{
namespace detail{
/* definition of red-black nodes for ordered_index */
enum ordered_index_color{red=false,black=true};
struct ordered_index_node_impl
{
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_;}
/* interoperability with index_iterator */
static void increment(ordered_index_node_impl*& x)
{
if(x->right()){
x=x->right();
while(x->left())x=x->left();
}
else{
ordered_index_node_impl* y=x->parent();
while(x==y->right()){
x=y;
y=y->parent();
}
if(x->right()!=y)x=y;
}
}
static void decrement(ordered_index_node_impl*& 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();
x=y;
}else{
ordered_index_node_impl* y=x->parent();
while(x==y->left()){
x=y;
y=y->parent();
}
x=y;
}
}
/* 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)
{
ordered_index_node_impl* y=x->right();
x->right()=y->left();
if(y->left())y->left()->parent()=x;
y->parent()=x->parent();
if(x==root) root=y;
else if(x==x->parent()->left())x->parent()->left()=y;
else x->parent()->right()=y;
y->left()=x;
x->parent()=y;
}
static ordered_index_node_impl* minimum(ordered_index_node_impl* x)
{
while(x->left())x=x->left();
return x;
}
static ordered_index_node_impl* maximum(ordered_index_node_impl* x)
{
while(x->right())x=x->right();
return x;
}
static void rotate_right(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
{
ordered_index_node_impl* y=x->left();
x->left()=y->right();
if(y->right())y->right()->parent()=x;
y->parent()=x->parent();
if(x==root) root=y;
else if(x==x->parent()->right())x->parent()->right()=y;
else x->parent()->left()=y;
y->right()=x;
x->parent()=y;
}
static void rebalance(
ordered_index_node_impl* x,ordered_index_node_impl*& 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){
x->parent()->color()=black;
y->color()=black;
x->parent()->parent()->color()=red;
x=x->parent()->parent();
}
else{
if(x==x->parent()->right()){
x=x->parent();
rotate_left(x,root);
}
x->parent()->color()=black;
x->parent()->parent()->color()=red;
rotate_right(x->parent()->parent(),root);
}
}
else{
ordered_index_node_impl* y=x->parent()->parent()->left();
if(y&&y->color()==red){
x->parent()->color()=black;
y->color()=black;
x->parent()->parent()->color()=red;
x=x->parent()->parent();
}
else{
if(x==x->parent()->left()){
x=x->parent();
rotate_right(x,root);
}
x->parent()->color()=black;
x->parent()->parent()->color()=red;
rotate_left(x->parent()->parent(),root);
}
}
}
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)
{
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 */
}
else{
if(y->right()==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())y=y->left();
x=y->right();
}
}
if(y!=z){
z->left()->parent()=y; /* relink y in place of z. y is z's successor */
y->left()=z->left();
if(y!=z->right()){
x_parent=y->parent();
if(x) x->parent()=y->parent();
y->parent()->left()=x; /* y must be a child of left */
y->right()=z->right();
z->right()->parent()=y;
}
else{
x_parent=y;
}
if(root==z) root=y;
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());
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(root==z){
root=x;
}
else{
if(z->parent()->left()==z)z->parent()->left()=x;
else z->parent()->right()=x;
}
if(leftmost==z){
if(z->right()==0){ /* z->left() must be null also */
leftmost=z->parent();
}
else{
leftmost=minimum(x); /* makes leftmost==header if z==root */
}
}
if(rightmost==z){
if(z->left()==0){ /* z->right() must be null also */
rightmost=z->parent();
}
else{ /* x==z->left() */
rightmost=maximum(x); /* makes rightmost==header if z==root */
}
}
}
if(y->color()!=red){
while(x!=root&&(x==0 || x->color()==black)){
if(x==x_parent->left()){
ordered_index_node_impl* 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)){
w->color()=red;
x=x_parent;
x_parent=x_parent->parent();
}
else{
if(w->right()==0
|| w->right()->color()==black){
if(w->left()) 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;
rotate_left(x_parent,root);
break;
}
}
else{ /* same as above,with right <-> left */
ordered_index_node_impl* 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)){
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;
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;
rotate_right(x_parent,root);
break;
}
}
}
if(x)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)
{
if(next==header){
header->parent()=x;
header->left()=x;
header->right()=x;
x->parent()=header;
}
else if(next->left()==0){
next->left()=x;
x->parent()=next;
if(next==header->left()){
header->left()=x; /* maintain leftmost pointing to min node */
}
}
else{ /* prior->right() must be null */
prior->right()=x;
x->parent()=prior;
if(prior==header->right()){
header->right()=x; /* maintain rightmost pointing to max node */
}
}
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)
{
if(!node)return 0;
std::size_t sum=0;
for(;;){
if(node->color()==black)++sum;
if(node==root)break;
node=node->parent();
}
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{};
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();}
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);}
static ordered_index_node* from_impl(ordered_index_node_impl *x)
{
return static_cast<ordered_index_node*>(static_cast<impl_type*>(x));
}
static const ordered_index_node* from_impl(const ordered_index_node_impl* x)
{
return static_cast<const ordered_index_node*>(
static_cast<const impl_type*>(x));
}
/* interoperability with index_iterator */
static void increment(ordered_index_node*& x)
{
ordered_index_node_impl* xi=x->impl();
impl_type::increment(xi);
x=from_impl(xi);
}
static void decrement(ordered_index_node*& x)
{
ordered_index_node_impl* xi=x->impl();
impl_type::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 */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,121 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*
* The internal implementation of red-black trees is based on that of SGI STL
* stl_tree.h file:
*
* Copyright (c) 1996,1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_OPS_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_OPS_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* Common code for index memfuns having templatized and
* non-templatized versions.
*/
template<
typename Node,typename KeyFromValue,
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_find(
Node* header,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());
}
else z=Node::from_impl(z->right());
}
return (y==header||comp(x,key(y->value)))?header:y;
}
template<
typename Node,typename KeyFromValue,
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_lower_bound(
Node* header,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());
}
else z=Node::from_impl(z->right());
}
return y;
}
template<
typename Node,typename KeyFromValue,
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_upper_bound(
Node* header,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());
}
else z=Node::from_impl(z->right());
}
return y;
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,56 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_PREVENT_ETI_HPP
#define BOOST_MULTI_INDEX_DETAIL_PREVENT_ETI_HPP
#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/mpl/if.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/aux_/msvc_never_true.hpp>
#endif
namespace boost{
namespace multi_index{
namespace detail{
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
/* See
* http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Effective_MPL
* Item 5.6, Beware of the 'early template instantiation' trap.
*/
template<typename Type,typename Construct>
struct prevent_eti
{
typedef typename mpl::if_<
mpl::aux::msvc_never_true<Type>,
mpl::integral_c<int,0>,
Construct
>::type type;
};
#else
template<typename Type,typename Construct>
struct prevent_eti
{
typedef Construct type;
};
#endif
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,339 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_MODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_SAFE_MODE_HPP
#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
* 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.
* Iterators are chained in a single attached list, whose header is
* 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.
* This is not a full-fledged safe mode framework, and is only inteded
* 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.
*/
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;}
inline void detach();
protected:
safe_iterator_base():cont(0),next(0){}
explicit safe_iterator_base(safe_container_base* cont_){attach(cont_);}
safe_iterator_base(const safe_iterator_base& it){attach(it.cont);}
safe_iterator_base& operator=(const safe_iterator_base& it)
{
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&);
#endif
inline void attach(safe_container_base* cont_);
safe_container_base* cont;
safe_iterator_base* next;
};
class safe_container_base:private noncopyable
{
public:
safe_container_base(){}
~safe_container_base()
{
for(safe_iterator_base* it=header.next;it;it=it->next)it->cont=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);
}
BOOST_MULTI_INDEX_PRIVATE_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_iterator_base header;
};
void safe_iterator_base::attach(safe_container_base* cont_)
{
cont=cont_;
if(cont){
next=cont->header.next;
cont->header.next=this;
}
}
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 safe_mode{
/* checking routines */
template<typename Iterator>
inline bool check_valid_iterator(const Iterator& it)
{
return it.valid();
}
template<typename Iterator>
inline bool check_dereferenceable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->end();
}
template<typename Iterator>
inline bool check_incrementable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->end();
}
template<typename Iterator>
inline bool check_decrementable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->begin();
}
template<typename Iterator>
inline bool check_is_owner(
const Iterator& it,const typename Iterator::container_type& cont)
{
return it.valid()&&it.owner()==&cont;
}
template<typename Iterator>
inline bool check_same_owner(const Iterator& it0,const Iterator& it1)
{
return it0.valid()&&it1.valid()&&it0.owner()==it1.owner();
}
template<typename Iterator>
inline bool check_valid_range(const Iterator& it0,const Iterator& it1)
{
if(!it0.valid()||!it1.valid()||it0.owner()!=it1.owner())return false;
Iterator last=it0.owner()->end();
if(it1==last)return true;
for(Iterator first=it0;first!=last;++first){
if(first==it1)return true;
}
return false;
}
template<typename Iterator>
inline bool check_outside_range(
const Iterator& it,const Iterator& it0,const Iterator& it1)
{
if(!it0.valid()||!it1.valid()||it0.owner()!=it1.owner())return false;
Iterator last=it0.owner()->end();
bool found=false;
Iterator first=it0;
for(;first!=last;++first){
if(first==it1)break;
/* crucial that this check goes after previous break */
if(first==it)found=true;
}
if(first!=it1)return false;
return !found;
}
template<typename Container>
inline bool check_different_container(
const Container& cont0,const Container& cont1)
{
return &cont0!=&cont1;
}
} /* namespace multi_index::safe_mode */
} /* namespace multi_index */
} /* namespace boost */
#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

View File

@ -0,0 +1,270 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_SCOPE_GUARD_HPP
#define BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* Until some official version of the ScopeGuard idiom makes it into Boost,
* we locally define our own. This is a merely reformated version of
* 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/
* 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.
* - Added scope_guard_impl_base::touch (see below.)
* - Removed RefHolder and ByRef, whose functionality is provided
* already by Boost.Ref.
* - Removed static make_guard's and make_obj_guard's, so that the code
* will work even if BOOST_NO_MEMBER_TEMPLATES is defined. This forces
* us to move some private ctors to public, though.
*/
class scope_guard_impl_base
{
public:
scope_guard_impl_base():dismissed_(false){}
void dismiss()const{dismissed_=true;}
/* This helps prevent some "unused variable" warnings under, for instance,
* GCC 3.2.
*/
void touch()const{}
protected:
~scope_guard_impl_base(){}
scope_guard_impl_base(const scope_guard_impl_base& other):
dismissed_(other.dismissed_)
{
other.dismiss();
}
template<typename J>
static void safe_execute(J& j){if(!j.dismissed_)j.execute();}
mutable bool dismissed_;
private:
scope_guard_impl_base& operator=(const scope_guard_impl_base&);
};
typedef const scope_guard_impl_base& scope_guard;
template<typename F>
class scope_guard_impl0:public scope_guard_impl_base
{
public:
scope_guard_impl0(F fun):fun_(fun){}
~scope_guard_impl0(){safe_execute(*this);}
void execute(){fun_();}
protected:
F fun_;
};
template<typename F>
inline scope_guard_impl0<F> make_guard(F fun)
{
return scope_guard_impl0<F>(fun);
}
template<typename F,typename P1>
class scope_guard_impl1:public scope_guard_impl_base
{
public:
scope_guard_impl1(F fun,P1 p1):fun_(fun),p1_(p1){}
~scope_guard_impl1(){safe_execute(*this);}
void execute(){fun_(p1_);}
protected:
F fun_;
const P1 p1_;
};
template<typename F,typename P1>
inline scope_guard_impl1<F,P1> make_guard(F fun,P1 p1)
{
return scope_guard_impl1<F,P1>(fun,p1);
}
template<typename F,typename P1,typename P2>
class scope_guard_impl2:public scope_guard_impl_base
{
public:
scope_guard_impl2(F fun,P1 p1,P2 p2):fun_(fun),p1_(p1),p2_(p2){}
~scope_guard_impl2(){safe_execute(*this);}
void execute(){fun_(p1_,p2_);}
protected:
F fun_;
const P1 p1_;
const P2 p2_;
};
template<typename F,typename P1,typename P2>
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<typename F,typename P1,typename P2,typename P3>
class scope_guard_impl3:public scope_guard_impl_base
{
public:
scope_guard_impl3(F fun,P1 p1,P2 p2,P3 p3):fun_(fun),p1_(p1),p2_(p2),p3_(p3){}
~scope_guard_impl3(){safe_execute(*this);}
void execute(){fun_(p1_,p2_,p3_);}
protected:
F fun_;
const P1 p1_;
const P2 p2_;
const P3 p3_;
};
template<typename F,typename P1,typename P2,typename P3>
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<typename F,typename P1,typename P2,typename P3,typename P4>
class scope_guard_impl4:public scope_guard_impl_base
{
public:
scope_guard_impl4(F fun,P1 p1,P2 p2,P3 p3,P4 p4):
fun_(fun),p1_(p1),p2_(p2),p3_(p3),p4_(p4){}
~scope_guard_impl4(){safe_execute(*this);}
void execute(){fun_(p1_,p2_,p3_,p4_);}
protected:
F fun_;
const P1 p1_;
const P2 p2_;
const P3 p3_;
const P4 p4_;
};
template<typename F,typename P1,typename P2,typename P3,typename P4>
inline scope_guard_impl4<F,P1,P2,P3,P4> make_guard(
F fun,P1 p1,P2 p2,P3 p3,P4 p4)
{
return scope_guard_impl4<F,P1,P2,P3,P4>(fun,p1,p2,p3,p4);
}
template<class Obj,typename MemFun>
class obj_scope_guard_impl0:public scope_guard_impl_base
{
public:
obj_scope_guard_impl0(Obj& obj,MemFun mem_fun):obj_(obj),mem_fun_(mem_fun){}
~obj_scope_guard_impl0(){safe_execute(*this);}
void execute(){(obj_.*mem_fun_)();}
protected:
Obj& obj_;
MemFun mem_fun_;
};
template<class Obj,typename MemFun>
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<class Obj,typename MemFun,typename P1>
class obj_scope_guard_impl1:public scope_guard_impl_base
{
public:
obj_scope_guard_impl1(Obj& obj,MemFun mem_fun,P1 p1):
obj_(obj),mem_fun_(mem_fun),p1_(p1){}
~obj_scope_guard_impl1(){safe_execute(*this);}
void execute(){(obj_.*mem_fun_)(p1_);}
protected:
Obj& obj_;
MemFun mem_fun_;
const P1 p1_;
};
template<class Obj,typename MemFun,typename P1>
inline obj_scope_guard_impl1<Obj,MemFun,P1> make_obj_guard(
Obj& obj,MemFun mem_fun,P1 p1)
{
return obj_scope_guard_impl1<Obj,MemFun,P1>(obj,mem_fun,p1);
}
template<class Obj,typename MemFun,typename P1,typename P2>
class obj_scope_guard_impl2:public scope_guard_impl_base
{
public:
obj_scope_guard_impl2(Obj& obj,MemFun mem_fun,P1 p1,P2 p2):
obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2)
{}
~obj_scope_guard_impl2(){safe_execute(*this);}
void execute(){(obj_.*mem_fun_)(p1_,p2_);}
protected:
Obj& obj_;
MemFun mem_fun_;
const P1 p1_;
const P2 p2_;
};
template<class Obj,typename MemFun,typename P1,typename P2>
inline obj_scope_guard_impl2<Obj,MemFun,P1,P2>
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<class Obj,typename MemFun,typename P1,typename P2,typename P3>
class obj_scope_guard_impl3:public scope_guard_impl_base
{
public:
obj_scope_guard_impl3(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3):
obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2),p3_(p3)
{}
~obj_scope_guard_impl3(){safe_execute(*this);}
void execute(){(obj_.*mem_fun_)(p1_,p2_,p3_);}
protected:
Obj& obj_;
MemFun mem_fun_;
const P1 p1_;
const P2 p2_;
const P3 p3_;
};
template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
inline obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>
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);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,197 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_SEQ_INDEX_NODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_NODE_HPP
#include <algorithm>
namespace boost{
namespace multi_index{
namespace detail{
/* doubly-linked node for use by sequenced_index */
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_;}
/* interoperability with index_iterator */
static void increment(sequenced_index_node_impl*& x){x=x->next();}
static void decrement(sequenced_index_node_impl*& x){x=x->prior();}
/* 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;
}
/* algorithmic stuff */
static void link(
sequenced_index_node_impl* x,sequenced_index_node_impl* header)
{
x->prior()=header->prior();
x->next()=header;
x->prior()->next()=x->next()->prior()=x;
};
static void unlink(sequenced_index_node_impl* x)
{
x->prior()->next()=x->next();
x->next()->prior()=x->prior();
}
static void relink(
sequenced_index_node_impl* position,sequenced_index_node_impl* x)
{
unlink(x);
x->prior()=position->prior();
x->next()=position;
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)
{
/* position is assumed not to be in [x,y) */
if(x!=y){
sequenced_index_node_impl* z=y->prior();
x->prior()->next()=y;
y->prior()=x->prior();
x->prior()=position->prior();
z->next()=position;
x->prior()->next()=x;
z->next()->prior()=z;
}
}
static void reverse(sequenced_index_node_impl* header)
{
sequenced_index_node_impl* x=header;
do{
sequenced_index_node_impl* 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)
{
/* This swap function does not exchange the header nodes,
* but rather their pointers. This is *not* used for implementing
* sequenced_index::swap.
*/
if(x->next()!=x){
if(y->next()!=y){
std::swap(x->next(),y->next());
std::swap(x->prior(),y->prior());
x->next()->prior()=x->prior()->next()=x;
y->next()->prior()=y->prior()->next()=y;
}
else{
y->next()=x->next();
y->prior()=x->prior();
x->next()=x->prior()=x;
y->next()->prior()=y->prior()->next()=y;
}
}
else if(y->next()!=y){
x->next()=y->next();
x->prior()=y->prior();
y->next()=y->prior()=y;
x->next()->prior()=x->prior()->next()=x;
}
}
private:
sequenced_index_node_impl();
sequenced_index_node_impl* prior_;
sequenced_index_node_impl* next_;
};
template<typename Super>
struct sequenced_index_node_trampoline:sequenced_index_node_impl{};
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();}
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);}
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)
{
return static_cast<const sequenced_index_node*>(
static_cast<const impl_type*>(x));
}
/* interoperability with index_iterator */
static void increment(sequenced_index_node*& x)
{
sequenced_index_node_impl* xi=x->impl();
impl_type::increment(xi);
x=from_impl(xi);
}
static void decrement(sequenced_index_node*& x)
{
sequenced_index_node_impl* xi=x->impl();
impl_type::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 */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,164 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_SEQ_INDEX_OPS_HPP
#define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_OPS_HPP
#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 <cstddef>
namespace boost{
namespace multi_index{
namespace detail{
/* Common code for sequenced_index memfuns having templatized and
* non-templatized versions.
*/
template <typename SequencedIndex,typename Predicate>
void sequenced_index_remove(SequencedIndex& x,Predicate pred)
{
typedef typename SequencedIndex::iterator iterator;
iterator first=x.begin(),last=x.end();
while(first!=last){
if(pred(*first))x.erase(first++);
else ++first;
}
}
template <typename SequencedIndex,class BinaryPredicate>
void sequenced_index_unique(SequencedIndex& x,BinaryPredicate binary_pred)
{
typedef typename SequencedIndex::iterator iterator;
iterator first=x.begin();
iterator last=x.end();
if(first!=last){
for(iterator middle=first;++middle!=last;middle=first){
if(binary_pred(*middle,*first))x.erase(middle);
else first=middle;
}
}
}
template <typename SequencedIndex,typename Compare>
void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
{
typedef typename SequencedIndex::iterator iterator;
if(x!=y){
iterator first0=x.begin(),last0=x.end();
iterator first1=y.begin(),last1=y.end();
while(first0!=last0&&first1!=last1){
if(comp(*first1,*first0))x.splice(first0,y,first1++);
else ++first0;
}
x.splice(last0,y,first1,last1);
}
}
/* sorting */
/* auxiliary stuff */
template<typename Node,typename Compare>
void sequenced_index_collate(
sequenced_index_node_impl* x,sequenced_index_node_impl* 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;
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);
first1=tmp;
}
else first0=first0->next();
}
sequenced_index_node_impl::relink(last0,first1,last1);
}
template<typename Node,typename Compare>
void sequenced_index_sort(Node* header,Compare comp)
{
/* Musser's mergesort, see http://www.cs.rpi.edu/~musser/gp/List/lists1.html.
* The implementation is a little convoluted: in the original code
* counter elements and carry are std::lists: here we do not want
* to use multi_index instead, so we do things at a lower level, managing
* directly the internal node representation.
* Incidentally, the implementations I've seen of this algorithm (SGI,
* Dinkumware, STLPort) are not exception-safe: this is. Moreover, we do not
* use any dynamic storage.
*/
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);
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<
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;
carry.prior()=carry.next()=&carry;
counter[0].prior()=counter[0].next()=&counter[0];
BOOST_TRY{
while(header->next()!=header->impl()){
sequenced_index_node_impl::relink(carry.next(),header->next());
std::size_t i=0;
while(i<fill&&counter[i].next()!=&counter[i]){
sequenced_index_collate<Node>(&carry,&counter[i++],comp);
}
sequenced_index_node_impl::swap(&carry,&counter[i]);
if(i==fill){
++fill;
counter[fill].prior()=counter[fill].next()=&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]);
}
BOOST_CATCH(...)
{
sequenced_index_node_impl::relink(header->impl(),carry.next(),&carry);
for(std::size_t i=0;i<=fill;++i){
sequenced_index_node_impl::relink(
header->impl(),counter[i].next(),&counter[i]);
}
BOOST_RETHROW;
}
BOOST_CATCH_END
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,35 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_UNBOUNDED_HPP
#define BOOST_MULTI_INDEX_DETAIL_UNBOUNDED_HPP
namespace boost{
namespace multi_index{
/* dummy type and variable for use in ordered_index::range() */
namespace detail{
struct unbounded_type{};
} /* namespace multi_index::detail */
namespace{
detail::unbounded_type unbounded_obj=detail::unbounded_type();
detail::unbounded_type& unbounded=unbounded_obj;
} /* unnamed */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,48 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_VALUE_COMPARE_HPP
#define BOOST_MULTI_INDEX_DETAIL_VALUE_COMPARE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/call_traits.hpp>
#include <functional>
namespace boost{
namespace multi_index{
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()):
key(key_),comp(comp_)
{
}
bool operator()(
typename call_traits<Value>::param_type x,
typename call_traits<Value>::param_type y)
{
return comp(key(x),key(y));
}
private:
KeyFromValue key;
Compare comp;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,119 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_IDENTITY_HPP
#define BOOST_MULTI_INDEX_IDENTITY_HPP
#include <boost/config.hpp>
#include <boost/mpl/if.hpp>
#include <boost/multi_index/identity_fwd.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_const.hpp>
namespace boost{
template<class Type> class reference_wrapper; /* fwd decl. */
namespace multi_index{
namespace detail{
/* identity is a do-nothing key extractor that returns the [const] Type&
* object passed.
* Additionally, identity is overloaded to support referece_wrappers
* of Type and "chained pointers" to Type's. By chained pointer to Type we
* mean a type P such that, given a p of type P
* *...n...*x is convertible to Type&, for some n>=1.
* Examples of chained pointers are raw and smart pointers, iterators and
* arbitrary combinations of these (vg. Type** or auto_ptr<Type*>.)
*/
/* NB. Some overloads of operator() have an extra dummy parameter int=0.
* This is so because MSVC++ 6.0 otherwise *incorrectly* regards these
* overloads as specializations of a previous member function template.
* Left for all compilers as it does no harm.
*/
template<typename Type>
struct const_identity_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type& operator()(Type& x)const
{
return x;
}
Type& operator()(const reference_wrapper<Type>& x)const
{
return x.get();
}
Type& operator()(
const reference_wrapper<typename remove_const<Type>::type>& x)const
{
return x.get();
}
};
template<typename Type>
struct non_const_identity_base
{
typedef Type result_type;
/* templatized for pointer-like types */
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
const Type& operator()(const Type& x,int=0)const
{
return x;
}
Type& operator()(Type& x)const
{
return x;
}
const Type& operator()(const reference_wrapper<const Type>& x,int=0)const
{
return x.get();
}
Type& operator()(const reference_wrapper<Type>& x)const
{
return x.get();
}
};
} /* namespace multi_index::detail */
template<class Type>
struct identity:
mpl::if_c<
is_const<Type>::value,
detail::const_identity_base<Type>,detail::non_const_identity_base<Type>
>::type
{
};
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,22 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_IDENTITY_HPP
#define BOOST_MULTI_INDEX_IDENTITY_HPP
namespace boost{
namespace multi_index{
template<class Type> struct identity;
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,68 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_INDEXED_BY_HPP
#define BOOST_MULTI_INDEX_INDEXED_BY_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/control/expr_if.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
/* An alias to mpl::vector used to hide MPL from the user.
* indexed_by contains the index specifiers for instantiation
* of a multi_index_container.
*/
/* This user_definable macro limits the number of elements of an index list;
* useful for shortening resulting symbol names (MSVC++ 6.0, for instance,
* has problems coping with very long symbol names.)
*/
#if !defined(BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE)
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
#define BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE 5
#else
#define BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
#endif
#endif
#if BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE<BOOST_MPL_LIMIT_VECTOR_SIZE
#define BOOST_MULTI_INDEX_INDEXED_BY_SIZE \
BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE
#else
#define BOOST_MULTI_INDEX_INDEXED_BY_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
#endif
#define BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM(z,n,var) \
typename BOOST_PP_CAT(var,n) BOOST_PP_EXPR_IF(n,=mpl::void_)
namespace boost{
namespace multi_index{
template<
BOOST_PP_ENUM(
BOOST_MULTI_INDEX_INDEXED_BY_SIZE,
BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM,T)
>
struct indexed_by:
mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_INDEXED_BY_SIZE,T)>
{
};
} /* namespace multi_index */
} /* namespace boost */
#undef BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM
#undef BOOST_MULTI_INDEX_INDEXED_BY_SIZE
#endif

View File

@ -0,0 +1,17 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_KEY_EXTRACTORS_HPP
#define BOOST_MULTI_INDEX_KEY_EXTRACTORS_HPP
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#endif

View File

@ -0,0 +1,171 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_MEM_FUN_HPP
#define BOOST_MULTI_INDEX_MEM_FUN_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/if.hpp>
#include <boost/type_traits/remove_reference.hpp>
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
namespace multi_index{
/* mem_fun implements a read-only key extractor based on a given non-const
* member function of a class.
* const_mem_fun does the same for const member functions.
* Additionally, mem_fun and const_mem_fun are overloaded to support
* referece_wrappers of T and "chained pointers" to T'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*>.)
*/
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
struct const_mem_fun
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(const Class& x)const
{
return (x.*PtrToMemberFunction)();
}
Type operator()(const reference_wrapper<const Class>& x)const
{
return operator()(x.get());
}
Type operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
struct mem_fun
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(Class& x)const
{
return (x.*PtrToMemberFunction)();
}
Type operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
/* MSVC++ 6.0 has problems with const member functions as non-type template
* parameters, somehow it takes them as non-const. mem_fun_explicit workarounds
* this defficiency by accepting an extra type parameter that specifies the
* signature of he member function. The workaround was found at:
* Daniel, C.:"Re: weird typedef problem in VC",
* news:microsoft.public.vc.language, 21st nov 2002,
* http://groups.google.com/groups?
* hl=en&lr=&ie=UTF-8&selm=ukwvg3O0BHA.1512%40tkmsftngp05
*/
template<
class Class,typename Type,
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
struct const_mem_fun_explicit
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(const Class& x)const
{
return (x.*PtrToMemberFunction)();
}
Type operator()(const reference_wrapper<const Class>& x)const
{
return operator()(x.get());
}
Type operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
template<
class Class,typename Type,
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
struct mem_fun_explicit
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(Class& x)const
{
return (x.*PtrToMemberFunction)();
}
Type operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
/* BOOST_MULTI_INDEX_CONST_MEM_FUN and BOOST_MULTI_INDEX_MEM_FUN resolve to
* mem_fun_explicit for MSVC++ 6.0 and to [const_]mem_fun otherwise.
*/
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
#define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::const_mem_fun_explicit<\
Class,Type,Type (Class::*)()const,&Class::MemberFunName>
#define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::mem_fun_explicit<\
Class,Type,Type (Class::*)(),&Class::MemberFunName>
#else
#define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::const_mem_fun<Class,Type,&Class::MemberFunName>
#define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::mem_fun<Class,Type,&Class::MemberFunName>
#endif
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,228 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_MEMBER_HPP
#define BOOST_MULTI_INDEX_MEMBER_HPP
#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 <cstddef>
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
namespace multi_index{
namespace detail{
/* member is a read/write key extractor for accessing a given
* member of a class.
* Additionally, member is overloaded to support referece_wrappers
* of T and "chained pointers" to T'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 is so because MSVC++ 6.0 otherwise *incorrectly* regards these
* overloads as specializations of a previous member function template.
* Left for all compilers as it does no harm.
*/
template<class Class,typename Type,Type Class::*PtrToMember>
struct const_member_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type& operator()(const Class& x)const
{
return x.*PtrToMember;
}
Type& operator()(const reference_wrapper<const Class>& x)const
{
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class> x)const
{
return operator()(x.get());
}
};
template<class Class,typename Type,Type Class::*PtrToMember>
struct non_const_member_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
const Type& operator()(const Class& x,int=0)const
{
return x.*PtrToMember;
}
Type& operator()(Class& x)const
{
return x.*PtrToMember;
}
const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
{
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
} /* namespace multi_index::detail */
template<class Class,typename Type,Type Class::*PtrToMember>
struct member:
mpl::if_c<
is_const<Type>::value,
detail::const_member_base<Class,Type,PtrToMember>,
detail::non_const_member_base<Class,Type,PtrToMember>
>::type
{
};
namespace detail{
/* MSVC++ 6.0 does not support properly pointers to members as
* non-type template arguments, as reported in
* http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
* We provide an alternative to member<> accepting offsets instead
* of pointers to members. This happens to work even for non-POD
* types (although the standard forbids use of offsetof on these),
* so it serves as a workaround in this compiler for all practical
* purposes.
* Surprisingly enough, other compilers (Intel C++ 7.1 at least)
* have similar bugs. This replacement of member<> can be used for
* them too.
*/
template<class Class,typename Type,std::size_t OffsetOfMember>
struct const_member_offset_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type& operator()(const Class& x)const
{
return *static_cast<const Type*>(
static_cast<const void*>(
static_cast<const char*>(
static_cast<const void *>(&x))+OffsetOfMember));
}
Type& operator()(const reference_wrapper<const Class>& x)const
{
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
template<class Class,typename Type,std::size_t OffsetOfMember>
struct non_const_member_offset_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
const Type& operator()(const Class& x,int=0)const
{
return *static_cast<const Type*>(
static_cast<const void*>(
static_cast<const char*>(
static_cast<const void *>(&x))+OffsetOfMember));
}
Type& operator()(Class& x)const
{
return *static_cast<Type*>(
static_cast<void*>(
static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
}
const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
{
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
} /* namespace multi_index::detail */
template<class Class,typename Type,std::size_t OffsetOfMember>
struct member_offset:
mpl::if_c<
is_const<Type>::value,
detail::const_member_offset_base<Class,Type,OffsetOfMember>,
detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
>::type
{
};
/* A proposal has been issued to add a defect macro in Boost.Config to detect
* this problem with pointer to members as template arguments. While
* the macro gets into the library, we follow our own heuristics in order to
* define BOOST_MULTI_INDEX_MEMBER as a convenient wrapper of member<> and
* member_offset<>
*/
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\
defined(BOOST_MSVC)&&(BOOST_MSVC<1300) ||\
defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\
(BOOST_INTEL_CXX_VERSION<=700)
#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
::boost::multi_index::member_offset<Class,Type,offsetof(Class,MemberName)>
#else
#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
::boost::multi_index::member<Class,Type,&Class::MemberName>
#endif
} /* namespace multi_index */
} /* namespace boost */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,112 @@
/* Copyright Joaquín M López Muńoz 2003-2004. Use, modification, and
* distribution are subject to 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_ORDERED_INDEX_FWD_HPP
#define BOOST_MULTI_INDEX_ORDERED_INDEX_FWD_HPP
#include <boost/multi_index/detail/ord_index_args.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<
typename KeyFromValue,typename Compare,
typename Super,typename TagList,typename Category
>
class index;
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator==(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator<(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator!=(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator>(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator>=(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator<=(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue,typename Compare,
typename Super,typename TagList,typename Category
>
void swap(
index<KeyFromValue,Compare,Super,TagList,Category>& x,
index<KeyFromValue,Compare,Super,TagList,Category>& y);
} /* namespace multi_index::detail */
/* index specifiers */
template<
typename Arg1,typename Arg2=detail::null_arg,typename Arg3=detail::null_arg
>
struct ordered_unique;
template<
typename Arg1,typename Arg2=detail::null_arg,typename Arg3=detail::null_arg
>
struct ordered_non_unique;
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,43 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_SAFE_MODE_ERRORS_HPP
#define BOOST_MULTI_INDEX_SAFE_MODE_ERRORS_HPP
namespace boost{
namespace multi_index{
namespace safe_mode{
/* Error codes for Boost.MultiIndex safe mode. These go in a separate
* header so that the user can include it when redefining
* BOOST_MULTI_INDEX_SAFE_MODE_ASSERT prior to the inclusion of
* any other header of Boost.MultiIndex.
*/
enum error_code
{
invalid_iterator=0,
not_dereferenceable_iterator,
not_incrementable_iterator,
not_decrementable_iterator,
not_owner,
not_same_owner,
invalid_range,
inside_range,
same_container
};
} /* namespace multi_index::safe_mode */
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,751 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_SEQUENCED_INDEX_HPP
#define BOOST_MULTI_INDEX_SEQUENCED_INDEX_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/call_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/index_iterator.hpp>
#include <boost/multi_index/detail/seq_index_node.hpp>
#include <boost/multi_index/detail/seq_index_ops.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
#include <boost/multi_index/detail/scope_guard.hpp>
#include <boost/multi_index/sequenced_index_fwd.hpp>
#include <boost/tuple/tuple.hpp>
#include <cstddef>
#include <functional>
#include <utility>
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
#define BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT \
detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
detail::make_obj_guard(*this,&sequenced_index::check_invariant_); \
BOOST_JOIN(check_invariant_,__LINE__).touch();
#else
#define BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT
#endif
namespace boost{
namespace multi_index{
namespace detail{
/* sequenced_index adds a layer of sequenced indexing to a given Super */
template<typename Super,typename TagList>
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
class sequenced_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS Super,
public index_proxy<sequenced_index_node<typename Super::node_type> >
#else
class sequenced_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS Super,
public safe_container<sequenced_index<Super,TagList> >
#endif
#else
class sequenced_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS Super
#endif
{
protected:
typedef sequenced_index_node<typename Super::node_type> node_type;
public:
/* types */
typedef typename node_type::value_type value_type;
typedef tuples::null_type ctor_args;
typedef typename Super::final_allocator_type allocator_type;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef index_iterator<node_type> iterator;
typedef index_iterator<node_type> const_iterator;
#else
typedef index_iterator<node_type,sequenced_index> iterator;
typedef index_iterator<node_type,sequenced_index> const_iterator;
#endif
#else
typedef index_iterator<node_type> iterator;
typedef index_iterator<node_type> const_iterator;
#endif
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename
boost::reverse_iterator<iterator> reverse_iterator;
typedef typename
boost::reverse_iterator<const_iterator> const_reverse_iterator;
typedef typename TagList::type tag_list;
protected:
typedef typename Super::final_node_type final_node_type;
typedef tuples::cons<
ctor_args,
typename Super::ctor_args_list> ctor_args_list;
typedef typename mpl::push_front<
typename Super::index_type_list,
sequenced_index>::type index_type_list;
typedef typename mpl::push_front<
typename Super::iterator_type_list,
iterator>::type iterator_type_list;
typedef typename mpl::push_front<
typename Super::const_iterator_type_list,
const_iterator>::type const_iterator_type_list;
typedef typename Super::copy_map_type copy_map_type;
private:
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef index_proxy<sequenced_index_node<
typename Super::node_type> > safe_super;
#else
typedef safe_container<sequenced_index> safe_super;
#endif
#endif
typedef typename call_traits<value_type>::param_type value_param_type;
public:
/* construct/copy/destroy
* Default and copy ctors are in the protected section as indices are
* not supposed to be created on their own. No range ctor either.
*/
sequenced_index<Super,TagList>& operator=(
const sequenced_index<Super,TagList>& x)
{
this->final()=x.final();
return *this;
}
template <class InputIterator>
void assign(InputIterator first,InputIterator last)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
clear();
for(;first!=last;++first)push_back(*first);
}
void assign(size_type n,value_param_type value)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
clear();
for(size_type i=0;i<n;++i)push_back(value);
}
allocator_type get_allocator()const
{
return this->final().get_allocator();
}
/* iterators */
iterator begin()
{return make_iterator(node_type::from_impl(header()->next()));}
const_iterator begin()const
{return make_iterator(node_type::from_impl(header()->next()));}
iterator end(){return make_iterator(header());}
const_iterator end()const{return make_iterator(header());}
reverse_iterator rbegin(){return make_reverse_iterator(end());}
const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
reverse_iterator rend(){return make_reverse_iterator(begin());}
const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
/* capacity */
bool empty()const{return this->final_empty_();}
size_type size()const{return this->final_size_();}
size_type max_size()const{return this->final_max_size_();}
void resize(size_type n,value_param_type x=value_type())
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(n>size())insert(end(),n-size(),x);
else if(n<size()){
iterator it=begin();
std::advance(it,n);
erase(it,end());
}
}
/* access: no non-const versions provided as sequenced_index
* handles const elements.
*/
const_reference front()const{return *begin();}
const_reference back()const{return *--end();}
/* modifiers */
std::pair<iterator,bool> push_front(value_param_type x)
{return insert(begin(),x);}
void pop_front(){erase(begin());}
std::pair<iterator,bool> push_back(value_param_type x)
{return insert(end(),x);}
void pop_back(){erase(--end());}
std::pair<iterator,bool> insert(iterator position,value_param_type x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
std::pair<final_node_type*,bool> p=this->final_insert_(x);
/* "this->" not required by std, but CW9.2 seems to need it */
if(p.second)relink(position.get_node(),p.first);
return std::pair<iterator,bool>(make_iterator(p.first),p.second);
}
void insert(iterator position,size_type n,value_param_type x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
for(size_type i=0;i<n;++i)insert(position,x);
}
template<typename InputIterator>
void insert(iterator position,InputIterator first,InputIterator last)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
for(;first!=last;++first)insert(position,*first);
}
void 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_SEQ_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
final_erase_(static_cast<final_node_type*>(position.get_node()));
}
void erase(iterator first,iterator last)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
while(first!=last){
erase(first++);
}
}
bool replace(iterator position,value_param_type x)
{
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_SEQ_INDEX_CHECK_INVARIANT;
return final_replace_(
x,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier>
bool modify(iterator position,Modifier mod)
{
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_SEQ_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 final_modify_(
mod,static_cast<final_node_type*>(position.get_node()));
}
void swap(sequenced_index<Super,TagList>& x)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
final_swap_(x.final());
}
void clear()
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
erase(begin(),end());
}
/* list operations */
void splice(iterator position,sequenced_index<Super,TagList>& x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(*this,x);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
iterator first=x.begin(),last=x.end();
while(first!=last){
if(insert(position,*first).second)x.erase(first++);
else ++first;
}
}
void splice(iterator position,sequenced_index<Super,TagList>& x,iterator i)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(x==*this){
if(position!=i)relink(position.get_node(),i.get_node());
}
else{
if(insert(position,*i).second){
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer has a hard time with safe mode, and the following
* workaround is needed. Left it for all compilers as it does no
* harm.
*/
i.detach();
x.erase(x.make_iterator(i.get_node()));
#else
x.erase(i);
#endif
}
}
}
void splice(
iterator position,sequenced_index<Super,TagList>& x,
iterator first,iterator last)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(x==*this){
BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
if(position!=last)relink(
position.get_node(),first.get_node(),last.get_node());
}
else{
while(first!=last){
if(insert(position,*first).second)x.erase(first++);
else ++first;
}
}
}
void remove(value_param_type value)
{
sequenced_index_remove(
*this,std::bind2nd(std::equal_to<value_type>(),value));
}
template<typename Predicate>
void remove_if(Predicate pred)
{
sequenced_index_remove(*this,pred);
}
void unique()
{
sequenced_index_unique(*this,std::equal_to<value_type>());
}
template <class BinaryPredicate>
void unique(BinaryPredicate binary_pred)
{
sequenced_index_unique(*this,binary_pred);
}
void merge(sequenced_index<Super,TagList>& x)
{
sequenced_index_merge(*this,x,std::less<value_type>());
}
template <typename Compare>
void merge(sequenced_index<Super,TagList>& x,Compare comp)
{
sequenced_index_merge(*this,x,comp);
}
void sort()
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
sequenced_index_sort(header(),std::less<value_type>());
}
template <typename Compare>
void sort(Compare comp)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
sequenced_index_sort(header(),comp);
}
void reverse()
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
sequenced_index_node_impl::reverse(header()->impl());
}
/* relocate operations */
void relocate(iterator position,iterator i)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(position!=i)relink(position.get_node(),i.get_node());
}
void relocate(iterator position,iterator first,iterator last)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(position!=last)relink(
position.get_node(),first.get_node(),last.get_node());
}
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
sequenced_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())
#endif
{
header()->prior()=header()->next()=header()->impl();
}
sequenced_index(const sequenced_index<Super,TagList>& x):
Super(x)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)&&\
BOOST_WORKAROUND(BOOST_MSVC,<1300)
,safe_super(final_header())
#endif
{
/* The actual copying takes place in subsequent call to copy_().
*/
}
~sequenced_index()
{
/* the container is guaranteed to be empty by now */
}
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
iterator make_iterator(node_type* node){return iterator(node,this);}
const_iterator make_iterator(node_type* node)const
{return const_iterator(node,const_cast<sequenced_index*>(this));}
#else
iterator make_iterator(node_type* node){return iterator(node);}
const_iterator make_iterator(node_type* node)const
{return const_iterator(node);}
#endif
void copy_(const sequenced_index<Super,TagList>& x,const copy_map_type& map)
{
node_type* org=x.header();
node_type* cpy=header();
do{
node_type* next_org=node_type::from_impl(org->next());
node_type* next_cpy=map.find(static_cast<final_node_type*>(next_org));
cpy->next()=next_cpy->impl();
next_cpy->prior()=cpy->impl();
org=next_org;
cpy=next_cpy;
}while(org!=x.header());
Super::copy_(x,map);
}
node_type* insert_(value_param_type v,node_type* x)
{
node_type* res=static_cast<node_type*>(Super::insert_(v,x));
if(res==x)link(x);
return res;
}
node_type* insert_(value_param_type v,node_type* position,node_type* x)
{
node_type* res=static_cast<node_type*>(Super::insert_(v,position,x));
if(res==x)link(x);
return res;
}
void erase_(node_type* x)
{
unlink(x);
Super::erase_(x);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
}
void swap_(sequenced_index<Super,TagList>& x)
{
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
safe_super::swap(x);
#endif
Super::swap_(x);
}
bool replace_(value_param_type v,node_type* x)
{
return Super::replace_(v,x);
}
bool modify_(node_type* x)
{
BOOST_TRY{
if(!Super::modify_(x)){
unlink(x);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
return false;
}
else return true;
}
BOOST_CATCH(...){
unlink(x);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
BOOST_RETHROW;
}
BOOST_CATCH_END
return true;
}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
bool invariant_()const
{
if(size()==0||begin()==end()){
if(size()!=0||begin()!=end()||
header()->next()!=header()->impl()||
header()->prior()!=header()->impl())return false;
}
else{
size_type s=0;
for(const_iterator it=begin();it!=end();++it,++s){
if(it.get_node()->next()->prior()!=it.get_node()->impl())return false;
if(it.get_node()->prior()->next()!=it.get_node()->impl())return false;
}
if(s!=size())return false;
}
return Super::invariant_();
}
/* This forwarding function eases things for the boost::mem_fn construct
* in BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT. Actually,
* final_check_invariant is already an inherited member function of index.
*/
void check_invariant_()const{this->final_check_invariant_();}
#endif
private:
node_type* header()const{return this->final_header();}
void link(node_type* x)
{
sequenced_index_node_impl::link(x->impl(),header()->impl());
};
static void unlink(node_type* x)
{
sequenced_index_node_impl::unlink(x->impl());
}
static void relink(node_type* position,node_type* x)
{
sequenced_index_node_impl::relink(position->impl(),x->impl());
}
static void relink(node_type* position,node_type* first,node_type* last)
{
sequenced_index_node_impl::relink(
position->impl(),first->impl(),last->impl());
}
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
void detach_iterators(node_type* x)
{
iterator it=make_iterator(x);
safe_mode::detach_equivalent_iterators(it);
}
#endif
};
/* comparison */
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator==(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator<(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator!=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return !(x==y);
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator>(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return y<x;
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator>=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return !(x<y);
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator<=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return !(x>y);
}
/* specialized algorithms */
template<typename Super,typename TagList>
void swap(
sequenced_index<Super,TagList>& x,
sequenced_index<Super,TagList>& y)
{
x.swap(y);
}
} /* namespace multi_index::detail */
/* sequenced index specifier */
template <typename TagList>
struct sequenced
{
BOOST_STATIC_ASSERT(detail::is_tag<TagList>::value);
template<typename Super>
struct node_class
{
typedef detail::sequenced_index_node<Super> type;
};
template<typename Super>
struct index_class
{
typedef detail::sequenced_index<Super,TagList> type;
};
};
} /* namespace multi_index */
} /* namespace boost */
#undef BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT
#endif

View File

@ -0,0 +1,87 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_SEQUENCED_INDEX_FWD_HPP
#define BOOST_MULTI_INDEX_SEQUENCED_INDEX_FWD_HPP
#include <boost/multi_index/tag.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename Super,typename TagList>
class sequenced_index;
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator==(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator<(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator!=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator>(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator>=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator<=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<typename Super,typename TagList>
void swap(
sequenced_index<Super,TagList>& x,
sequenced_index<Super,TagList>& y);
} /* namespace multi_index::detail */
/* index specifiers */
template <typename TagList=tag<> >
struct sequenced;
} /* namespace multi_index */
} /* namespace boost */
#endif

View File

@ -0,0 +1,79 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_TAG_HPP
#define BOOST_MULTI_INDEX_TAG_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index/detail/no_duplicate_tags.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
/* An alias to mpl::vector used to hide MPL from the user.
* tag contains types used as tag names for indices in get() functions.
*/
/* This user_definable macro limits the number of elements of a tag;
* useful for shortening resulting symbol names (MSVC++ 6.0, for instance,
* has problems coping with very long symbol names.)
*/
#if !defined(BOOST_MULTI_INDEX_LIMIT_TAG_SIZE)
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
#define BOOST_MULTI_INDEX_LIMIT_TAG_SIZE 3
#else
#define BOOST_MULTI_INDEX_LIMIT_TAG_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
#endif
#endif
#if BOOST_MULTI_INDEX_LIMIT_TAG_SIZE<BOOST_MPL_LIMIT_VECTOR_SIZE
#define BOOST_MULTI_INDEX_TAG_SIZE BOOST_MULTI_INDEX_LIMIT_TAG_SIZE
#else
#define BOOST_MULTI_INDEX_TAG_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
#endif
namespace boost{
namespace multi_index{
namespace detail{
struct tag_marker{};
template<typename T>
struct is_tag
{
BOOST_STATIC_CONSTANT(bool,value=(is_base_and_derived<tag_marker,T>::value));
};
} /* namespace multi_index::detail */
template<
BOOST_PP_ENUM_BINARY_PARAMS(
BOOST_MULTI_INDEX_TAG_SIZE,
typename T,
=mpl::void_ BOOST_PP_INTERCEPT)
>
struct tag:private detail::tag_marker
{
typedef mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_TAG_SIZE,T)> type;
BOOST_STATIC_ASSERT(detail::no_duplicate_tags<type>::value);
};
} /* namespace multi_index */
} /* namespace boost */
#undef BOOST_MULTI_INDEX_TAG_SIZE
#endif

View File

@ -0,0 +1,864 @@
/* Multiply indexed container.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_HPP
#define BOOST_MULTI_INDEX_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/size.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/allocator.hpp>
#include <boost/multi_index/detail/base_type.hpp>
#include <boost/multi_index/detail/converter.hpp>
#include <boost/multi_index/detail/def_ctor_tuple_cons.hpp>
#include <boost/multi_index/detail/header_holder.hpp>
#include <boost/multi_index/detail/has_tag.hpp>
#include <boost/multi_index/detail/no_duplicate_tags.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
#include <boost/multi_index/detail/scope_guard.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/base_from_member.hpp>
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
#include <boost/multi_index/detail/invariant_assert.hpp>
#define BOOST_MULTI_INDEX_CHECK_INVARIANT \
detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
detail::make_obj_guard(*this,&multi_index_container::check_invariant_); \
BOOST_JOIN(check_invariant_,__LINE__).touch();
#else
#define BOOST_MULTI_INDEX_CHECK_INVARIANT
#endif
namespace boost{
namespace multi_index{
template<typename Value,typename IndexSpecifierList,typename Allocator>
class multi_index_container:
private base_from_member<
typename detail::allocator::rebind_to<
Allocator,
typename detail::multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type
>::type>,
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
typename detail::multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type,
multi_index_container<Value,IndexSpecifierList,Allocator> >,
public detail::multi_index_base_type<Value,IndexSpecifierList,Allocator>::type
{
private:
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename,typename,typename> friend class detail::index_base;
template <typename,typename> friend class detail::header_holder;
template <typename,typename> friend class detail::converter;
#endif
typedef typename detail::multi_index_base_type<
Value,IndexSpecifierList,Allocator>::type super;
typedef base_from_member<
typename detail::allocator::rebind_to<
Allocator,
typename super::node_type
>::type> bfm_allocator;
typedef detail::header_holder<
typename super::node_type,
multi_index_container> bfm_header;
public:
/* All types are inherited from super, a few are explicitly
* brought forward here to save us some typename's.
*/
#if defined(BOOST_MSVC)
typedef
detail::default_constructible_tuple_cons<
typename super::ctor_args_list> ctor_args_list;
#else
typedef typename super::ctor_args_list ctor_args_list;
#endif
typedef typename IndexSpecifierList::type index_specifier_type_list;
typedef typename super::index_type_list index_type_list;
typedef typename super::iterator_type_list iterator_type_list;
typedef typename super::const_iterator_type_list const_iterator_type_list;
typedef typename super::value_type value_type;
typedef typename super::final_allocator_type allocator_type;
typedef typename super::iterator iterator;
typedef typename super::const_iterator const_iterator;
BOOST_STATIC_ASSERT(
detail::no_duplicate_tags_in_index_list<index_type_list>::value);
/* global project() needs to see this publicly */
typedef typename super::node_type node_type;
/* construct/copy/destroy */
explicit multi_index_container(
const ctor_args_list& args_list=ctor_args_list(),
const allocator_type& al=allocator_type()):
bfm_allocator(al),
super(args_list,bfm_allocator::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
}
template<typename InputIterator>
multi_index_container(
InputIterator first,InputIterator last,
const ctor_args_list& args_list=ctor_args_list(),
const allocator_type& al=allocator_type()):
bfm_allocator(al),
super(args_list,bfm_allocator::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
BOOST_TRY{
iterator hint=super::end();
for(;first!=last;++first){
hint=super::make_iterator(insert_(*first,hint.get_node()).first);
}
}
BOOST_CATCH(...){
clean_up();
BOOST_RETHROW;
}
BOOST_CATCH_END
}
multi_index_container(
const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
bfm_allocator(x.bfm_allocator::member),
super(x),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
for(const_iterator it=x.begin();it!=x.end();++it)map.clone(it.get_node());
super::copy_(x,map);
map.release();
node_count=x.size();
}
~multi_index_container()
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
clean_up();
}
multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
multi_index_container<Value,IndexSpecifierList,Allocator> tmp(x);
swap(tmp);
return *this;
}
allocator_type get_allocator()const
{
return allocator_type(bfm_allocator::member);
}
/* retrieval of indices by number */
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template<int N>
struct nth_index
{
BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
typedef typename mpl::at_c<index_type_list,N>::type type;
};
template<int N>
typename nth_index<N>::type& get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
return *this;
}
template<int N>
const typename nth_index<N>::type& get(
BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
{
BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
return *this;
}
#endif
/* retrieval of indices by tag */
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template<typename Tag>
struct index
{
typedef typename mpl::find_if<
index_type_list,
detail::has_tag<Tag>
>::type iter;
BOOST_STATIC_CONSTANT(
bool,index_found=!(is_same<iter,mpl::end<index_type_list> >::value));
BOOST_STATIC_ASSERT(index_found);
typedef typename iter::type type;
};
template<typename Tag>
typename index<Tag>::type& get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
{
return *this;
}
template<typename Tag>
const typename index<Tag>::type& get(
BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))const
{
return *this;
}
#endif
/* projection of iterators by number */
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template<int N>
struct nth_index_iterator
{
typedef typename nth_index<N>::type::iterator type;
};
template<int N>
struct nth_index_const_iterator
{
typedef typename nth_index<N>::type::const_iterator type;
};
template<int N,typename IteratorType>
typename nth_index_iterator<N>::type project(
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef typename nth_index<N>::type index;
BOOST_STATIC_ASSERT(
(mpl::contains<iterator_type_list,IteratorType>::value));
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(
it,static_cast<typename IteratorType::container_type&>(*this));
return index::make_iterator(static_cast<node_type*>(it.get_node()));
}
template<int N,typename IteratorType>
typename nth_index_const_iterator<N>::type project(
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
{
typedef typename nth_index<N>::type index;
BOOST_STATIC_ASSERT((
mpl::contains<iterator_type_list,IteratorType>::value||
mpl::contains<const_iterator_type_list,IteratorType>::value));
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(
it,static_cast<const typename IteratorType::container_type&>(*this));
return index::make_iterator(static_cast<node_type*>(it.get_node()));
}
#endif
/* projection of iterators by tag */
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template<typename Tag>
struct index_iterator
{
typedef typename index<Tag>::type::iterator type;
};
template<typename Tag>
struct index_const_iterator
{
typedef typename index<Tag>::type::const_iterator type;
};
template<typename Tag,typename IteratorType>
typename index_iterator<Tag>::type project(
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef typename index<Tag>::type index;
BOOST_STATIC_ASSERT(
(mpl::contains<iterator_type_list,IteratorType>::value));
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(
it,static_cast<typename IteratorType::container_type&>(*this));
return index::make_iterator(static_cast<node_type*>(it.get_node()));
}
template<typename Tag,typename IteratorType>
typename index_const_iterator<Tag>::type project(
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))const
{
typedef typename index<Tag>::type index;
BOOST_STATIC_ASSERT((
mpl::contains<iterator_type_list,IteratorType>::value||
mpl::contains<const_iterator_type_list,IteratorType>::value));
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(
it,static_cast<const typename IteratorType::container_type&>(*this));
return index::make_iterator(static_cast<node_type*>(it.get_node()));
}
#endif
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
typedef typename super::copy_map_type copy_map_type;
node_type* header()const
{
return bfm_header::member;
}
node_type* allocate_node()
{
return detail::allocator::allocate<node_type>(bfm_allocator::member,1);
}
void deallocate_node(node_type* x)
{
detail::allocator::deallocate(bfm_allocator::member,x,1);
}
bool empty_()const
{
return node_count==0;
}
std::size_t size_()const
{
return node_count;
}
std::size_t max_size_()const
{
return static_cast<std::size_t >(-1);
}
std::pair<node_type*,bool> insert_(const Value& v)
{
node_type* x=allocate_node();
BOOST_TRY{
node_type* res=super::insert_(v,x);
if(res==x){
++node_count;
return std::pair<node_type*,bool>(res,true);
}
else{
deallocate_node(x);
return std::pair<node_type*,bool>(res,false);
}
}
BOOST_CATCH(...){
deallocate_node(x);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
std::pair<node_type*,bool> insert_(const Value& v,node_type* position)
{
node_type* x=allocate_node();
BOOST_TRY{
node_type* res=super::insert_(v,position,x);
if(res==x){
++node_count;
return std::pair<node_type*,bool>(res,true);
}
else{
deallocate_node(x);
return std::pair<node_type*,bool>(res,false);
}
}
BOOST_CATCH(...){
deallocate_node(x);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
void erase_(node_type* x)
{
super::erase_(x);
deallocate_node(x);
--node_count;
}
void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
{
std::swap(bfm_header::member,x.bfm_header::member);
super::swap_(x);
std::swap(node_count,x.node_count);
}
bool replace_(const Value& k,node_type* x)
{
return super::replace_(k,x);
}
template<typename Modifier>
bool modify_(Modifier mod,node_type* x)
{
mod(const_cast<value_type&>(x->value));
BOOST_TRY{
if(!super::modify_(x)){
deallocate_node(x);
--node_count;
return false;
}
else return true;
}
BOOST_CATCH(...){
deallocate_node(x);
--node_count;
BOOST_RETHROW;
}
BOOST_CATCH_END
}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
bool invariant_()const
{
return super::invariant_();
}
void check_invariant_()const
{
BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
}
#endif
private:
void clean_up()
{
for(iterator it=super::begin();it!=super::end();)erase_(it++.get_node());
}
std::size_t node_count;
};
/* retrieval of indices by number */
template<typename MultiIndexContainer,int N>
struct nth_index
{
BOOST_STATIC_CONSTANT(
int,
M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
BOOST_STATIC_ASSERT(N>=0&&N<M);
typedef typename mpl::at_c<
typename MultiIndexContainer::index_type_list,N>::type type;
};
template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
typename nth_index<
multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
get(
multi_index_container<Value,IndexSpecifierList,Allocator>& m
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename nth_index<
multi_index_container<
Value,IndexSpecifierList,Allocator>,
N
>::type index;
BOOST_STATIC_ASSERT(N>=0&&
N<
mpl::size<
BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
>::type::value);
return detail::converter<multi_index_type,index>::index(m);
}
template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
const typename nth_index<
multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
get(
const multi_index_container<Value,IndexSpecifierList,Allocator>& m
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename nth_index<
multi_index_container<
Value,IndexSpecifierList,Allocator>,
N
>::type index;
BOOST_STATIC_ASSERT(N>=0&&
N<
mpl::size<
BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
>::type::value);
return detail::converter<multi_index_type,index>::index(m);
}
/* retrieval of indices by tag */
template<typename MultiIndexContainer,typename Tag>
struct index
{
typedef typename MultiIndexContainer::index_type_list index_type_list;
typedef typename mpl::find_if<
index_type_list,
detail::has_tag<Tag>
>::type iter;
BOOST_STATIC_CONSTANT(
bool,index_found=!(is_same<iter,mpl::end<index_type_list> >::value));
BOOST_STATIC_ASSERT(index_found);
typedef typename iter::type type;
};
template<
typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
>
typename index<
multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
get(
multi_index_container<Value,IndexSpecifierList,Allocator>& m
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename index<
multi_index_container<
Value,IndexSpecifierList,Allocator>,
Tag
>::type index;
return detail::converter<multi_index_type,index>::index(m);
}
template<
typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
>
const typename index<
multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
get(
const multi_index_container<Value,IndexSpecifierList,Allocator>& m
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename index<
multi_index_container<
Value,IndexSpecifierList,Allocator>,
Tag
>::type index;
return detail::converter<multi_index_type,index>::index(m);
}
/* projection of iterators by number */
template<typename MultiIndexContainer,int N>
struct nth_index_iterator
{
typedef typename detail::prevent_eti<
nth_index<MultiIndexContainer,N>,
typename nth_index<MultiIndexContainer,N>::type>::type::iterator type;
};
template<typename MultiIndexContainer,int N>
struct nth_index_const_iterator
{
typedef typename detail::prevent_eti<
nth_index<MultiIndexContainer,N>,
typename nth_index<MultiIndexContainer,N>::type
>::type::const_iterator type;
};
template<
int N,typename IteratorType,
typename Value,typename IndexSpecifierList,typename Allocator>
typename nth_index_iterator<
multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
project(
multi_index_container<Value,IndexSpecifierList,Allocator>& m,
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename nth_index<multi_index_type,N>::type index;
#if !defined(BOOST_MSVC)||!(BOOST_MSVC<1300) /* this ain't work in MSVC++ 6.0 */
BOOST_STATIC_ASSERT((
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
IteratorType>::value));
#endif
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
typedef detail::converter<
multi_index_type,
BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
#endif
return detail::converter<multi_index_type,index>::iterator(
m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
}
template<
int N,typename IteratorType,
typename Value,typename IndexSpecifierList,typename Allocator>
typename nth_index_const_iterator<
multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
project(
const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename nth_index<multi_index_type,N>::type index;
#if !defined(BOOST_MSVC)||!(BOOST_MSVC<1300) /* this ain't work in MSVC++ 6.0 */
BOOST_STATIC_ASSERT((
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
IteratorType>::value||
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
IteratorType>::value));
#endif
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
typedef detail::converter<
multi_index_type,
BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
#endif
return detail::converter<multi_index_type,index>::const_iterator(
m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
}
/* projection of iterators by tag */
template<typename MultiIndexContainer,typename Tag>
struct index_iterator
{
typedef typename index<MultiIndexContainer,Tag>::type::iterator type;
};
template<typename MultiIndexContainer,typename Tag>
struct index_const_iterator
{
typedef typename index<MultiIndexContainer,Tag>::type::const_iterator type;
};
template<
typename Tag,typename IteratorType,
typename Value,typename IndexSpecifierList,typename Allocator>
typename index_iterator<
multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
project(
multi_index_container<Value,IndexSpecifierList,Allocator>& m,
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename index<multi_index_type,Tag>::type index;
#if !defined(BOOST_MSVC)||!(BOOST_MSVC<1300) /* this ain't work in MSVC++ 6.0 */
BOOST_STATIC_ASSERT((
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
IteratorType>::value));
#endif
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
typedef detail::converter<
multi_index_type,
BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
#endif
return detail::converter<multi_index_type,index>::iterator(
m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
}
template<
typename Tag,typename IteratorType,
typename Value,typename IndexSpecifierList,typename Allocator>
typename index_const_iterator<
multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
project(
const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename index<multi_index_type,Tag>::type index;
#if !defined(BOOST_MSVC)||!(BOOST_MSVC<1300) /* this ain't work in MSVC++ 6.0 */
BOOST_STATIC_ASSERT((
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
IteratorType>::value||
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
IteratorType>::value));
#endif
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
typedef detail::converter<
multi_index_type,
BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
#endif
return detail::converter<multi_index_type,index>::const_iterator(
m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
}
/* Comparison. Simple forward to first index. */
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator==(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)==get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator<(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)<get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator!=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)!=get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator>(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)>get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator>=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)>=get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator<=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)<=get<0>(y);
}
/* specialized algorithms */
template<typename Value,typename IndexSpecifierList,typename Allocator>
void swap(
multi_index_container<Value,IndexSpecifierList,Allocator>& x,
multi_index_container<Value,IndexSpecifierList,Allocator>& y)
{
x.swap(y);
}
} /* namespace multi_index */
/* Associated global functions are promoted to namespace boost, except
* comparison operators and swap, which are meant to be Koenig looked-up.
*/
using multi_index::get;
using multi_index::project;
} /* namespace boost */
#undef BOOST_MULTI_INDEX_CHECK_INVARIANT
#endif

View File

@ -0,0 +1,117 @@
/* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_FWD_HPP
#define BOOST_MULTI_INDEX_FWD_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/ordered_index_fwd.hpp>
#include <memory>
namespace boost{
namespace multi_index{
/* Default value for IndexSpecifierList specifies a container
* equivalent to std::set<Value>.
*/
template<
typename Value,
typename IndexSpecifierList=indexed_by<ordered_unique<identity<Value> > >,
typename Allocator=std::allocator<Value> >
class multi_index_container;
template<typename MultiIndexContainer,int N>
struct nth_index;
template<typename MultiIndexContainer,typename Tag>
struct index;
template<typename MultiIndexContainer,int N>
struct nth_index_iterator;
template<typename MultiIndexContainer,int N>
struct nth_index_const_iterator;
template<typename MultiIndexContainer,typename Tag>
struct index_iterator;
template<typename MultiIndexContainer,typename Tag>
struct index_const_iterator;
/* get and project functions not fwd declared due to problems
* with dependent typenames
*/
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator==(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator<(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator!=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator>(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator>=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator<=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<typename Value,typename IndexSpecifierList,typename Allocator>
void swap(
multi_index_container<Value,IndexSpecifierList,Allocator>& x,
multi_index_container<Value,IndexSpecifierList,Allocator>& y);
} /* namespace multi_index */
/* multi_index_container, being the main type of this library, is promoted to
* namespace boost.
*/
using multi_index::multi_index_container;
} /* namespace boost */
#endif

16
index.html Normal file
View File

@ -0,0 +1,16 @@
<!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">
<meta http-equiv="refresh" content="0; URL=doc/index.html">
<title>Boost.MultiIndex Documentation</title>
<link rel="stylesheet" href="doc/style.css" type="text/css">
</head>
<body>
Automatic redirection failed, please go to
<a href="doc/index.html">doc/index.html</a>
</body>
</html></body>
</html>

15
perf/Jamfile Normal file
View File

@ -0,0 +1,15 @@
# Boost.MultiIndex performance tests Jamfile
#
# Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and distribution
# are subject to 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/perf ;
exe test_perf
: test_perf.cpp
: <include>$(BOOST_ROOT)
: release
;

556
perf/test_perf.cpp Normal file
View File

@ -0,0 +1,556 @@
/* Boost.MultiIndex performance test.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <assert.h>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <climits>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <list>
#include <set>
#include <string>
#include <vector>
using namespace std;
using namespace boost::multi_index;
/* Measurement harness by Andrew Koenig, extracted from companion code to
* Stroustrup, B.: "Wrapping C++ Member Function Calls", The C++ Report,
* June 2000, Vol 12/No 6.
* Original code retrievable at: http://www.research.att.com/~bs/wrap_code.cpp
*/
// How many clock units does it take to interrogate the clock?
static double clock_overhead()
{
clock_t k = clock(), start, limit;
// Wait for the clock to tick
do start = clock();
while (start == k);
// interrogate the clock until it has advanced at least a second
// (for reasonable accuracy)
limit = start + CLOCKS_PER_SEC;
unsigned long r = 0;
while ((k = clock()) < limit)
++r;
return double(k - start) / r;
}
// We'd like the odds to be factor:1 that the result is
// within percent% of the median
const int factor = 10;
const int percent = 20;
// Measure a function (object) factor*2 times,
// appending the measurements to the second argument
template<class F>
void measure_aux(F f, vector<double>& mv)
{
static double ovhd = clock_overhead();
// Ensure we don't reallocate in mid-measurement
mv.reserve(mv.size() + factor*2);
// Wait for the clock to tick
clock_t k = clock();
clock_t start;
do start = clock();
while (start == k);
// Do 2*factor measurements
for (int i = 2*factor; i; --i) {
unsigned long count = 0, limit = 1, tcount = 0;
const clock_t clocklimit = start + CLOCKS_PER_SEC/100;
clock_t t;
do {
while (count < limit) {
f();
++count;
}
limit *= 2;
++tcount;
} while ((t = clock()) < clocklimit);
// Wait for the clock to tick again;
clock_t t2;
do ++tcount;
while ((t2 = clock()) == t);
// Append the measurement to the vector
mv.push_back(((t2 - start) - (tcount * ovhd)) / count);
// Establish a new starting point
start = t2;
}
}
// Returns the number of clock units per iteration
// With odds of factor:1, the measurement is within percent% of
// the value returned, which is also the median of all measurements.
template<class F>
double measure(F f)
{
vector<double> mv;
int n = 0; // iteration counter
do {
++n;
// Try 2*factor measurements
measure_aux(f, mv);
assert(mv.size() == 2*n*factor);
// Compute the median. We know the size is even, so we cheat.
sort(mv.begin(), mv.end());
double median = (mv[n*factor] + mv[n*factor-1])/2;
// If the extrema are within threshold of the median, we're done
if (mv[n] > (median * (100-percent))/100 &&
mv[mv.size() - n - 1] < (median * (100+percent))/100)
return median;
} while (mv.size() < factor * 200);
// Give up!
clog << "Help!\n\n";
exit(1);
}
/* dereferencing compare predicate */
template <typename Iterator,typename Compare>
struct it_compare
{
bool operator()(const Iterator& x,const Iterator& y)const{return comp(*x,*y);}
private:
Compare comp;
};
/* list_wrapper and multiset_wrapper adapt std::lists and std::multisets
* to make them conform to a set-like insert interface which test
* routines do assume.
*/
template <typename List>
struct list_wrapper:List
{
typedef typename List::value_type value_type;
typedef typename List::iterator iterator;
pair<iterator,bool> insert(const value_type& v)
{
List::push_back(v);
return pair<iterator,bool>(--end(),true);
}
};
template <typename Multiset>
struct multiset_wrapper:Multiset
{
typedef typename Multiset::value_type value_type;
typedef typename Multiset::iterator iterator;
pair<iterator,bool> insert(const value_type& v)
{
return pair<iterator,bool>(Multiset::insert(v),true);
}
};
/* space comsumption of manual simulations is determined by checking
* the node sizes of the containers involved. This cannot be done in a
* portable manner, so node_size has to be written on a per stdlibrary
* basis. Add your own versions if necessary.
*/
#if defined(BOOST_DINKUMWARE_STDLIB)
template<typename Container>
size_t node_size(const Container&)
{
return sizeof(*Container().begin()._Mynode());
}
#elif defined(__GLIBCPP__)
template<typename Container>
size_t node_size(const Container&)
{
typedef typename Container::iterator::_Link_type node_ptr;
node_ptr p=0;
return sizeof(*p);
}
template<typename Value,typename Allocator>
size_t node_size(const list<Value,Allocator>&)
{
return sizeof(typename list<Value,Allocator>::iterator::_Node);
}
template<typename List>
size_t node_size(const list_wrapper<List>&)
{
return sizeof(typename List::iterator::_Node);
}
#else
/* default version returns 0 by convention */
template<typename Container>
size_t node_size(const Container&)
{
return 0;
}
#endif
/* mono_container runs the tested routine on multi_index and manual
* simulations comprised of one standard container.
* bi_container and tri_container run the equivalent routine for manual
* compositions of two and three standard containers, respectively.
*/
template <typename Container>
struct mono_container
{
mono_container(int n_):n(n_){}
void operator()()
{
typedef typename Container::iterator iterator;
Container c;
for(int i=0;i<n;++i)c.insert(i);
for(iterator it=c.begin();it!=c.end();)c.erase(it++);
}
static size_t multi_index_node_size()
{
return sizeof(*Container().begin().get_node());
}
static size_t node_size()
{
return ::node_size(Container());
}
private:
int n;
};
template <typename Container1,typename Container2>
struct bi_container
{
bi_container(int n_):n(n_){}
void operator()()
{
typedef typename Container1::iterator iterator1;
typedef typename Container2::iterator iterator2;
Container1 c1;
Container2 c2;
for(int i=0;i<n;++i){
iterator1 it1=c1.insert(i).first;
c2.insert(it1);
}
for(iterator2 it2=c2.begin();it2!=c2.end();)
{
c1.erase(*it2);
c2.erase(it2++);
}
}
static size_t node_size()
{
return ::node_size(Container1())+::node_size(Container2());
}
private:
int n;
};
template <typename Container1,typename Container2,typename Container3>
struct tri_container
{
tri_container(int n_):n(n_){}
void operator()()
{
typedef typename Container1::iterator iterator1;
typedef typename Container2::iterator iterator2;
typedef typename Container3::iterator iterator3;
Container1 c1;
Container2 c2;
Container3 c3;
for(int i=0;i<n;++i){
iterator1 it1=c1.insert(i).first;
iterator2 it2=c2.insert(it1).first;
c3.insert(it2);
}
for(iterator3 it3=c3.begin();it3!=c3.end();)
{
c1.erase(**it3);
c2.erase(*it3);
c3.erase(it3++);
}
}
static size_t node_size()
{
return ::node_size(Container1())+
::node_size(Container2())+::node_size(Container3());
}
private:
int n;
};
/* measure and compare two routines for several numbers of elements
* and also estimates relative memory consumption.
*/
template <typename IndexedTest,typename ManualTest>
void run_tests(
const char* title
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(IndexedTest)
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(ManualTest))
{
cout<<fixed<<setprecision(2);
cout<<title<<endl;
int n=1000;
for(int i=0;i<3;++i){
double indexed_t=measure(IndexedTest(n));
double manual_t=measure(ManualTest(n));
cout<<" 10^"<<i+3<<" elmts: "
<<setw(6)<<100.0*indexed_t/manual_t<<"%"<<endl;
n*=10;
}
size_t indexed_t_node_size=IndexedTest::multi_index_node_size();
size_t manual_t_node_size=ManualTest::node_size();
if(manual_t_node_size){
cout<<" space gain: "
<<setw(6)<<100.0*indexed_t_node_size/manual_t_node_size<<"%"<<endl;
}
}
/* compare_structures accept a multi_index_container instantiation and
* several standard containers, builds a manual simulation out of the
* latter and run the tests.
*/
template <typename IndexedType,typename ManualType>
void compare_structures(
const char* title
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(IndexedType)
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(ManualType))
{
run_tests<
mono_container<IndexedType>,
mono_container<ManualType>
>(title);
}
template <typename IndexedType,typename ManualType1,typename ManualType2>
void compare_structures2(
const char* title
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(IndexedType)
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(ManualType1)
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(ManualType2))
{
run_tests<
mono_container<IndexedType>,
bi_container<ManualType1,ManualType2>
>(title);
}
template <
typename IndexedType,
typename ManualType1,typename ManualType2,typename ManualType3
>
void compare_structures3(
const char* title
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(IndexedType)
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(ManualType1)
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(ManualType2)
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(ManualType3))
{
run_tests<
mono_container<IndexedType>,
tri_container<ManualType1,ManualType2,ManualType3>
>(title);
}
int main()
{
{
/* 1 ordered index */
typedef multi_index_container<int> indexed_t;
typedef set<int> manual_t;
indexed_t dummy; /* MSVC++ 6.0 chokes if indexed_t is not instantiated */
compare_structures<indexed_t,manual_t>(
"1 ordered index");
}
{
/* 1 sequenced index */
typedef list_wrapper<
multi_index_container<
int,
indexed_by<sequenced<> >
>
> indexed_t;
typedef list_wrapper<list<int> > manual_t;
indexed_t dummy; /* MSVC++ 6.0 chokes if indexed_t is not instantiated */
compare_structures<indexed_t,manual_t>(
"1 sequenced index");
}
{
/* 2 ordered indices */
typedef multi_index_container<
int,
indexed_by<
ordered_unique<identity<int> >,
ordered_non_unique<identity<int> >
>
> indexed_t;
typedef set<int> manual_t1;
typedef multiset<
manual_t1::iterator,
it_compare<
manual_t1::iterator,
manual_t1::key_compare
>
> manual_t2;
indexed_t dummy; /* MSVC++ 6.0 chokes if indexed_t is not instantiated */
compare_structures2<indexed_t,manual_t1,manual_t2>(
"2 ordered indices");
}
{
/* 1 ordered index + 1 sequenced index */
typedef multi_index_container<
int,
indexed_by<
boost::multi_index::ordered_unique<identity<int> >,
sequenced<>
>
> indexed_t;
typedef list_wrapper<
list<int>
> manual_t1;
typedef multiset<
manual_t1::iterator,
it_compare<
manual_t1::iterator,
std::less<int>
>
> manual_t2;
indexed_t dummy; /* MSVC++ 6.0 chokes if indexed_t is not instantiated */
compare_structures2<indexed_t,manual_t1,manual_t2>(
"1 ordered index + 1 sequenced index");
}
{
/* 3 ordered indices */
typedef multi_index_container<
int,
indexed_by<
ordered_unique<identity<int> >,
ordered_non_unique<identity<int> >,
ordered_non_unique<identity<int> >
>
> indexed_t;
typedef set<int> manual_t1;
typedef multiset_wrapper<
multiset<
manual_t1::iterator,
it_compare<
manual_t1::iterator,
manual_t1::key_compare
>
>
> manual_t2;
typedef multiset<
manual_t2::iterator,
it_compare<
manual_t2::iterator,
manual_t2::key_compare
>
> manual_t3;
indexed_t dummy; /* MSVC++ 6.0 chokes if indexed_t is not instantiated */
compare_structures3<indexed_t,manual_t1,manual_t2,manual_t3>(
"3 ordered indices");
}
{
/* 2 ordered indices + 1 sequenced index */
typedef multi_index_container<
int,
indexed_by<
ordered_unique<identity<int> >,
ordered_non_unique<identity<int> >,
sequenced<>
>
> indexed_t;
typedef list_wrapper<
list<int>
> manual_t1;
typedef multiset_wrapper<
multiset<
manual_t1::iterator,
it_compare<
manual_t1::iterator,
std::less<int>
>
>
> manual_t2;
typedef multiset<
manual_t2::iterator,
it_compare<
manual_t2::iterator,
manual_t2::key_compare
>
> manual_t3;
indexed_t dummy; /* MSVC++ 6.0 chokes if indexed_t is not instantiated */
compare_structures3<indexed_t,manual_t1,manual_t2,manual_t3>(
"2 ordered indices + 1 sequenced index");
}
return 0;
}

41
test/Jamfile Normal file
View File

@ -0,0 +1,41 @@
# Boost.MultiIndex tests Jamfile
#
# Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and distribution
# are subject to 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/test ;
# bring in rules for testing
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
# make tests run by default
DEPENDS all : test ;
{
test-suite "multi_index"
: [ run test_basic_main.cpp test_basic.cpp ]
: [ run test_capacity_main.cpp test_capacity.cpp ]
: [ run test_comparison_main.cpp test_comparison.cpp ]
: [ run test_composite_key_main.cpp test_composite_key.cpp ]
: [ run test_conv_iterators_main.cpp test_conv_iterators.cpp ]
: [ run test_copy_assignment_main.cpp test_copy_assignment.cpp ]
: [ run test_iterators_main.cpp test_iterators.cpp ]
: [ run test_key_extractors_main.cpp test_key_extractors.cpp ]
: [ run test_list_ops_main.cpp test_list_ops.cpp ]
: [ run test_modifiers_main.cpp test_modifiers.cpp ]
: [ run test_mpl_ops_main.cpp test_mpl_ops.cpp ]
: [ run test_projection_main.cpp test_projection.cpp ]
: [ run test_range_main.cpp test_range.cpp ]
: [ run test_safe_mode_main.cpp test_safe_mode.cpp ]
: [ run test_set_ops_main.cpp test_set_ops.cpp ]
: [ run test_special_list_ops_main.cpp test_special_list_ops.cpp ]
: [ run test_special_set_ops_main.cpp test_special_set_ops.cpp ]
: [ run test_update_main.cpp test_update.cpp ]
;
}

88
test/employee.hpp Normal file
View File

@ -0,0 +1,88 @@
/* Used in Boost.MultiIndex tests.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_TEST_EMPLOYEE_HPP
#define BOOST_MULTI_INDEX_TEST_EMPLOYEE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <cstddef>
#include <ostream>
#include <string>
struct employee
{
int id;
std::string name;
int age;
employee(int id_,std::string name_,int age_):id(id_),name(name_),age(age_){}
bool operator==(const employee& x)const
{
return id==x.id&&name==x.name&&age==x.age;
}
bool operator<(const employee& x)const
{
return id<x.id;
}
struct comp_id
{
bool operator()(int x,const employee& e2)const{return x<e2.id;}
bool operator()(const employee& e1,int x)const{return e1.id<x;}
};
friend std::ostream& operator<<(std::ostream& os,const employee& e)
{
os<<e.id<<" "<<e.name<<" "<<e.age<<std::endl;
return os;
}
};
struct name{};
struct by_name{};
struct age{};
struct as_inserted{};
typedef
boost::multi_index::multi_index_container<
employee,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::identity<employee> >,
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<name,by_name>,
BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>,
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<age>,
BOOST_MULTI_INDEX_MEMBER(employee,int,age)>,
boost::multi_index::sequenced<
boost::multi_index::tag<as_inserted> > > >
employee_set;
#if defined(BOOST_NO_MEMBER_TEMPLATES)
typedef boost::multi_index::nth_index<
employee_set,1>::type employee_set_by_name;
#else
typedef employee_set::nth_index<1>::type employee_set_by_name;
#endif
typedef boost::multi_index::index<
employee_set,age>::type employee_set_by_age;
typedef boost::multi_index::index<
employee_set,as_inserted>::type employee_set_as_inserted;
#endif

34
test/pair_of_ints.hpp Normal file
View File

@ -0,0 +1,34 @@
/* Used in Boost.MultiIndex tests.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_TEST_PAIR_OF_INTS_HPP
#define BOOST_MULTI_INDEX_TEST_PAIR_OF_INTS_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <utility>
typedef std::pair<int,int> pair_of_ints;
inline void increment_first(pair_of_ints& p)
{
++p.first;
}
inline void increment_second(pair_of_ints& p)
{
++p.second;
}
inline void increment_int(int& x)
{
++x;
}
#endif

31
test/pre_multi_index.hpp Normal file
View File

@ -0,0 +1,31 @@
/* Used in Boost.MultiIndex tests.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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_TEST_PRE_MULTI_INDEX_HPP
#define BOOST_MULTI_INDEX_TEST_PRE_MULTI_INDEX_HPP
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#include <boost/multi_index/safe_mode_errors.hpp>
struct safe_mode_exception
{
safe_mode_exception(boost::multi_index::safe_mode::error_code error_code_):
error_code(error_code_)
{}
boost::multi_index::safe_mode::error_code error_code;
};
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) \
if(!(expr)){throw safe_mode_exception(error_code);}
#endif

53
test/test_all_main.cpp Normal file
View File

@ -0,0 +1,53 @@
/* Boost.MultiIndex test suite.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include <boost/test/included/test_exec_monitor.hpp>
#include "test_basic.hpp"
#include "test_capacity.hpp"
#include "test_comparison.hpp"
#include "test_composite_key.hpp"
#include "test_conv_iterators.hpp"
#include "test_copy_assignment.hpp"
#include "test_iterators.hpp"
#include "test_key_extractors.hpp"
#include "test_list_ops.hpp"
#include "test_modifiers.hpp"
#include "test_mpl_ops.hpp"
#include "test_projection.hpp"
#include "test_range.hpp"
#include "test_safe_mode.hpp"
#include "test_set_ops.hpp"
#include "test_special_list_ops.hpp"
#include "test_special_set_ops.hpp"
#include "test_update.hpp"
int test_main(int,char *[])
{
test_basic();
test_capacity();
test_comparison();
test_composite_key();
test_conv_iterators();
test_copy_assignment();
test_iterators();
test_key_extractors();
test_list_ops();
test_modifiers();
test_mpl_ops();
test_projection();
test_range();
test_safe_mode();
test_set_ops();
test_special_list_ops();
test_special_set_ops();
test_update();
return 0;
}

90
test/test_basic.cpp Normal file
View File

@ -0,0 +1,90 @@
/* Boost.MultiIndex basic test.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include "test_basic.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <vector>
#include "pre_multi_index.hpp"
#include "employee.hpp"
#include <boost/test/test_tools.hpp>
using namespace boost::multi_index;
struct less_by_employee_name
{
bool operator()(const employee& e1,const employee& e2)const
{
return e1.name<e2.name;
}
};
struct less_by_employee_age
{
bool operator()(const employee& e1,const employee& e2)const
{
return e1.age<e2.age;
}
};
void test_basic()
{
employee_set es;
std::vector<employee> v;
#if defined(BOOST_NO_MEMBER_TEMPLATES)
employee_set_by_name& i1=get<by_name>(es);
#else
employee_set_by_name& i1=es.get<by_name>();
#endif
const employee_set_by_age& i2=get<2>(es);
employee_set_as_inserted& i3=get<3>(es);
es.insert(employee(0,"Joe",31));
i1.insert(employee(1,"Robert",27));
es.insert(employee(2,"John",40));
i3.push_back(employee(3,"Albert",20));
es.insert(employee(4,"John",57));
v.push_back(employee(0,"Joe",31));
v.push_back(employee(1,"Robert",27));
v.push_back(employee(2,"John",40));
v.push_back(employee(3,"Albert",20));
v.push_back(employee(4,"John",57));
{
/* by insertion order */
BOOST_CHECK(std::equal(i3.begin(),i3.end(),v.begin()));
}
{
/* by id */
std::sort(v.begin(),v.end());
BOOST_CHECK(std::equal(es.begin(),es.end(),v.begin()));
}
{
/* by name */
std::sort(v.begin(),v.end(),less_by_employee_name());
BOOST_CHECK(std::equal(i1.begin(),i1.end(),v.begin()));
}
{
/* by age */
std::sort(v.begin(),v.end(),less_by_employee_age());
BOOST_CHECK(std::equal(i2.begin(),i2.end(),v.begin()));
}
}

11
test/test_basic.hpp Normal file
View File

@ -0,0 +1,11 @@
/* Boost.MultiIndex basic test.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
void test_basic();

18
test/test_basic_main.cpp Normal file
View File

@ -0,0 +1,18 @@
/* Boost.MultiIndex basic test.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include <boost/test/included/test_exec_monitor.hpp>
#include "test_basic.hpp"
int test_main(int,char *[])
{
test_basic();
return 0;
}

50
test/test_capacity.cpp Normal file
View File

@ -0,0 +1,50 @@
/* Boost.MultiIndex test for capacity memfuns.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include "test_capacity.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include "pre_multi_index.hpp"
#include "employee.hpp"
#include <boost/test/test_tools.hpp>
using namespace boost::multi_index;
void test_capacity()
{
employee_set es;
es.insert(employee(0,"Joe",31));
es.insert(employee(1,"Robert",27));
es.insert(employee(2,"John",40));
es.insert(employee(3,"Albert",20));
es.insert(employee(4,"John",57));
BOOST_CHECK(!es.empty());
BOOST_CHECK(es.size()==5);
es.erase(es.begin());
BOOST_CHECK(get<name>(es).size()==4);
es.erase(es.begin());
BOOST_CHECK(!get<as_inserted>(es).empty());
BOOST_CHECK(get<as_inserted>(es).size()==3);
multi_index_container<int,indexed_by<sequenced<> > > ss;
ss.resize(10);
BOOST_CHECK(ss.size()==10);
ss.resize(20);
BOOST_CHECK(ss.size()==20);
ss.resize(5);
BOOST_CHECK(ss.size()==5);
}

11
test/test_capacity.hpp Normal file
View File

@ -0,0 +1,11 @@
/* Boost.MultiIndex test for capacity memfuns.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
void test_capacity();

View File

@ -0,0 +1,19 @@
/* Boost.MultiIndex test for capacity memfuns.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include <boost/test/included/test_exec_monitor.hpp>
#include "test_capacity.hpp"
int test_main(int,char *[])
{
test_capacity();
return 0;
}

84
test/test_comparison.cpp Normal file
View File

@ -0,0 +1,84 @@
/* Boost.MultiIndex test for comparison functions.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include "test_comparison.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include "pre_multi_index.hpp"
#include "employee.hpp"
#include <boost/test/test_tools.hpp>
using namespace boost::multi_index;
template<typename Value>
struct lookup_list{
typedef multi_index_container<
Value,
indexed_by<
sequenced<>,
ordered_non_unique<identity<Value> >
>
> type;
};
void test_comparison()
{
employee_set es;
employee_set_by_name& i1=get<1>(es);
employee_set_as_inserted& i3=get<3>(es);
es.insert(employee(0,"Joe",31));
es.insert(employee(1,"Robert",27));
es.insert(employee(2,"John",40));
es.insert(employee(3,"Albert",20));
es.insert(employee(4,"John",57));
employee_set es2;
employee_set_by_name& i12=get<name>(es2);
employee_set_as_inserted& i32=get<3>(es2);
es2.insert(employee(0,"Joe",31));
es2.insert(employee(1,"Robert",27));
es2.insert(employee(2,"John",40));
es2.insert(employee(3,"Albert",20));
BOOST_CHECK(es==es&&es<=es&&es>=es&&
i12==i12&&i12<=i12&&i12>=i12&&
i32==i32&&i32<=i32&&i32>=i32);
BOOST_CHECK(es!=es2&&es2<es&&es>es2&&!(es<=es2)&&!(es2>=es));
BOOST_CHECK(i1!=i12&&i12<i1&&i1>i12&&!(i1<=i12)&&!(i12>=i1));
BOOST_CHECK(i3!=i32&&i32<i3&&i3>i32&&!(i3<=i32)&&!(i32>=i3));
lookup_list<int>::type l1;
lookup_list<char>::type l2;
lookup_list<long>::type l3;
l1.push_back(3);
l1.push_back(4);
l1.push_back(5);
l1.push_back(1);
l1.push_back(2);
l2.push_back(char(3));
l2.push_back(char(4));
l2.push_back(char(5));
l2.push_back(char(1));
l2.push_back(char(2));
l3.push_back(long(3));
l3.push_back(long(4));
l3.push_back(long(5));
l3.push_back(long(1));
BOOST_CHECK(l1==l2&&l1<=l2&&l1>=l2);
BOOST_CHECK(
get<1>(l1)==get<1>(l2)&&get<1>(l1)<=get<1>(l2)&&get<1>(l1)>=get<1>(l2));
BOOST_CHECK(l1!=l3&&l3<l1&&l1>l3);
BOOST_CHECK(
get<1>(l1)!=get<1>(l3)&&get<1>(l1)<get<1>(l3)&&get<1>(l3)>get<1>(l1));
}

11
test/test_comparison.hpp Normal file
View File

@ -0,0 +1,11 @@
/* Boost.MultiIndex test for comparison functions.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
void test_comparison();

View File

@ -0,0 +1,19 @@
/* Boost.MultiIndex test for comparison functions.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include <boost/test/included/test_exec_monitor.hpp>
#include "test_comparison.hpp"
int test_main(int,char *[])
{
test_comparison();
return 0;
}

448
test/test_composite_key.cpp Normal file
View File

@ -0,0 +1,448 @@
/* Boost.MultiIndex test for composite_key.
*
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
* distribution are subject to 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.
*/
#include "test_composite_key.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include "pre_multi_index.hpp"
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/test/test_tools.hpp>
using namespace boost::multi_index;
using namespace boost::tuples;
template<typename T>
struct is_composite_key_result
{
typedef char yes;
struct no{char m[2];};
static no test(void *);
template<typename CompositeKey>
static yes test(composite_key_result<CompositeKey>*);
static T* make();
BOOST_STATIC_CONSTANT(bool,value=(sizeof(test(make()))==sizeof(yes)));
};
template<typename CompositeKeyResult>
struct composite_key_result_length
{
BOOST_STATIC_CONSTANT(int,
value=boost::tuples::length<
BOOST_DEDUCED_TYPENAME
CompositeKeyResult::composite_key_type::key_extractor_tuple
>::value);
};
template<typename T>
struct composite_object_length
{
typedef typename boost::mpl::if_c<
is_composite_key_result<T>::value,
composite_key_result_length<T>,
boost::tuples::length<T>
>::type type;
BOOST_STATIC_CONSTANT(int,value=type::value);
};
template<typename CompositeKeyResult,typename T2>
struct comparison_equal_length
{
static bool is_less(const CompositeKeyResult& x,const T2& y)
{
composite_key_result_less<CompositeKeyResult> lt;
composite_key_result_greater<CompositeKeyResult> gt;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
std::less<CompositeKeyResult> std_lt;
std::greater<CompositeKeyResult> std_gt;
#endif
return (x< y) && !(y< x)&&
!(x==y) && !(y==x)&&
(x!=y) && (y!=x)&&
!(x> y) && (y> x)&&
!(x>=y) && (y>=x)&&
(x<=y) && !(y<=x)&&
lt(x,y) && !lt(y,x)&&
!gt(x,y) && gt(y,x)
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
&&
std_lt(x,y) && !std_lt(y,x)&&
!std_gt(x,y) && std_gt(y,x)
#endif
;
}
static bool is_greater(const CompositeKeyResult& x,const T2& y)
{
composite_key_result_less<CompositeKeyResult> lt;
composite_key_result_greater<CompositeKeyResult> gt;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
std::less<CompositeKeyResult> std_lt;
std::greater<CompositeKeyResult> std_gt;
#endif
return !(x< y) && (y< x)&&
!(x==y) && !(y==x)&&
(x!=y) && (y!=x)&&
(x> y) && !(y> x)&&
(x>=y) && !(y>=x)&&
!(x<=y) && (y<=x)&&
!lt(x,y) && lt(y,x)&&
gt(x,y) && !gt(y,x)
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
&&
!std_lt(x,y) && std_lt(y,x)&&
std_gt(x,y) && !std_gt(y,x)
#endif
;
}
static bool is_equiv(const CompositeKeyResult& x,const T2& y)
{
composite_key_result_less<CompositeKeyResult> lt;
composite_key_result_greater<CompositeKeyResult> gt;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
std::less<CompositeKeyResult> std_lt;
std::greater<CompositeKeyResult> std_gt;
#endif
return !(x< y) && !(y< x)&&
(x==y) && (y==x)&&
!(x!=y) && !(y!=x)&&
!(x> y) && !(y> x)&&
(x>=y) && (y>=x)&&
(x<=y) && (y<=x)&&
!lt(x,y) && !lt(y,x)&&
!gt(x,y) && !gt(y,x)
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
&&
!std_lt(x,y) && !std_lt(y,x)&&
!std_gt(x,y) && !std_gt(y,x)
#endif
;
}
};
template<typename CompositeKeyResult,typename T2>
struct comparison_different_length
{
static bool is_less(const CompositeKeyResult& x,const T2& y)
{
composite_key_result_less<CompositeKeyResult> lt;
composite_key_result_greater<CompositeKeyResult> gt;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
std::less<CompositeKeyResult> std_lt;
std::greater<CompositeKeyResult> std_gt;
#endif
return (x< y) && !(y< x)&&
!(x> y) && (y> x)&&
!(x>=y) && (y>=x)&&
(x<=y) && !(y<=x)&&
lt(x,y) && !lt(y,x)&&
!gt(x,y) && gt(y,x)
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
&&
std_lt(x,y) && !std_lt(y,x)&&
!std_gt(x,y) && std_gt(y,x)
#endif
;
}
static bool is_greater(const CompositeKeyResult& x,const T2& y)
{
composite_key_result_less<CompositeKeyResult> lt;
composite_key_result_greater<CompositeKeyResult> gt;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
std::less<CompositeKeyResult> std_lt;
std::greater<CompositeKeyResult> std_gt;
#endif
return !(x< y) && (y< x)&&
(x> y) && !(y> x)&&
(x>=y) && !(y>=x)&&
!(x<=y) && (y<=x)&&
!lt(x,y) && lt(y,x)&&
gt(x,y) && !gt(y,x)
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
&&
!std_lt(x,y) && std_lt(y,x)&&
std_gt(x,y) && !std_gt(y,x)
#endif
;
}
static bool is_equiv(const CompositeKeyResult& x,const T2& y)
{
composite_key_result_less<CompositeKeyResult> lt;
composite_key_result_greater<CompositeKeyResult> gt;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
std::less<CompositeKeyResult> std_lt;
std::greater<CompositeKeyResult> std_gt;
#endif
return !(x< y) && !(y< x)&&
!(x> y) && !(y> x)&&
(x>=y) && (y>=x)&&
(x<=y) && (y<=x)&&
!lt(x,y) && !lt(y,x)&&
!gt(x,y) && !gt(y,x)
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
&&
!std_lt(x,y) && !std_lt(y,x)&&
!std_gt(x,y) && !std_gt(y,x)
#endif
;
}
};
template<typename CompositeKeyResult,typename T2>
struct comparison_helper:
boost::mpl::if_c<
composite_key_result_length<CompositeKeyResult>::value==
composite_object_length<T2>::value,
comparison_equal_length<CompositeKeyResult,T2>,
comparison_different_length<CompositeKeyResult,T2>
>::type
{
};
template<typename CompositeKeyResult,typename T2>
static bool is_less(const CompositeKeyResult& x,const T2& y)
{
return comparison_helper<CompositeKeyResult,T2>::is_less(x,y);
}
template<typename CompositeKeyResult,typename T2>
static bool is_greater(const CompositeKeyResult& x,const T2& y)
{
return comparison_helper<CompositeKeyResult,T2>::is_greater(x,y);
}
template<typename CompositeKeyResult,typename T2>
static bool is_equiv(const CompositeKeyResult& x,const T2& y)
{
return comparison_helper<CompositeKeyResult,T2>::is_equiv(x,y);
}
template<typename T1,typename T2,typename Compare>
static bool is_less(const T1& x,const T2& y,const Compare& c)
{
return c(x,y)&&!c(y,x);
}
template<typename T1,typename T2,typename Compare>
static bool is_greater(const T1& x,const T2& y,const Compare& c)
{
return c(y,x)&&!c(x,y);
}
template<typename T1,typename T2,typename Compare>
static bool is_equiv(const T1& x,const T2& y,const Compare& c)
{
return !c(x,y)&&!c(y,x);
}
struct xyz
{
xyz(int x_=0,int y_=0,int z_=0):x(x_),y(y_),z(z_){}
int x;
int y;
int z;
};
void test_composite_key()
{
typedef composite_key<
xyz,
BOOST_MULTI_INDEX_MEMBER(xyz,int,x),
BOOST_MULTI_INDEX_MEMBER(xyz,int,y),
BOOST_MULTI_INDEX_MEMBER(xyz,int,z)
> ckey_t1;
typedef multi_index_container<
xyz,
indexed_by<
ordered_unique<
ckey_t1
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
,composite_key_result_less<ckey_t1::result_type>
#endif
>
>
> indexed_t;
indexed_t mc;
mc.insert(xyz(0,0,0));
mc.insert(xyz(0,0,1));
mc.insert(xyz(0,1,0));
mc.insert(xyz(0,1,1));
mc.insert(xyz(1,0,0));
mc.insert(xyz(1,0,1));
mc.insert(xyz(1,1,0));
mc.insert(xyz(1,1,1));
BOOST_CHECK(mc.size()==8);
BOOST_CHECK(
std::distance(
mc.find(mc.key_extractor()(xyz(0,0,0))),
mc.find(mc.key_extractor()(xyz(1,0,0))))==4);
BOOST_CHECK(
std::distance(
mc.find(make_tuple(0,0,0)),
mc.find(make_tuple(1,0,0)))==4);
BOOST_CHECK(
std::distance(
mc.lower_bound(make_tuple(0,0)),
mc.upper_bound(make_tuple(1,0)))==6);
ckey_t1 ck1;
ckey_t1 ck2(ck1);
ckey_t1 ck3(
boost::make_tuple(
BOOST_MULTI_INDEX_MEMBER(xyz,int,x)(),
BOOST_MULTI_INDEX_MEMBER(xyz,int,y)(),
BOOST_MULTI_INDEX_MEMBER(xyz,int,z)()));
ckey_t1 ck4(get<0>(ck1.key_extractors()));
get<2>(ck4.key_extractors())=
get<2>(ck2.key_extractors());
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0))));
BOOST_CHECK(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0))));
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0))));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0)));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(1)));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(-1)));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0)));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,1)));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,-1)));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0)));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1)));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1)));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0,1)));
typedef composite_key_result_less<ckey_t1::result_type> ckey_comp_t1;
ckey_comp_t1 cp1;
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp1));
BOOST_CHECK(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp1));
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp1));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp1));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(1),cp1));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(-1),cp1));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp1));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,1),cp1));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,-1),cp1));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp1));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1),cp1));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp1));
typedef composite_key_result_greater<ckey_t1::result_type> ckey_comp_t2;
ckey_comp_t2 cp2;
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp2));
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp2));
BOOST_CHECK(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp2));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp2));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(1),cp2));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(-1),cp2));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp2));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,1),cp2));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,-1),cp2));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp2));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,1),cp2));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp2));
typedef composite_key_compare<
std::less<int>,
std::greater<int>, /* order reversed */
std::less<int>
> ckey_comp_t3;
ckey_comp_t3 cp3;
ckey_comp_t3 cp4(cp3);
ckey_comp_t3 cp5(
boost::make_tuple(
std::less<int>(),
std::greater<int>(),
std::less<int>()));
ckey_comp_t3 cp6(get<0>(cp3.key_comps()));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp3));
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp3));
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp3));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp3));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(1),cp3));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(-1),cp3));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp3));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,-1),cp3));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,1),cp3));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp3));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1),cp3));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp3));
typedef composite_key<
xyz,
BOOST_MULTI_INDEX_MEMBER(xyz,int,y), /* members reversed */
BOOST_MULTI_INDEX_MEMBER(xyz,int,x)
> ckey_t2;
ckey_t2 ck5;
BOOST_CHECK(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0))));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0))));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0))));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp1));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp1));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp1));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp2));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp2));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp2));
BOOST_CHECK(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp3));
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp3));
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp3));
}

Some files were not shown because too many files have changed in this diff Show More