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));
|
||||||
|
}
|