initial commit
[SVN r22759]
96
.gitattributes
vendored
Normal 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
@ -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
@ -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árdez proofread the last version of the tutorial.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pavel Vožení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žení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ö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 "as is" 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 "as is" 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árdez, my very first
|
||||
C++ teacher, for her unconditional support in many endeavors of which programming is
|
||||
by no means the most important. In memory of my cat López (2001-2003): he
|
||||
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 © 2003-2004 Joaquín M López Muñ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
314
doc/compiler_specifics.html
Normal 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><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><...></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><...></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><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><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 © 2003-2004 Joaquín M López Muñ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
@ -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<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><</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>></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>&</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>&</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><</span><span class=keyword>typename</span> <span class=identifier>Arg</span><span class=special>></span>
|
||||
<span class=identifier>result_type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Arg</span><span class=special>&</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><</span>
|
||||
<span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>car_manufacturer</span><span class=special>::</span><span class=identifier>name</span><span class=special>>,</span>
|
||||
<span class=identifier>member</span><span class=special><</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>></span>
|
||||
<span class=special>></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><directory></i>]</code></li>
|
||||
<li><code>ls [-s]</code> (<code>-s</code> orders the output by size)</li>
|
||||
<li><code>mkdir <i><directory></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 © 2003-2004 Joaquín M López Muñ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
@ -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><<</span><span class=string>"insert: "</span><span class=special><<</span><span class=identifier>x</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
|
||||
<span class=special>}</span>
|
||||
<span class=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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>notifying</span><span class=special><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span> <span class=special>>,</span> <span class=comment>// notifying index</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>indexed_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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>constrained</span><span class=special><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span><span class=identifier>is_even</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>indexed_t</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<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><</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>></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><<</span><span class=identifier>m</span><span class=special>[</span><span class=number>0</span><span class=special>]<<</span><span class=identifier>endl</span><span class=special>;</span> <span class=comment>// OK</span>
|
||||
<span class=identifier>cout</span><span class=special><<</span><span class=identifier>m</span><span class=special>[</span><span class=string>"zero"</span><span class=special>]<<</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<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 © 2003-2004 Joaquín M López Muñ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
@ -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 © 2003-2004 Joaquín M López Muñ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
After Width: | Height: | Size: 15 KiB |
BIN
doc/multi_index_cont_example.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
doc/next.gif
Normal file
After Width: | Height: | Size: 852 B |
BIN
doc/perf_1o.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
doc/perf_1o1s.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
doc/perf_1s.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
doc/perf_2o.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
doc/perf_2o1s.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
doc/perf_3o.png
Normal file
After Width: | Height: | Size: 13 KiB |
724
doc/performance.html
Normal 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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>>,</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>greater</span> <span class=special>>,</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>indexed_t</span><span class=special>;</span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<code>indexed_t</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>Iterator</span><span class=special>&</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>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><</span><span class=keyword>int</span><span class=special>></span> <span class=identifier>manual_t1</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #0</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special><</span>
|
||||
<span class=keyword>const</span> <span class=keyword>int</span><span class=special>*,</span>
|
||||
<span class=identifier>it_compare</span><span class=special><</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><</span><span class=keyword>int</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>manual_t2</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #1</span>
|
||||
</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>(&*</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><</span><span class=keyword>int</span><span class=special>></span> <span class=identifier>manual_t1</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #0</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special><</span>
|
||||
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span>
|
||||
<span class=identifier>it_compare</span><span class=special><</span>
|
||||
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>greater</span><span class=special><</span><span class=keyword>int</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>manual_t2</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #1</span>
|
||||
</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> / <i>S<sub>M</sub></i>, which can be expressed
|
||||
then as:
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<i>S<sub>I</sub></i> / <i>S<sub>M</sub></i> =
|
||||
<i>S<sub>I</sub></i> / (<i>S<sub>I</sub></i> + (<i>N</i>-1)<i>p</i>).
|
||||
</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><...></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><</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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
which is functionally equivalent to <code>std::set<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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>sequenced</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
which is functionally equivalent to <code>std::list<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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
</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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>sequenced</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
</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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
</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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>sequenced</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
</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 © 2003-2004 Joaquín M López Muñ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
After Width: | Height: | Size: 852 B |
116
doc/reference/index.html
Normal 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 © 2003-2004 Joaquín M López Muñ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
@ -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><</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Tn</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>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><</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Tn</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>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><</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Tn</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>tag</span><span class=special>;</span>
|
||||
|
||||
<span class=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><</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Tn</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>tag</span><span class=special>;</span>
|
||||
</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 © 2003-2004 Joaquín M López Muñ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>
|
1505
doc/reference/key_extraction.html
Normal file
831
doc/reference/multi_index_container.html
Normal 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><</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><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>Value</span><span class=special>></span> <span class=special>></span> <span class=special>>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special><</span><span class=identifier>Value</span><span class=special>></span> <span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>></span>
|
||||
<span class=keyword>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><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index_const_iterator</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// multi_index_container global functions for index retrieval:</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>&</span>
|
||||
<span class=identifier>get</span><span class=special>(</span><span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>&</span>
|
||||
<span class=identifier>get</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>&</span>
|
||||
<span class=identifier>get</span><span class=special>(</span><span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>&</span>
|
||||
<span class=identifier>get</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>);</span>
|
||||
|
||||
<span class=comment>// multi_index_container global functions for projection of iterators:</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
|
||||
<span class=comment>// comparison:</span>
|
||||
|
||||
<span class=comment>// <b>OP</b> is any of ==,<,!=,>,>=,<=</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>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>></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><</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>>&</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><</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>>&</span> <span class=identifier>y</span><span class=special>);</span>
|
||||
|
||||
<span class=comment>// specialized algorithms:</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>></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><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>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><</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><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>Value</span><span class=special>></span> <span class=special>></span> <span class=special>>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>allocator</span><span class=special><</span><span class=identifier>Value</span><span class=special>></span> <span class=special>></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><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
|
||||
|
||||
<span class=comment>// construct/copy/destroy:</span>
|
||||
|
||||
<span class=keyword>explicit</span> <span class=identifier>multi_index_container</span><span class=special>(
|
||||
</span><span class=keyword>const</span> <span class=identifier>ctor_args_list</span><span class=special>&</span> <span class=identifier>args_list</span><span class=special>=</span><span class=identifier>ctor_args_list</span><span class=special>(),
|
||||
</span><span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&</span> <span class=identifier>al</span><span class=special>=</span><span class=identifier>allocator_type</span><span class=special>());</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special>(</span>
|
||||
<span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>InputIterator</span> <span class=identifier>last</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>ctor_args_list</span><span class=special>&</span> <span class=identifier>args_list</span><span class=special>=</span><span class=identifier>ctor_args_list</span><span class=special>(),
|
||||
</span><span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&</span> <span class=identifier>al</span><span class=special>=</span><span class=identifier>allocator_type</span><span class=special>());</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>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><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=keyword>operator</span><span class=special>=(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>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><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span><span class=special>&</span> <span class=identifier>get</span><span class=special>();</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span><span class=special>&</span> <span class=identifier>get</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span><span class=special>&</span> <span class=identifier>get</span><span class=special>()</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span><span class=special>&</span> <span class=identifier>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><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=comment>// multi_index_container associated global class templates:</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index</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><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index</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><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>nth_index_iterator</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>nth_index_const_iterator</span><span class=special><</span><span class=identifier>N</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index_iterator</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>index_iterator</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>></span> <span class=keyword>struct</span> <span class=identifier>index_const_iterator</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>index_const_iterator</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=comment>// multi_index_container global functions for index retrieval:</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>&</span>
|
||||
<span class=identifier>get</span><span class=special>(</span><span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>get</span><span class=special><</span><span class=identifier>N</span><span class=special>>();</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>&</span>
|
||||
<span class=identifier>get</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>get</span><span class=special><</span><span class=identifier>N</span><span class=special>>();</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>&</span>
|
||||
<span class=identifier>get</span><span class=special>(</span><span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>get</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>();</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>const</span> <span class=keyword>typename</span> <span class=identifier>index</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span><span class=special>&</span>
|
||||
<span class=identifier>get</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>get</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>();</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><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=identifier>N</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>N</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=identifier>N</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special><</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>,</span><span class=identifier>Tag</span>
|
||||
<span class=special>>::</span><span class=identifier>type</span>
|
||||
<span class=identifier>project</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>m</span><span class=special>,</span>
|
||||
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
|
||||
<span class=special>{</span>
|
||||
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=identifier>Tag</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=comment>// comparison:</span>
|
||||
|
||||
<span class=comment>// <b>OP</b> is any of ==,<,!=,>,>=,<=</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span>
|
||||
<span class=keyword>typename</span> <span class=identifier>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>></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><</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>>&</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><</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>>&</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><</span><span class=number>0</span><span class=special>>(</span><span class=identifier>x</span><span class=special>)</span> <b><i>OP</i></b> <span class=identifier>get</span><span class=special><</span><span class=number>0</span><span class=special>>(</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><</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>></span>
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>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<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<C<sub>0</sub>,...,C<sub>I-1</sub>>&</code>
|
||||
to <code>const ctor_args_list&</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<int N> struct nth_index</code>
|
||||
|
||||
<blockquote>
|
||||
<code>nth_index<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 <= N < I</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag> struct index</code>
|
||||
|
||||
<blockquote>
|
||||
<code>index<Tag>::type</code> yields the type of the index which
|
||||
has <code>Tag</code> as an associated <a href="indices.html#tags">tag type</a>.</br>
|
||||
<b>Requires:</b> Some index of the <code>multi_index_container</code> has <code>Tag</code>
|
||||
as an associated tag type.
|
||||
</blockquote>
|
||||
|
||||
<code>template<int N> struct nth_index_iterator</code>
|
||||
|
||||
<blockquote>
|
||||
<code>nth_index_iterator<N>::type</code> is equivalent to
|
||||
<code>nth_index<N>::type::iterator</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<int N> struct nth_index_const_iterator</code>
|
||||
|
||||
<blockquote>
|
||||
<code>nth_index_const_iterator<N>::type</code> is equivalent to
|
||||
<code>nth_index<N>::type::const_iterator</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag> struct index_iterator</code>
|
||||
|
||||
<blockquote>
|
||||
<code>index_iterator<Tag>::type</code> is equivalent to
|
||||
<code>index<Tag>::type::iterator</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag> struct index_const_iterator</code>
|
||||
|
||||
<blockquote>
|
||||
<code>index_const_iterator<Tag>::type</code> is equivalent to
|
||||
<code>index<Tag>::type::const_iterator</code>.<br>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
|
||||
|
||||
<code>explicit multi_index_container(<br>
|
||||
const ctor_args_list& comp=ctor_args_list(),<br>
|
||||
const allocator_type& 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<typename InputIterator><br>
|
||||
multi_index_container(<br>
|
||||
InputIterator first,InputIterator last,<br>
|
||||
const ctor_args_list& comp=ctor_args_list(),<br>
|
||||
const allocator_type& 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>
|
||||
const multi_index_container<Value,IndexSpecifierList,Allocator>& 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<Value,IndexSpecifierList,Allocator>& operator=(<br>
|
||||
const multi_index_container<Value,IndexSpecifierList,Allocator>& 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<int N> typename nth_index<N>::type& get();</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>0 <= N < I</code>.<br>
|
||||
<b>Effects:</b> Returns a reference to the
|
||||
<code>nth_index<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<int N> const typename nth_index<N>::type& get()const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>0 <= N < I</code>.<br>
|
||||
<b>Effects:</b> Returns a <code>const</code> reference to the
|
||||
<code>nth_index<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<typename Tag> typename index<Tag>::type& get()</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Tag</code> is such that <code>index<Tag>::type</code>
|
||||
is valid.<br>
|
||||
<b>Effects:</b> Returns a reference to the
|
||||
<code>index<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<typename Tag> const typename index<Tag>::type& get()const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Tag</code> is such that <code>index<Tag>::type</code>
|
||||
is valid.<br>
|
||||
<b>Effects:</b> Returns a <code>const</code> reference to the
|
||||
<code>index<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<int N,typename IteratorType><br>
|
||||
typename nth_index_iterator<N>::type project(IteratorType it);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>0 <= N < I</code>. <code>IteratorType</code>
|
||||
belongs to <code>iterator_type_list</code>. <code>it</code> is a valid
|
||||
iterator of some index of <code>*this</code> (i.e. does not refer to some
|
||||
other <code>multi_index_container</code>.)<br>
|
||||
<b>Effects:</b> Returns an <code>nth_index_iterator<N>::type</code> iterator
|
||||
equivalent to <code>it</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>template<int N,typename IteratorType><br>
|
||||
typename nth_index_const_iterator<N>::type project(IteratorType it)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>0 <= N < 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<N>::type</code>
|
||||
iterator equivalent to <code>it</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag,typename IteratorType><br>
|
||||
typename index_iterator<Tag>::type project(IteratorType it);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Tag</code> is such that
|
||||
<code>index_iterator<Tag>::type</code> is valid. <code>IteratorType</code>
|
||||
belongs to <code>iterator_type_list</code>. <code>it</code> is a valid
|
||||
iterator of some index of <code>*this</code> (i.e. does not refer to some
|
||||
other <code>multi_index_container</code>.)<br>
|
||||
<b>Effects:</b> Returns an <code>index_iterator<Tag>::type</code> iterator
|
||||
equivalent to <code>it</code>.<br>
|
||||
<b>Complexity:</b> Constant.<br>
|
||||
<b>Exception safety:</b> <code>nothrow</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename Tag,typename IteratorType><br>
|
||||
typename index_const_iterator<Tag>::type project(IteratorType it)const;</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Tag</code> is such that
|
||||
<code>index_const_iterator<Tag>::type</code> is valid. <code>IteratorType</code>
|
||||
belongs to <code>const_iterator_type_list</code> or
|
||||
<code>iterator_type_list</code>. <code>it</code> is a valid
|
||||
(constant or non-constant) iterator of some index of <code>*this</code>
|
||||
(i.e. does not refer to some other <code>multi_index_container</code>.)<br>
|
||||
<b>Effects:</b> Returns an <code>index_const_iterator<Tag>::type</code>
|
||||
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 © 2003-2004 Joaquín M López Muñ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>
|
909
doc/reference/ord_indices.html
Normal 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><</span><b>consult ordered_unique reference for arguments</b><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>ordered_unique</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><b>consult ordered_non_unique reference for arguments</b><span class=special>></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><</span><b>implementation defined</b><span class=special>></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><</span><b>consult ordered_unique reference for arguments</b><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>ordered_unique</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><b>consult ordered_non_unique reference for arguments</b><span class=special>></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><</span><b>implementation defined</b><span class=special>></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 ==,<,!=,>,>=,<=</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>implementation defined</b><span class=special>></span>
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&</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><</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><</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span>
|
||||
<span class=special>></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><</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><</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>></span>
|
||||
<span class=special>></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><</span><b>implementation defined: dependent on types Value, Allocator,
|
||||
TagList, KeyFromValue, Compare</b><span class=special>></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><</span><span class=identifier>key_from_value</span><span class=special>,</span><span class=identifier>key_compare</span><span class=special>></span> <span class=identifier>ctor_args</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>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<iterator></b> <span class=identifier>reverse_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <b>equivalent to
|
||||
std::reverse_iterator<const_iterator></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>&</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <b>index class name</b><span class=special>&</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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></span>
|
||||
<span class=keyword>void</span> <span class=identifier>insert</span><span class=special>(</span><span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>InputIterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
|
||||
<span class=identifier>size_type</span> <span class=identifier>erase</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>key_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></span> <span class=keyword>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>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>></span> <span class=identifier>equal_range</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</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>></span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>></span> <span class=identifier>equal_range</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</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>></span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>></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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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>()&&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><span class=identifier>x</span><span class=special>;</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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=comment>// index specialized algorithms:</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>implementation defined</b><span class=special>></span>
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&</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>& operator=(const <b>index class name</b>& 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<iterator,bool> insert(const value_type& 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& 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<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& 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& 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<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&</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<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&</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<typename CompatibleKey> const_iterator find(const CompatibleKey& 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<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
const_iterator find(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
<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<typename CompatibleKey> size_type<br>
|
||||
count(const CompatibleKey& 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<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
<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<typename CompatibleKey><br>
|
||||
const_iterator lower_bound(const CompatibleKey& 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<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
const_iterator lower_bound(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
<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<typename CompatibleKey><br>
|
||||
const_iterator upper_bound(const CompatibleKey& 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<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
const_iterator upper_bound(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
<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<typename CompatibleKey><br>
|
||||
std::pair<const_iterator,const_iterator> equal_range(<br>
|
||||
const CompatibleKey& 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<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
std::pair<const_iterator,const_iterator> equal_range(</br>
|
||||
const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
|
||||
is a compatible extension of <code>key_compare</code>.</br>
|
||||
<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<typename LowerBounder,typename UpperBounder><br>
|
||||
std::pair<const_iterator,const_iterator> range(<br>
|
||||
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 © 2003-2004 Joaquín M López Muñ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>
|
837
doc/reference/seq_indices.html
Normal 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><</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special><></span> <span class=special>></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><</span><b>implementation defined</b><span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special><></span> <span class=special>></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><</span><b>implementation defined</b><span class=special>></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 ==,<,!=,>,>=,<=</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>implementation defined</b><span class=special>></span>
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special><></span> <span class=special>></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><</span><b>implementation defined: dependent on types Value, Allocator, TagList</b><span class=special>></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<iterator></b> <span class=identifier>reverse_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <b>equivalent to
|
||||
std::reverse_iterator<const_iterator></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>&</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>template</span> <span class=special><</span><span class=keyword>class</span> <span class=identifier>InputIterator</span><span class=special>></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>&</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>&</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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></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>&</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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></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>&</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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></span> <span class=identifier>insert</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</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>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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
|
||||
|
||||
<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>&</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>&</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>&</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>&</span> <span class=identifier>value</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Predicate</span><span class=special>></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><</span><span class=keyword>class</span> <span class=identifier>BinaryPredicate</span><span class=special>></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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span> <span class=special><</span><span class=keyword>typename</span> <span class=identifier>Compare</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>&</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><</span><span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>></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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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>()&&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span>
|
||||
<span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><span class=identifier>x</span><span class=special>;</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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=comment>// index specialized algorithms:</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>implementation defined</b><span class=special>></span>
|
||||
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&</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>& operator=(const <b>index class name</b>& 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 <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& 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><</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& 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>></span><span class=identifier>size</span><span class=special>())</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>n</span><span class=special>-</span><span class=identifier>size</span><span class=special>(),</span><span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>else</span> <span class=keyword>if</span><span class=special>(</span><span class=identifier>n</span><span class=special><</span><span class=identifier>size</span><span class=special>())</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>begin</span><span class=special>()+</span><span class=identifier>n</span><span class=special>,</span><span class=identifier>end</span><span class=special>());</span>
|
||||
</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<iterator,bool> push_front(const value_type& 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<iterator,bool> push_back(const value_type& 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& 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& 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><</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<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& 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<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&</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>& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
|
||||
<code>&x!=this</code>.</br>
|
||||
<b>Effects:</b> Inserts the contents of <code>x</code> before <code>position</code>,
|
||||
in the same order as they were in <code>x</code>. Those elements succesfully
|
||||
inserted are erased from <code>x</code>.<br>
|
||||
<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>& 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>&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>&x==this</code>, no iterator or reference
|
||||
is invalidated.<br>
|
||||
<b>Complexity:</b> If <code>&x==this</code>, constant; otherwise
|
||||
<code>O(I(n) + D(n))</code>.<br>
|
||||
<b>Exception safety:</b> If <code>&x==this</code>, <code>nothrow</code>;
|
||||
otherwise, strong.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void splice(iterator position,<b>index class name&</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>&x==this</code>, no copy or deletion is performed, and insertions are
|
||||
always succesful.<br>
|
||||
<b>Postconditions:</b> If <code>&x==this</code>, no iterator or reference
|
||||
is invalidated.<br>
|
||||
<b>Complexity:</b> If <code>&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>&x==this</code>, <code>nothrow</code>;
|
||||
otherwise, basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void remove(const value_type& 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<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 <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& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>std::less<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<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>&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>&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>&x==this</code>, <code>nothrow</code>;
|
||||
otherwise, basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template <typename Compare> void merge(index class name& 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>&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>&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>&x==this</code>, <code>nothrow</code>;
|
||||
otherwise, basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void sort();</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>std::less<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<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<value_type></code> does not throw; otherwise, basic.
|
||||
</blockquote>
|
||||
|
||||
<code>template <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 © 2003-2004 Joaquín M López Muñ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
@ -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
@ -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 © 2003-2004 Joaquín M López Muñ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
BIN
doc/up.gif
Normal file
After Width: | Height: | Size: 853 B |
44
example/Jamfile
Normal 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
@ -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
@ -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
@ -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
@ -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
@ -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;
|
||||
}
|
96
example/non_default_ctor.cpp
Normal 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
@ -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;
|
||||
}
|
948
include/boost/multi_index/composite_key.hpp
Normal 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
|
39
include/boost/multi_index/detail/access_specifier.hpp
Normal 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
|
213
include/boost/multi_index/detail/allocator.hpp
Normal 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
|
64
include/boost/multi_index/detail/auto_space.hpp
Normal 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
|
81
include/boost/multi_index/detail/base_type.hpp
Normal 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
|
48
include/boost/multi_index/detail/converter.hpp
Normal 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
|
127
include/boost/multi_index/detail/copy_map.hpp
Normal 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
|
55
include/boost/multi_index/detail/def_ctor_tuple_cons.hpp
Normal 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
|
38
include/boost/multi_index/detail/has_tag.hpp
Normal 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
|
49
include/boost/multi_index/detail/header_holder.hpp
Normal 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
|
133
include/boost/multi_index/detail/index_base.hpp
Normal 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
|
140
include/boost/multi_index/detail/index_iterator.hpp
Normal 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
|
40
include/boost/multi_index/detail/index_iterator_fwd.hpp
Normal 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
|
39
include/boost/multi_index/detail/index_node_base.hpp
Normal 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
|
78
include/boost/multi_index/detail/index_proxy.hpp
Normal 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
|
17
include/boost/multi_index/detail/invariant_assert.hpp
Normal 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
|
36
include/boost/multi_index/detail/is_index_list.hpp
Normal 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
|
45
include/boost/multi_index/detail/modify_key_adaptor.hpp
Normal 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
|
65
include/boost/multi_index/detail/msvc_index_specifier.hpp
Normal 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
|
93
include/boost/multi_index/detail/no_duplicate_tags.hpp
Normal 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
|
73
include/boost/multi_index/detail/node_type.hpp
Normal 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
|
86
include/boost/multi_index/detail/ord_index_args.hpp
Normal 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
|
457
include/boost/multi_index/detail/ord_index_node.hpp
Normal 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
|
121
include/boost/multi_index/detail/ord_index_ops.hpp
Normal 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
|
56
include/boost/multi_index/detail/prevent_eti.hpp
Normal 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
|
339
include/boost/multi_index/detail/safe_mode.hpp
Normal 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
|
270
include/boost/multi_index/detail/scope_guard.hpp
Normal 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
|
197
include/boost/multi_index/detail/seq_index_node.hpp
Normal 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
|
164
include/boost/multi_index/detail/seq_index_ops.hpp
Normal 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
|
35
include/boost/multi_index/detail/unbounded.hpp
Normal 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
|
48
include/boost/multi_index/detail/value_compare.hpp
Normal 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
|
119
include/boost/multi_index/identity.hpp
Normal 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
|
22
include/boost/multi_index/identity_fwd.hpp
Normal 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
|
68
include/boost/multi_index/indexed_by.hpp
Normal 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
|
17
include/boost/multi_index/key_extractors.hpp
Normal 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
|
171
include/boost/multi_index/mem_fun.hpp
Normal 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
|
228
include/boost/multi_index/member.hpp
Normal 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
|
1124
include/boost/multi_index/ordered_index.hpp
Normal file
112
include/boost/multi_index/ordered_index_fwd.hpp
Normal 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
|
43
include/boost/multi_index/safe_mode_errors.hpp
Normal 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
|
751
include/boost/multi_index/sequenced_index.hpp
Normal 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
|
87
include/boost/multi_index/sequenced_index_fwd.hpp
Normal 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
|
79
include/boost/multi_index/tag.hpp
Normal 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
|
864
include/boost/multi_index_container.hpp
Normal 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
|
117
include/boost/multi_index_container_fwd.hpp
Normal 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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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();
|
19
test/test_capacity_main.cpp
Normal 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
@ -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
@ -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();
|
19
test/test_comparison_main.cpp
Normal 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
@ -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));
|
||||
}
|