First inclusion

[SVN r37592]
This commit is contained in:
Ion Gaztañaga 2007-05-04 21:22:02 +00:00
commit fe23901b24
29 changed files with 13078 additions and 0 deletions

96
.gitattributes vendored Normal file
View File

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

View File

@ -0,0 +1,319 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/get_pointer.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
//! circular_list_algorithms provides basic algorithms to manipulate nodes
//! forming a circular doubly linked list. An empty circular list is formed by a node
//! whose pointers point to itself.
//!
//! circular_list_algorithms is configured with a NodeTraits class, which encapsulates the
//! information about the node to be manipulated. NodeTraits must support the
//! following interface:
//!
//! <b>Typedefs</b>:
//!
//! <tt>node</tt>: The type of the node that forms the circular list
//!
//! <tt>node_ptr</tt>: A pointer to a node
//!
//! <tt>const_node_ptr</tt>: A pointer to a const node
//!
//! <b>Static functions</b>:
//!
//! <tt>static node_ptr get_previous(const_node_ptr n);</tt>
//!
//! <tt>static void set_previous(node_ptr n, node_ptr prev);</tt>
//!
//! <tt>static node_ptr get_next(const_node_ptr n);</tt>
//!
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
template<class NodeTraits>
class circular_list_algorithms
{
public:
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
//! == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node)
{
NodeTraits::set_next(this_node, this_node);
NodeTraits::set_previous(this_node, this_node);
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node)
{ return NodeTraits::get_next(this_node) == this_node; }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list
//! is empty, returns 1.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static std::size_t count(const_node_ptr this_node)
{
std::size_t result = 0;
const_node_ptr p = this_node;
do{
p = NodeTraits::get_next(p);
++result;
}while (p != this_node);
return result;
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static node_ptr unlink(node_ptr this_node)
{
node_ptr next(NodeTraits::get_next(this_node));
node_ptr prev(NodeTraits::get_previous(this_node));
NodeTraits::set_next(prev, next);
NodeTraits::set_previous(next, prev);
return next;
}
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//!
//! <b>Effects</b>: Unlinks the node [b, e) from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink(node_ptr b, node_ptr e)
{
if (b != e) {
node_ptr prev(NodeTraits::get_previous(b));
node_ptr next(NodeTraits::get_next(e));
NodeTraits::set_previous(next, prev);
NodeTraits::set_next(prev, next);
}
}
//! <b>Requires</b>: nxt_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node before nxt_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_before(node_ptr nxt_node, node_ptr this_node)
{
node_ptr prev(NodeTraits::get_previous(nxt_node));
NodeTraits::set_previous(this_node, prev);
NodeTraits::set_next(prev, this_node);
NodeTraits::set_previous(nxt_node, this_node);
NodeTraits::set_next(this_node, nxt_node);
}
//! <b>Requires</b>: prev_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node)
{
node_ptr next(NodeTraits::get_next(prev_node));
NodeTraits::set_previous(this_node, prev_node);
NodeTraits::set_next(this_node, next);
NodeTraits::set_previous(next, this_node);
NodeTraits::set_next(prev_node, this_node);
}
//! <b>Requires</b>: this_node and other_node must be nodes inserted
//! in circular lists or be empty circular lists.
//!
//! <b>Effects</b>: Swaps the position of the nodes: this_node is inserted in
//! other_nodes position in the second circular list and the other_node is inserted
//! in this_node's position in the first circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void swap_nodes(node_ptr this_node, node_ptr other_node)
{
if (other_node == this_node)
return;
bool empty1 = unique(this_node);
bool empty2 = unique(other_node);
node_ptr next_this(NodeTraits::get_next(this_node));
node_ptr prev_this(NodeTraits::get_previous(this_node));
node_ptr next_other(NodeTraits::get_next(other_node));
node_ptr prev_other(NodeTraits::get_previous(other_node));
//Do the swap
NodeTraits::set_next(this_node, next_other);
NodeTraits::set_next(other_node, next_this);
NodeTraits::set_previous(this_node, prev_other);
NodeTraits::set_previous(other_node, prev_this);
if (empty2){
init(this_node);
}
else{
NodeTraits::set_next(prev_other, this_node);
NodeTraits::set_previous(next_other, this_node);
}
if (empty1){
init(other_node);
}
else{
NodeTraits::set_next(prev_this, other_node);
NodeTraits::set_previous(next_this, other_node);
}
}
/*
//Watanabe version
private:
static void swap_prev(node_ptr this_node, node_ptr other_node)
{
node_ptr temp(NodeTraits::get_previous(this_node));
NodeTraits::set_previous(this_node, NodeTraits::get_previous(other_node));
NodeTraits::set_previous(other_node, temp);
}
static void swap_next(node_ptr this_node, node_ptr other_node)
{
node_ptr temp(NodeTraits::get_next(this_node));
NodeTraits::set_next(this_node, NodeTraits::get_next(other_node));
NodeTraits::set_next(other_node, temp);
}
public:
static void swap_nodes(node_ptr this_node, node_ptr other_node)
{
node_ptr next_this(NodeTraits::get_next(this_node));
node_ptr prev_this(NodeTraits::get_previous(this_node));
node_ptr next_other(NodeTraits::get_next(other_node));
node_ptr prev_other(NodeTraits::get_previous(other_node));
//these first two swaps must happen before the other two
swap_prev(next_this, next_other);
swap_next(prev_this, prev_other);
swap_next(this_node, other_node);
swap_prev(this_node, other_node);
}
*/
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//! and p must be a node of a different circular list or may not be an iterator in
// [b, e).
//!
//! <b>Effects</b>: Removes the nodes from [b, e) range from their circular list and inserts
//! them before p in p's circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer(node_ptr p, node_ptr b, node_ptr e)
{
if (b != e) {
node_ptr prev_p(NodeTraits::get_previous(p));
node_ptr prev_e(NodeTraits::get_previous(e));
node_ptr prev_b(NodeTraits::get_previous(b));
NodeTraits::set_next(prev_e, p);
NodeTraits::set_previous(p, prev_e);
NodeTraits::set_next(prev_b, e);
NodeTraits::set_previous(e, prev_b);
NodeTraits::set_next(prev_p, b);
NodeTraits::set_previous(b, prev_p);
}
}
//! <b>Requires</b>: i must a node of a circular list
//! and p must be a node of a different circular list.
//!
//! <b>Effects</b>: Removes the node i from its circular list and inserts
//! it before p in p's circular list.
//! If p == i or p == NodeTraits::get_next(i), this function is a null operation.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer(node_ptr p, node_ptr i)
{
node_ptr n(NodeTraits::get_next(i));
if(n != p && i != p){
node_ptr prev_p(NodeTraits::get_previous(p));
node_ptr prev_i(NodeTraits::get_previous(i));
NodeTraits::set_next(prev_p, i);
NodeTraits::set_previous(i, prev_p);
NodeTraits::set_next(i, p);
NodeTraits::set_previous(p, i);
NodeTraits::set_previous(n, prev_i);
NodeTraits::set_next(prev_i, n);
}
}
//! <b>Effects</b>: Reverses the order of elements in the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: This function is linear time.
static void reverse(node_ptr p)
{
node_ptr f(NodeTraits::get_next(p));
node_ptr i(NodeTraits::get_next(f)), e(p);
while(i != e) {
node_ptr n = i;
i = NodeTraits::get_next(i);
transfer(f, n, i);
f = n;
}
}
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP

View File

@ -0,0 +1,291 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/get_pointer.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
//! circular_slist_algorithms provides basic algorithms to manipulate nodes
//! forming a circular singly linked list. An empty circular list is formed by a node
//! whose pointer to the next node points to itself.
//!
//! circular_slist_algorithms is configured with a NodeTraits class, which capsulates the
//! information about the node to be manipulated. NodeTraits must support the
//! following interface:
//!
//! <b>Typedefs</b>:
//!
//! <tt>node</tt>: The type of the node that forms the circular list
//!
//! <tt>node_ptr</tt>: A pointer to a node
//!
//! <tt>const_node_ptr</tt>: A pointer to a const node
//!
//! <b>Static functions</b>:
//!
//! <tt>static node_ptr get_next(const_node_ptr n);</tt>
//!
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
template<class NodeTraits>
class circular_slist_algorithms
{
public:
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns the previous node of this_node in the circular list.
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr this_node)
{ return get_previous_node(this_node, this_node); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same circular list.
//!
//! <b>Effects</b>: Returns the previous node of this_node in the circular list starting.
//! the search from prev_init_node. The first node checked for equality
//! is NodeTraits::get_next(prev_init_node).
//!
//! <b>Complexity</b>: Linear to the number of elements between prev_init_node and this_node.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node)
{
node_ptr p = prev_init_node;
for( node_ptr p_next
; this_node != (p_next = NodeTraits::get_next(p))
; p = p_next){
//empty
}
return p;
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns the previous node of the previous node of this_node in the circular list.
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_previous_node(node_ptr this_node)
{ return get_previous_previous_node(this_node, this_node); }
//! <b>Requires</b>: this_node and prev_prev_init_node must be in the same circular list.
//!
//! <b>Effects</b>: Returns the previous node of the previous node of this_node in the
//! circular list starting. the search from prev_init_node. The first node checked
//! for equality is NodeTraits::get_next((NodeTraits::get_next(prev_prev_init_node)).
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_previous_node(node_ptr prev_prev_init_node, node_ptr this_node)
{
node_ptr p = prev_prev_init_node;
node_ptr p_next = NodeTraits::get_next(p);
node_ptr p_next_next = NodeTraits::get_next(p_next);
while (this_node != p_next_next){
p = p_next;
p_next = p_next_next;
p_next_next = NodeTraits::get_next(p_next);
}
return p;
}
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
//! == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node)
{ NodeTraits::set_next(this_node, this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node)
{ return NodeTraits::get_next(this_node) == this_node; }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list
//! is empty, returns 1.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static std::size_t count(const_node_ptr this_node)
{
std::size_t result = 0;
const_node_ptr p = this_node;
do{
p = NodeTraits::get_next(p);
++result;
} while (p != this_node);
return result;
}
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node)
{
node_ptr this_node(NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node));
NodeTraits::set_next(this_node, this_node);
}
//! <b>Requires</b>: nxt_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the previous node of nxt_node from the circular list.
//!
//! <b>Complexity</b>: Linear to the elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static void unlink_before(node_ptr nxt_node)
{
node_ptr prev_to_erase(get_previous_previous_node(nxt_node));
unlink_after(prev_to_erase);
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the node from the circular list.
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list
//!
//! <b>Throws</b>: Nothing.
static void unlink(node_ptr this_node)
{ unlink_after(get_previous_node(this_node)); }
//! <b>Requires</b>: prev_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node)
{
NodeTraits::set_next(this_node, NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, this_node);
}
//! <b>Requires</b>: nxt_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node before nxt_node in the circular list.
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static void link_before (node_ptr nxt_node, node_ptr this_node)
{ link_after(get_previous_node(nxt_node), this_node); }
//! <b>Requires</b>: this_node and other_node must be nodes inserted
//! in circular lists or be empty circular lists.
//!
//! <b>Effects</b>: Swaps the position of the nodes: this_node is inserted in
//! other_nodes position in the second circular list and the other_node is inserted
//! in this_node's position in the first circular list.
//!
//! <b>Complexity</b>: Linear to number of elements of both lists
//!
//! <b>Throws</b>: Nothing.
static void swap_nodes(node_ptr this_node, node_ptr other_node)
{
if (other_node == this_node)
return;
bool empty1 = unique(this_node);
bool empty2 = unique(other_node);
node_ptr prev_this (get_previous_node(this_node));
node_ptr prev_other(get_previous_node(other_node));
node_ptr this_next (NodeTraits::get_next(this_node));
node_ptr other_next(NodeTraits::get_next(other_node));
NodeTraits::set_next(this_node, other_next);
NodeTraits::set_next(other_node, this_next);
NodeTraits::set_next(empty1 ? other_node : prev_this, other_node);
NodeTraits::set_next(empty2 ? this_node : prev_other, this_node);
}
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//! and p must be a node of a different circular list.
//!
//! <b>Effects</b>: Removes the nodes from [b, e) range from their circular list and inserts
//! them after p in p's circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e)
{
if (p != b && p != e) {
node_ptr next_b = NodeTraits::get_next(b);
node_ptr next_e = NodeTraits::get_next(e);
node_ptr next_p = NodeTraits::get_next(p);
NodeTraits::set_next(b, next_e);
NodeTraits::set_next(e, next_p);
NodeTraits::set_next(p, next_b);
}
}
//! <b>Effects</b>: Reverses the order of elements in the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: This function is linear to the contained elements.
static void reverse(node_ptr p)
{
node_ptr i = NodeTraits::get_next(p), e(p);
for (;;) {
node_ptr nxt(NodeTraits::get_next(i));
if (nxt == e)
break;
transfer_after(e, i, nxt);
}
}
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP

View File

@ -0,0 +1,48 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/config.hpp>
#ifdef BOOST_MSVC
#pragma warning (push)
//
//'function' : resolved overload was found by argument-dependent lookup
//A function found by argument-dependent lookup (Koenig lookup) was eventually
//chosen by overload resolution.
//
//In Visual C++ .NET and earlier compilers, a different function would have
//been called. To pick the original function, use an explicitly qualified name.
//
//warning C4275: non dll-interface class 'x' used as base for
//dll-interface class 'Y'
#pragma warning (disable : 4275)
//warning C4251: 'x' : class 'y' needs to have dll-interface to
//be used by clients of class 'z'
#pragma warning (disable : 4251)
#pragma warning (disable : 4675)
#pragma warning (disable : 4996)
#pragma warning (disable : 4503)
#pragma warning (disable : 4284) // odd return type for operator->
#pragma warning (disable : 4244) // possible loss of data
#pragma warning (disable : 4521) ////Disable "multiple copy constructors specified"
#pragma warning (disable : 4522)
#pragma warning (disable : 4146)
#pragma warning (disable : 4267) //conversion from 'X' to 'Y', possible loss of data
#endif
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# pragma warn -8026 // shut up warning "cannot inline function because ..."
# pragma warn -8027 // shut up warning "cannot inline function because ..."
#endif

View File

@ -0,0 +1,22 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#if defined _MSC_VER
#pragma warning (pop)
#endif
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# pragma warn .8026
# pragma warn .8027
#endif

View File

@ -0,0 +1,71 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Joaquín M López Muñoz 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP
#define BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP
#include <boost/type_traits/is_empty.hpp>
namespace boost {
namespace intrusive {
namespace detail {
template<typename T, bool IsEmpty = false>
class ebo_holder_impl
{
public:
ebo_holder_impl(){}
ebo_holder_impl(const T& t):t(t){}
T& get(){return t;}
const T& get()const{return t;}
private:
T t;
};
template<typename T>
class ebo_holder_impl<T, true>
: private T
{
public:
ebo_holder_impl(){}
ebo_holder_impl(const T& t):T(t){}
T& get(){return *this;}
const T& get()const{return *this;}
};
template<typename T>
class ebo_holder
: public ebo_holder_impl<T,boost::is_empty<T>::value>
{
private:
typedef ebo_holder_impl<T,boost::is_empty<T>::value> super;
public:
ebo_holder(){}
ebo_holder(const T& t):super(t){}
ebo_holder& operator=(const ebo_holder& x)
{
this->get()=x.get();
return *this;
}
};
} //namespace detail {
} //namespace intrusive {
} //namespace boost {
#endif //#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP

View File

@ -0,0 +1,205 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gazta<74>ga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
#define BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/circular_list_algorithms.hpp>
#include <boost/get_pointer.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
namespace detail {
template<int Dummy = 0>
struct prime_list_holder
{
static const std::size_t prime_list[];
static const std::size_t prime_list_size;
};
template<int Dummy>
const std::size_t prime_list_holder<Dummy>::prime_list[] = {
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul };
template<int Dummy>
const std::size_t prime_list_holder<Dummy>::prime_list_size
= sizeof(prime_list)/sizeof(std::size_t);
template <class SlistImpl>
struct bucket_type_impl
: public SlistImpl
{
bucket_type_impl()
{}
bucket_type_impl(const bucket_type_impl &)
{}
bucket_type_impl &operator=(const bucket_type_impl&)
{ SlistImpl::clear(); }
static typename std::iterator_traits
<typename SlistImpl::const_iterator>::difference_type
get_bucket_num
( typename SlistImpl::const_iterator it
, const bucket_type_impl<SlistImpl> &first_bucket
, const bucket_type_impl<SlistImpl> &last_bucket)
{
typename SlistImpl::const_iterator
first(first_bucket.cend()), last(last_bucket.cend());
//The end node is embedded in the singly linked list:
//iterate until we reach it.
while(!(first.pointed_node() <= it.pointed_node() &&
it.pointed_node() <= last.pointed_node())){
++it;
}
//Now get the bucket_type_impl from the iterator
const bucket_type_impl &b = static_cast<const bucket_type_impl&>
(SlistImpl::container_from_end_iterator(it));
//Now just calculate the index b has in the bucket array
return &b - &first_bucket;
}
static SlistImpl &bucket_to_slist(bucket_type_impl<SlistImpl> &b)
{ return static_cast<SlistImpl &>(b); }
static const SlistImpl &bucket_to_slist(const bucket_type_impl<SlistImpl> &b)
{ return static_cast<const SlistImpl &>(b); }
};
template<class SlistImpl>
struct bucket_info_impl
{
typedef typename boost::pointer_to_other
< typename SlistImpl::pointer
, bucket_type_impl<SlistImpl> >::type bucket_ptr;
typedef typename SlistImpl::size_type size_type;
bucket_ptr buckets_;
size_type buckets_len_;
};
template<class Value, class SlistImpl>
class hashtable_iterator
: public boost::iterator_facade
< hashtable_iterator<Value, SlistImpl>
, Value
, boost::forward_traversal_tag
, Value&
, typename std::iterator_traits<typename SlistImpl::iterator>::difference_type
>
{
typedef typename SlistImpl::iterator local_iterator;
typedef typename SlistImpl::const_iterator const_local_iterator;
typedef typename SlistImpl::value_traits::node_ptr node_ptr;
typedef typename SlistImpl::value_traits::const_node_ptr const_node_ptr;
typedef bucket_type_impl<SlistImpl> bucket_type;
typedef typename boost::pointer_to_other
< typename SlistImpl::pointer, bucket_type>::type bucket_ptr;
typedef typename boost::pointer_to_other
< typename SlistImpl::pointer, const bucket_type>::type const_bucket_ptr;
typedef detail::bucket_info_impl<SlistImpl> bucket_info_t;
typedef typename boost::pointer_to_other
<bucket_ptr, bucket_info_t>::type bucket_info_ptr;
typedef typename boost::pointer_to_other
<bucket_ptr, const bucket_info_t>::type const_bucket_info_ptr;
typedef typename SlistImpl::size_type size_type;
struct enabler {};
public:
hashtable_iterator ()
{}
explicit hashtable_iterator(local_iterator ptr, const_bucket_info_ptr bucket_info)
: local_it_ (ptr), bucket_info_ (bucket_info)
{}
template <class OtherValue>
hashtable_iterator(hashtable_iterator<OtherValue, SlistImpl> const& other
,typename boost::enable_if<
boost::is_convertible<OtherValue*,Value*>
, enabler
>::type = enabler()
)
: local_it_(other.local_it_), bucket_info_(other.bucket_info_)
{}
const local_iterator &local() const
{ return local_it_; }
const_node_ptr pointed_node() const
{ return local_it_.pointed_node(); }
const const_bucket_info_ptr &bucket_info() const
{ return bucket_info_; }
private:
friend class boost::iterator_core_access;
template <class, class> friend class hashtable_iterator;
template <class OtherValue>
bool equal(hashtable_iterator<OtherValue, SlistImpl> const& other) const
{ return other.local() == local_it_; }
void increment()
{
using boost::get_pointer;
size_type buckets_len = bucket_info_->buckets_len_;
const_bucket_ptr buckets = bucket_info_->buckets_;
const_local_iterator first = bucket_type::bucket_to_slist(buckets[0]).cend();
const_local_iterator last = bucket_type::bucket_to_slist(buckets[buckets_len]).cend();
++local_it_;
if(first.pointed_node() <= local_it_.pointed_node() &&
local_it_.pointed_node() <= last.pointed_node()){
size_type n_bucket = (size_type)
bucket_type::get_bucket_num(local_it_, buckets[0], buckets[buckets_len]);
do{
if (++n_bucket == buckets_len){
local_it_ = bucket_info_->buckets_->end();
break;
}
local_it_ = bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).begin();
}
while (local_it_ == bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).end());
}
}
Value& dereference() const
{ return *local_it_; }
local_iterator local_it_;
const_bucket_info_ptr bucket_info_;
};
} //namespace detail {
} //namespace intrusive {
} //namespace boost {
#endif

View File

@ -0,0 +1,132 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_LIST_NODE_HPP
#define BOOST_INTRUSIVE_LIST_NODE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/circular_list_algorithms.hpp>
#include <boost/get_pointer.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
namespace detail {
// list_node_traits can be used with circular_list_algorithms and supplies
// a list_node holding the pointers needed for a double-linked list
// it is used by list_derived_node and list_member_node
template<class VoidPointer>
struct list_node_traits
{
struct node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
struct node
{
node_ptr prev_, next_;
};
static node_ptr get_previous(const_node_ptr n)
{ return n->prev_; }
static void set_previous(node_ptr n, node_ptr prev)
{ n->prev_ = prev; }
static node_ptr get_next(const_node_ptr n)
{ return n->next_; }
static void set_next(node_ptr n, node_ptr next)
{ n->next_ = next; }
};
// list_iterator provides some basic functions for a
// node oriented forward iterator:
template<class T, class ValueTraits>
class list_iterator
: public boost::iterator_facade
< list_iterator<T, ValueTraits>
, T
, boost::bidirectional_traversal_tag
, T&
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
>
{
typedef typename ValueTraits::node_traits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
struct enabler{};
public:
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
list_iterator ()
: node_ (0)
{}
explicit list_iterator(node_ptr node)
: node_ (node)
{}
template <class OtherValue>
list_iterator(list_iterator<OtherValue, ValueTraits> const& other
,typename boost::enable_if<
boost::is_convertible<OtherValue*,T*>
, enabler
>::type = enabler()
)
: node_(other.pointed_node())
{}
const node_ptr &pointed_node() const
{ return node_; }
private:
friend class boost::iterator_core_access;
template <class, class> friend class list_iterator;
template <class OtherValue>
bool equal(list_iterator<OtherValue, ValueTraits> const& other) const
{ return other.pointed_node() == node_; }
void increment()
{ node_ = node_traits::get_next(node_); }
void decrement()
{ node_ = node_traits::get_previous(node_); }
T& dereference() const
{ return *ValueTraits::to_value_ptr(node_); }
node_ptr node_;
};
} //namespace detail
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_LIST_NODE_HPP

View File

@ -0,0 +1,46 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP
#define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP
namespace boost {
namespace intrusive {
namespace detail {
template<class Parent, class Member>
std::size_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member)
{
//This works with gcc and msvc
return *(const std::size_t*)(const void*)&ptr_to_member;
//Other compilers might need other transformation, depending how a
//pointer to data member is implemented.
}
template<class Parent, class Member>
Parent *parent_from_member(Member *member, const Member Parent::* ptr_to_member)
{
return (Parent*)((char*)member -
offset_from_pointer_to_member(ptr_to_member));
}
template<class Parent, class Member>
const Parent *parent_from_member(const Member *member, const Member Parent::* ptr_to_member)
{
return (const Parent*)((const char*)member -
offset_from_pointer_to_member(ptr_to_member));
}
} //namespace detail {
} //namespace intrusive {
} //namespace boost {
#endif //#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP

View File

@ -0,0 +1,65 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_POINTER_TO_OTHER_HPP
#define BOOST_INTRUSIVE_POINTER_TO_OTHER_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/version.hpp>
#if (BOOST_VERSION < 103400)
#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
#define BOOST_POINTER_TO_OTHER_HPP_INCLUDED
namespace boost {
template<class T, class U>
struct pointer_to_other;
template<class T, class U, template <class> class Sp>
struct pointer_to_other< Sp<T>, U >
{
typedef Sp<U> type;
};
template<class T, class T2, class U,
template <class, class> class Sp>
struct pointer_to_other< Sp<T, T2>, U >
{
typedef Sp<U, T2> type;
};
template<class T, class T2, class T3, class U,
template <class, class, class> class Sp>
struct pointer_to_other< Sp<T, T2, T3>, U >
{
typedef Sp<U, T2, T3> type;
};
template<class T, class U>
struct pointer_to_other< T*, U >
{
typedef U* type;
};
} // namespace boost
#endif
#else
#include <boost/pointer_to_other.hpp>
#endif //#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
#include <boost/intrusive/detail/config_end.hpp>
#endif //#ifndef BOOST_INTRUSIVE_POINTER_TO_OTHER_HPP

View File

@ -0,0 +1,54 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_POINTER_TYPE_HPP
#define BOOST_INTRUSIVE_POINTER_TYPE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
namespace boost {
namespace intrusive {
namespace detail {
struct two {char _[2];};
namespace pointer_type_imp
{
template <class U> static two test(...);
template <class U> static char test(typename U::pointer* = 0);
} //namespace pointer_type_imp
template <class T>
struct has_pointer_type
{
static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
};
template <class T, class A, bool = has_pointer_type<A>::value>
struct pointer_type
{
typedef typename A::pointer type;
};
template <class T, class A>
struct pointer_type<T, A, false>
{
typedef T* type;
};
} //namespace detail
} //namespace intrusive
} // namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //#ifndef BOOST_INTRUSIVE_POINTER_TYPE_HPP

View File

@ -0,0 +1,257 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_RBTREE_NODE_HPP
#define BOOST_INTRUSIVE_RBTREE_NODE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/rbtree_algorithms.hpp>
#include <boost/get_pointer.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <cstddef>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/intrusive/pointer_plus_bit.hpp>
namespace boost {
namespace intrusive {
namespace detail {
/////////////////////////////////////////////////////////////////////////////
// //
// Generic node_traits for any pointer type //
// //
/////////////////////////////////////////////////////////////////////////////
//This is the compact representation: 3 pointers
template<class VoidPointer>
struct compact_rbtree_node
{
typedef typename pointer_to_other
<VoidPointer
,compact_rbtree_node<VoidPointer> >::type node_ptr;
enum color { red_t, black_t };
node_ptr parent_, left_, right_;
};
//This is the normal representation: 3 pointers + enum
template<class VoidPointer>
struct rbtree_node
{
typedef typename pointer_to_other
<VoidPointer
,rbtree_node<VoidPointer> >::type node_ptr;
enum color { red_t, black_t };
node_ptr parent_, left_, right_;
color color_;
};
//This is the default node traits implementation
//using a node with 3 generic pointers plus an enum
template<class VoidPointer>
struct default_rbtree_node_traits_impl
{
typedef rbtree_node<VoidPointer> node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef typename node::color color;
static node_ptr get_parent(const_node_ptr n)
{ return n->parent_; }
static void set_parent(node_ptr n, node_ptr p)
{ n->parent_ = p; }
static node_ptr get_left(const_node_ptr n)
{ return n->left_; }
static void set_left(node_ptr n, node_ptr l)
{ n->left_ = l; }
static node_ptr get_right(const_node_ptr n)
{ return n->right_; }
static void set_right(node_ptr n, node_ptr r)
{ n->right_ = r; }
static color get_color(const_node_ptr n)
{ return n->color_; }
static void set_color(node_ptr n, color c)
{ n->color_ = c; }
static color black()
{ return node::black_t; }
static color red()
{ return node::red_t; }
};
//This is the compact node traits implementation
//using a node with 3 generic pointers
template<class VoidPointer>
struct compact_rbtree_node_traits_impl
{
typedef compact_rbtree_node<VoidPointer> node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef pointer_plus_bit<node_ptr> ptr_bit;
typedef typename node::color color;
static node_ptr get_parent(const_node_ptr n)
{ return ptr_bit::get_pointer(n->parent_); }
static void set_parent(node_ptr n, node_ptr p)
{ ptr_bit::set_pointer(n->parent_, p); }
static node_ptr get_left(const_node_ptr n)
{ return n->left_; }
static void set_left(node_ptr n, node_ptr l)
{ n->left_ = l; }
static node_ptr get_right(const_node_ptr n)
{ return n->right_; }
static void set_right(node_ptr n, node_ptr r)
{ n->right_ = r; }
static color get_color(const_node_ptr n)
{ return (color)ptr_bit::get_bit(n->parent_); }
static void set_color(node_ptr n, color c)
{ ptr_bit::set_bit(n->parent_, c != 0); }
static color black()
{ return node::black_t; }
static color red()
{ return node::red_t; }
};
//Dispatches the implementation based on the boolean
template<class VoidPointer, bool compact>
struct rbtree_node_traits_dispatch
: public default_rbtree_node_traits_impl<VoidPointer>
{};
template<class VoidPointer>
struct rbtree_node_traits_dispatch<VoidPointer, true>
: public compact_rbtree_node_traits_impl<VoidPointer>
{};
//Inherit from the dispatcher depending on the embedding capabilities
template<class VoidPointer>
struct rbtree_node_traits
: public rbtree_node_traits_dispatch
<VoidPointer
,has_pointer_plus_bit
< typename pointer_to_other
<VoidPointer
, compact_rbtree_node<VoidPointer>
>::type
>::value
>
{};
/////////////////////////////////////////////////////////////////////////////
// //
// Implementation of the rbtree iterator //
// //
/////////////////////////////////////////////////////////////////////////////
template<class T, class ValueTraits>
class rbtree_iterator
: public boost::iterator_facade
< rbtree_iterator<T, ValueTraits>
, T
, boost::bidirectional_traversal_tag
, T&
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
>
{
typedef typename ValueTraits::node_traits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef rbtree_algorithms<node_traits> node_algorithms;
struct enabler{};
public:
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
rbtree_iterator ()
: node_ (0)
{}
explicit rbtree_iterator(node_ptr node)
: node_ (node)
{}
template <class OtherValue>
rbtree_iterator(rbtree_iterator<OtherValue, ValueTraits> const& other
,typename boost::enable_if<
boost::is_convertible<OtherValue*,T*>
, enabler
>::type = enabler()
)
: node_(other.pointed_node())
{}
const node_ptr &pointed_node() const
{ return node_; }
private:
friend class boost::iterator_core_access;
template <class, class> friend class rbtree_iterator;
template <class OtherValue>
bool equal(rbtree_iterator<OtherValue, ValueTraits> const& other) const
{ return other.pointed_node() == node_; }
void increment()
{ node_ = node_algorithms::next_node(node_); }
void decrement()
{ node_ = node_algorithms::prev_node(node_); }
T& dereference() const
{ return *ValueTraits::to_value_ptr(node_); }
node_ptr node_;
};
} //namespace detail
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_RBTREE_NODE_HPP

View File

@ -0,0 +1,125 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_SLIST_NODE_HPP
#define BOOST_INTRUSIVE_SLIST_NODE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/circular_slist_algorithms.hpp>
#include <boost/get_pointer.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
namespace detail {
// slist_node_traits can be used with circular_slist_algorithms and supplies
// a slist_node holding the pointers needed for a singly-linked list
// it is used by slist_base_hook and slist_member_hook
template<class VoidPointer>
struct slist_node_traits
{
struct node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
struct node
{
node_ptr next_;
};
static node_ptr get_next(const_node_ptr n)
{ return n->next_; }
static void set_next(node_ptr n, node_ptr next)
{ n->next_ = next; }
};
// slist_iterator provides some basic functions for a
// node oriented forward iterator:
template<class T, class ValueTraits>
class slist_iterator
: public boost::iterator_facade
< slist_iterator<T, ValueTraits>
, T
, boost::forward_traversal_tag
, T&
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
>
{
typedef typename ValueTraits::node_traits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
struct enabler{};
public:
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
slist_iterator ()
: node_ (0)
{}
explicit slist_iterator(node_ptr node)
: node_ (node)
{}
template <class OtherValue>
slist_iterator(slist_iterator<OtherValue, ValueTraits> const& other
,typename boost::enable_if<
boost::is_convertible<OtherValue*,T*>
, enabler
>::type = enabler()
)
: node_(other.pointed_node())
{}
const node_ptr &pointed_node() const
{ return node_; }
private:
friend class boost::iterator_core_access;
template <class, class> friend class slist_iterator;
template <class OtherValue>
bool equal(slist_iterator<OtherValue, ValueTraits> const& other) const
{ return other.pointed_node() == node_; }
void increment()
{ node_ = node_traits::get_next(node_); }
T& dereference() const
{ return *ValueTraits::to_value_ptr(node_); }
node_ptr node_;
};
} //namespace detail
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_SLIST_NODE_HPP

View File

@ -0,0 +1,293 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP
#define BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/detail/parent_from_member.hpp>
#include <boost/intrusive/detail/ebo_holder.hpp>
#include <boost/intrusive/linking_policy.hpp>
#include <boost/get_pointer.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
namespace detail {
//This functor compares a stored value
//and the one passed as an argument
template<class ConstReference>
class equal_to_value
{
ConstReference t_;
public:
equal_to_value(ConstReference t)
: t_(t)
{}
bool operator()(ConstReference t)const
{ return t_ == t; }
};
class null_destroyer
{
public:
template <class Pointer>
void operator()(Pointer)
{}
};
template<bool ConstantSize, class SizeType>
struct size_holder
{
enum { constant_time_size = ConstantSize };
typedef SizeType size_type;
SizeType get_size() const
{ return size_; }
void set_size(SizeType size)
{ size_ = size; }
void decrement()
{ --size_; }
void increment()
{ ++size_; }
SizeType size_;
};
template<class SizeType>
struct size_holder<false, SizeType>
{
enum { constant_time_size = false };
typedef SizeType size_type;
size_type get_size() const
{ return 0; }
void set_size(size_type)
{}
void decrement()
{}
void increment()
{}
};
template<class T, class DerivationHookType, typename Tag>
struct derivation_value_traits
{
public:
typedef typename DerivationHookType::node_traits node_traits;
typedef T value_type;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef typename boost::pointer_to_other<node_ptr, T>::type pointer;
typedef typename boost::pointer_to_other<node_ptr, const T>::type const_pointer;
typedef typename std::iterator_traits<pointer>::reference reference;
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
enum { linking_policy = DerivationHookType::linking_policy };
static node_ptr to_node_ptr(reference value)
{ return static_cast<DerivationHookType &>(value).to_node_ptr(); }
static const_node_ptr to_node_ptr(const_reference value)
{ return static_cast<const DerivationHookType &>(value).to_node_ptr(); }
static pointer to_value_ptr(node_ptr n)
{
using boost::get_pointer;
return static_cast<T*>(get_pointer(DerivationHookType::to_hook_ptr(n)));
}
static const_pointer to_value_ptr(const_node_ptr n)
{
using boost::get_pointer;
return static_cast<const T*>(get_pointer(DerivationHookType::to_hook_ptr(n)));
}
};
template<class T, class MemberHookType, MemberHookType T::* P>
struct member_value_traits
{
public:
typedef typename MemberHookType::node_traits node_traits;
typedef T value_type;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef typename boost::pointer_to_other<node_ptr, T>::type pointer;
typedef typename boost::pointer_to_other<node_ptr, const T>::type const_pointer;
typedef typename std::iterator_traits<pointer>::reference reference;
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
enum { linking_policy = MemberHookType::linking_policy };
public:
static node_ptr to_node_ptr(reference value)
{
MemberHookType* result = &(value.*P);
return result->to_node_ptr();
}
static const_node_ptr to_node_ptr(const_reference value)
{
const MemberHookType* result = &(value.*P);
return result->to_node_ptr();
}
//Now let's be nasty. A pointer to member is usually implemented
//as an offset from the start of the class.
//get the offset in bytes and go
//backwards from n to the value subtracting
//the needed bytes.
static pointer to_value_ptr(node_ptr n)
{
using boost::get_pointer;
return pointer(parent_from_member((MemberHookType*)get_pointer(n), P));
}
static const_pointer to_value_ptr(const_node_ptr n)
{
using boost::get_pointer;
const_pointer(parent_from_member<value_type>((const MemberHookType*)get_pointer(n), P));
}
private:
//This function converts a pointer to data member into an offset.
//This function is not standard and it's compiler-dependent.
static std::size_t value_to_node_offset()
{
const MemberHookType T::* const p = P;
return *(const std::size_t*)(const void *)(&p);
// using boost::get_pointer;
// const typename node_traits::node *np =
// get_pointer((((const value_type *)get_pointer(n))->*P).to_node_ptr());
// return ((const char*)np - (const char*)(const value_type *)get_pointer(n));
}
};
template<class KeyValueCompare, class ValueTraits>
struct key_node_ptr_compare
: private detail::ebo_holder<KeyValueCompare>
{
typedef typename ValueTraits::node_ptr node_ptr;
typedef detail::ebo_holder<KeyValueCompare> base_t;
key_node_ptr_compare(KeyValueCompare kcomp)
: base_t(kcomp)
{}
template<class KeyType>
bool operator()(node_ptr node, const KeyType &key) const
{ return base_t::get()(*ValueTraits::to_value_ptr(node), key); }
template<class KeyType>
bool operator()(const KeyType &key, node_ptr node) const
{ return base_t::get()(key, *ValueTraits::to_value_ptr(node)); }
bool operator()(node_ptr node1, node_ptr node2) const
{
return base_t::get()
(*ValueTraits::to_value_ptr(node1), *ValueTraits::to_value_ptr(node2));
}
};
template<class F, class ValueTraits>
struct value_to_node_cloner
: private detail::ebo_holder<F>
{
typedef typename ValueTraits::node_ptr node_ptr;
typedef detail::ebo_holder<F> base_t;
value_to_node_cloner(F f)
: base_t(f)
{}
node_ptr operator()(node_ptr p)
{ return ValueTraits::to_node_ptr(*base_t::get()(*ValueTraits::to_value_ptr(p))); }
};
template<class F, class ValueTraits>
struct value_to_node_destroyer
: private detail::ebo_holder<F>
{
typedef typename ValueTraits::node_ptr node_ptr;
typedef detail::ebo_holder<F> base_t;
value_to_node_destroyer(F f)
: base_t(f)
{}
void operator()(node_ptr p)
{ base_t::get()(ValueTraits::to_value_ptr(p)); }
};
template <linking_policy Policy>
struct dispatcher
{};
template<class Container>
void destructor_impl(Container &cont, dispatcher<safe_link>)
{ BOOST_ASSERT(!cont.is_linked()); }
template<class Container>
void destructor_impl(Container &cont, dispatcher<auto_unlink>)
{ cont.unlink(); }
template<class Container>
void destructor_impl(Container &cont, dispatcher<normal_link>)
{}
template<class Node, class MaybeClass>
struct node_plus_pred
: public ebo_holder<MaybeClass>
, public Node
{
node_plus_pred()
{}
node_plus_pred(const Node &x, const MaybeClass &y)
: Node(x), ebo_holder<MaybeClass>(y) {}
node_plus_pred(const MaybeClass &y)
: ebo_holder<MaybeClass>(y) {}
Node &first()
{ return *this; }
const Node &first() const
{ return *this; }
MaybeClass &second()
{ return ebo_holder<MaybeClass>::get(); }
const MaybeClass &second() const
{ return ebo_holder<MaybeClass>::get(); }
static node_plus_pred *this_from_node(Node *n)
{ return static_cast<node_plus_pred*>(n); }
static node_plus_pred *this_from_node(const Node *n)
{ return static_cast<const node_plus_pred*>(n); }
};
} //namespace detail
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP

View File

@ -0,0 +1,852 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_HASHTABLE_HPP
#define BOOST_INTRUSIVE_HASHTABLE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
//std C++
#include <functional>
#include <iterator>
#include <utility>
#include <algorithm>
//boost
#include <boost/utility.hpp>
#include <boost/compressed_pair.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/functional/hash.hpp>
//General intrusive utilities
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/detail/hashtable_node.hpp>
#include <boost/intrusive/linking_policy.hpp>
//Implementation utilities
#include <boost/intrusive/unordered_set_hook.hpp>
#include <boost/intrusive/slist.hpp>
#include <cstddef>
#include <iterator>
namespace boost {
namespace intrusive {
//! The class template hashtable is an intrusive hash table container, that
//! is used to construct intrusive unordered_set and unordered_multiset containers. The
//! no-throw guarantee holds only, if the Equal object and Hasher don't throw.
template< class ValueTraits
, class Hash //= boost::hash<typename ValueTraits::value_type>
, class Equal //= std::equal_to<typename ValueTraits::value_type>
, bool ConstantTimeSize //= true
, class SizeType //= std::size_t
>
class hashtable
: private detail::size_holder<ConstantTimeSize, SizeType>
{
/// @cond
private:
typedef slist<ValueTraits, false, SizeType> slist_impl;
typedef hashtable<ValueTraits, Hash, Equal
,ConstantTimeSize, SizeType> this_type;
typedef typename ValueTraits::node_traits node_traits;
typedef detail::size_holder<ConstantTimeSize, SizeType> size_traits;
//noncopyable
hashtable (const hashtable&);
hashtable operator =(const hashtable&);
/// @endcond
public:
typedef ValueTraits value_traits;
typedef typename ValueTraits::value_type value_type;
typedef typename ValueTraits::pointer pointer;
typedef typename ValueTraits::const_pointer const_pointer;
typedef typename std::iterator_traits<pointer>::reference reference;
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
typedef typename std::iterator_traits<pointer>::difference_type difference_type;
typedef SizeType size_type;
typedef value_type key_type;
typedef Hash hasher;
typedef Equal key_equal;
typedef detail::bucket_type_impl<slist_impl> bucket_type;
typedef typename boost::pointer_to_other
<pointer, bucket_type>::type bucket_ptr;
typedef typename slist_impl::iterator local_iterator;
typedef typename slist_impl::const_iterator const_local_iterator;
typedef detail::hashtable_iterator<value_type, slist_impl> iterator;
typedef detail::hashtable_iterator<value_type, slist_impl> const_iterator;
/// @cond
private:
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<pointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<node_ptr, const node>::type const_node_ptr;
enum { safemode_or_autounlink =
(int)ValueTraits::linking_policy == (int)auto_unlink ||
(int)ValueTraits::linking_policy == (int)safe_link };
//Constant-time size is incompatible with auto-unlink hooks!
BOOST_STATIC_ASSERT(!(ConstantTimeSize && ((int)ValueTraits::linking_policy == (int)auto_unlink)));
typedef detail::bucket_info_impl<slist_impl> bucket_info_t;
typedef typename boost::pointer_to_other
<pointer, bucket_info_t>::type bucket_info_ptr;
typedef typename boost::pointer_to_other
<pointer, const bucket_info_t>::type const_bucket_info_ptr;
//User scattered boost::compressed pair to get EBO all compilers
boost::compressed_pair
<boost::compressed_pair<bucket_info_t, Hash>
,Equal> members_;
const Equal &priv_equal() const
{ return members_.second(); }
Equal &priv_equal()
{ return members_.second(); }
const_bucket_info_ptr priv_bucket_info() const
{ return &members_.first().first(); }
bucket_info_ptr priv_bucket_info()
{ return &members_.first().first(); }
const Hash &priv_hasher() const
{ return members_.first().second(); }
Hash &priv_hasher()
{ return members_.first().second(); }
const bucket_ptr &priv_buckets() const
{ return members_.first().first().buckets_; }
bucket_ptr &priv_buckets()
{ return members_.first().first().buckets_; }
const size_type &priv_buckets_len() const
{ return members_.first().first().buckets_len_; }
size_type &priv_buckets_len()
{ return members_.first().first().buckets_len_; }
static node_ptr uncast(const_node_ptr ptr)
{
using boost::get_pointer;
return node_ptr(const_cast<node*>(get_pointer(ptr)));
}
static bucket_info_ptr uncast(const_bucket_info_ptr ptr)
{
using boost::get_pointer;
return bucket_info_ptr(const_cast<bucket_info_t*>(get_pointer(ptr)));
}
static slist_impl &bucket_to_slist(bucket_type &b)
{ return static_cast<slist_impl &>(b); }
static const slist_impl &bucket_to_slist(const bucket_type &b)
{ return static_cast<const slist_impl &>(b); }
struct insert_commit_data_impl
{
size_type hash;
};
/// @endcond
public:
typedef insert_commit_data_impl insert_commit_data;
hashtable( bucket_ptr buckets
, size_type buckets_len
, const Hash & hasher = Hash()
, const Equal &equal = Equal())
: members_(boost::compressed_pair<bucket_info_t, Hash>(hasher), equal)
{
BOOST_ASSERT(buckets_len != 0);
priv_buckets() = buckets;
priv_buckets_len() = buckets_len;
priv_clear_buckets();
size_traits::set_size(size_type(0));
}
~hashtable()
{ this->clear(); }
iterator begin()
{
size_type bucket_num;
local_iterator local_it = priv_begin(bucket_num);
return iterator( local_it, this->priv_bucket_info());
}
const_iterator begin() const
{ return cbegin(); }
const_iterator cbegin() const
{
size_type bucket_num;
local_iterator local_it = priv_begin(bucket_num);
return const_iterator( local_it, this->priv_bucket_info());
}
iterator end()
{
using boost::get_pointer;
bucket_info_t *info = get_pointer(this->priv_bucket_info());
return iterator(invalid_local_it(*info), 0);
}
const_iterator end() const
{ return cend(); }
const_iterator cend() const
{
using boost::get_pointer;
const bucket_info_t *info = get_pointer(this->priv_bucket_info());
return const_iterator(invalid_local_it(*info), 0);
}
hasher hash_function() const
{ return this->priv_hasher(); }
key_equal key_eq() const
{ return this->priv_equal(); }
bool empty() const
{
if(ConstantTimeSize){
return !size();
}
else{
using boost::get_pointer;
size_type buckets_len = this->priv_buckets_len();
const bucket_type *b = get_pointer(this->priv_buckets());
for (size_type n = 0; n < buckets_len; ++n, ++b){
if(!b->empty()){
return false;
}
}
return true;
}
}
size_type size() const
{
if(ConstantTimeSize)
return size_traits::get_size();
else{
size_type len = 0;
using boost::get_pointer;
size_type buckets_len = this->priv_buckets_len();
const bucket_type *b = get_pointer(this->priv_buckets());
for (size_type n = 0; n < buckets_len; ++n, ++b){
len += b->size();
}
return len;
}
}
void swap(hashtable& other)
{
using std::swap;
//These can throw
swap(this->priv_equal(), other.priv_equal());
swap(this->priv_hasher(), other.priv_hasher());
//These can't throw
swap(this->priv_buckets(), other.priv_buckets());
swap(this->priv_buckets_len(), other.priv_buckets_len());
if(ConstantTimeSize){
size_type backup = size_traits::get_size();
size_traits::set_size(other.get_size());
other.set_size(backup);
}
}
template <class Cloner, class Destroyer>
void clone_from(const hashtable &src, Cloner cloner, Destroyer destroyer)
{
this->clear_and_destroy(destroyer);
if(!ConstantTimeSize || !src.empty()){
const size_type src_bucket_count = src.bucket_count();
const size_type dst_bucket_count = this->bucket_count();
//If src bucket count is bigger or equal, structural copy is possible
if(src_bucket_count >= dst_bucket_count){
//First clone the first ones
const bucket_ptr src_buckets = src.priv_buckets();
const bucket_ptr dst_buckets = this->priv_buckets();
size_type constructed;
try{
for( constructed = 0
; constructed < dst_bucket_count
; ++constructed){
dst_buckets[constructed].clone_from(src_buckets[constructed], cloner, destroyer);
}
if(src_bucket_count != dst_bucket_count){
//Now insert the remaining ones using the modulo trick
for(//"constructed" comes from the previous loop
; constructed < src_bucket_count
; ++constructed){
bucket_type &dst_b = dst_buckets[constructed % dst_bucket_count];
bucket_type &src_b = src_buckets[constructed];
for( local_iterator b(src_b.begin()), e(src_b.end())
; b != e
; ++b){
dst_b.push_front(*cloner(*b));
}
}
}
}
catch(...){
while(constructed--){
dst_buckets[constructed].clear_and_destroy(destroyer);
}
throw;
}
size_traits::set_size(src.get_size());
}
else{
//Unlike previous cloning algorithm, this can throw
//if cloner, the hasher or comparison functor throw
const_iterator b(src.begin()), e(src.end());
try{
for(; b != e; ++b){
this->insert_equal(*cloner(*b));
}
}
catch(...){
this->clear_and_destroy(destroyer);
throw;
}
}
}
}
iterator insert_equal(reference value)
{
size_type bucket_num, hash;
local_iterator it = priv_find(value, this->priv_hasher(), this->priv_equal(), bucket_num, hash);
bucket_type &b = this->priv_buckets()[bucket_num];
if(it == invalid_local_it(*this->priv_bucket_info())){
it = b.before_begin();
}
size_traits::increment();
return iterator(b.insert_after(it, value), this->priv_bucket_info());
}
template<class Iterator>
void insert_equal(Iterator b, Iterator e)
{
for (; b != e; ++b)
this->insert_equal(*b);
}
std::pair<iterator, bool> insert_unique(reference value)
{
insert_commit_data commit_data;
std::pair<iterator, bool> ret = insert_unique_check(value, commit_data);
if(!ret.second)
return ret;
return std::pair<iterator, bool> (insert_unique_commit(value, commit_data), true);
}
template<class Iterator>
void insert_unique(Iterator b, Iterator e)
{
for (; b != e; ++b)
this->insert_unique(*b);
}
std::pair<iterator, bool> insert_unique_check
(const_reference value, insert_commit_data &commit_data)
{ return insert_unique_check(value, this->priv_hasher(), this->priv_equal(), commit_data); }
template<class KeyType, class KeyHasher, class KeyValueEqual>
std::pair<iterator, bool> insert_unique_check
( const KeyType &key
, KeyHasher hasher
, KeyValueEqual key_value_eq
, insert_commit_data &commit_data)
{
size_type bucket_num;
local_iterator prev_pos =
priv_find(key, hasher, key_value_eq, bucket_num, commit_data.hash);
bool success = prev_pos == invalid_local_it(*this->priv_bucket_info());
if(success){
prev_pos = this->priv_buckets()[bucket_num].before_begin();
}
return std::pair<iterator, bool>
(iterator(prev_pos, this->priv_bucket_info())
,success);
}
iterator insert_unique_commit(reference value, const insert_commit_data &commit_data)
{
size_type bucket_num = commit_data.hash % this->priv_buckets_len();
bucket_type &b = this->priv_buckets()[bucket_num];
size_traits::increment();
return iterator( b.insert_after(b.before_begin(), value)
, this->priv_bucket_info());
}
void erase(const_iterator i)
{ erase_and_destroy(i, detail::null_destroyer()); }
void erase(const_iterator b, const_iterator e)
{ erase_and_destroy(b, e, detail::null_destroyer()); }
size_type erase(const_reference value)
{ return this->erase(value, this->priv_hasher(), this->priv_equal()); }
template<class KeyType, class KeyHasher, class KeyValueEqual>
size_type erase(const KeyType& key, KeyHasher hasher, KeyValueEqual equal)
{ return erase_and_destroy(key, hasher, equal, detail::null_destroyer()); }
template<class Destroyer>
void erase_and_destroy(const_iterator i, Destroyer destroyer)
{
local_iterator to_erase(i.local());
bucket_ptr f(priv_buckets()), l(f + priv_buckets_len());
bucket_type &b = this->priv_buckets()[bucket_type::get_bucket_num(to_erase, *f, *l)];
b.erase_after_and_destroy(b.previous(to_erase), destroyer);
size_traits::decrement();
}
template<class Destroyer>
void erase_and_destroy(const_iterator b, const_iterator e, Destroyer destroyer)
{
if(b == e) return;
//Get the bucket number and local iterator for both iterators
bucket_ptr f(priv_buckets()), l(f + priv_buckets_len());
size_type first_bucket_num = bucket_type::get_bucket_num(b.local(), *f, *l);
local_iterator before_first_local_it
= priv_buckets()[first_bucket_num].previous(b.local());
size_type last_bucket_num;
local_iterator last_local_it;
//For the end iterator, we will assign the end iterator
//of the last bucket
if(e == end()){
last_bucket_num = this->bucket_count() - 1;
last_local_it = priv_buckets()[last_bucket_num].end();
}
else{
last_local_it = e.local();
last_bucket_num = bucket_type::get_bucket_num(last_local_it, *f, *l);
}
const bucket_ptr buckets = priv_buckets();
//First erase the nodes of the first bucket
{
bucket_type &first_b = buckets[first_bucket_num];
local_iterator nxt(before_first_local_it); ++nxt;
local_iterator end = first_b.end();
while(nxt != end){
nxt = first_b.erase_after_and_destroy(before_first_local_it, destroyer);
size_traits::decrement();
}
}
//Now fully clear the intermediate buckets
for(size_type i = first_bucket_num+1; i < last_bucket_num; ++i){
bucket_type &b = buckets[i];
if(b.empty())
continue;
local_iterator b_begin(b.before_begin());
local_iterator nxt(b_begin); ++nxt;
local_iterator end = b.end();
while(nxt != end){
nxt = b.erase_after_and_destroy(b_begin, destroyer);
size_traits::decrement();
}
}
//Now erase nodes from the last bucket
{
bucket_type &last_b = buckets[last_bucket_num];
local_iterator b_begin(last_b.before_begin());
local_iterator nxt(b_begin); ++nxt;
while(nxt != last_local_it){
nxt = last_b.erase_after_and_destroy(b_begin, destroyer);
size_traits::decrement();
}
}
}
template<class Destroyer>
size_type erase_and_destroy(const_reference value, Destroyer destroyer)
{ return erase_and_destroy(value, priv_hasher(), priv_equal(), destroyer); }
template<class KeyType, class KeyHasher, class KeyValueEqual, class Destroyer>
size_type erase_and_destroy(const KeyType& key, KeyHasher hasher
,KeyValueEqual equal, Destroyer destroyer)
{
size_type count(0);
if(ConstantTimeSize && this->empty()){
return 0;
}
bucket_type &b = this->priv_buckets()[hasher(key) % this->priv_buckets_len()];
local_iterator it = b.begin();
local_iterator prev = b.before_begin();
bool found = false;
//Find equal value
while(it != b.end()){
if(equal(key, *it)){
found = true;
break;
}
++prev;
++it;
}
if(!found)
return 0;
//If found erase all equal values
for(local_iterator end = b.end(); it != end && equal(key, *it); ++count){
it = b.erase_after_and_destroy(prev, destroyer);
size_traits::decrement();
}
return count;
}
void clear()
{
if(safemode_or_autounlink){
priv_clear_buckets();
}
size_traits::set_size(size_type(0));
}
template<class Destroyer>
void clear_and_destroy(Destroyer destroyer)
{
if(!ConstantTimeSize || !this->empty()){
size_type num_buckets = this->bucket_count();
bucket_ptr b = this->priv_buckets();
for(; num_buckets--; ++b){
b->clear_and_destroy(destroyer);
}
size_traits::set_size(size_type(0));
}
}
size_type count(const_reference value) const
{ return this->count(value, this->priv_hasher(), this->priv_equal()); }
template<class KeyType, class KeyHasher, class KeyValueEqual>
size_type count(const KeyType &key, const KeyHasher &hasher, const KeyValueEqual &equal) const
{
size_type bucket_n1, bucket_n2, count;
priv_equal_range(key, hasher, equal, bucket_n1, bucket_n2, count);
return count;
}
iterator find(const_reference value)
{ return find(value, this->priv_hasher(), this->priv_equal()); }
template<class KeyType, class KeyHasher, class KeyValueEqual>
iterator find(const KeyType &key, KeyHasher hasher, KeyValueEqual equal)
{
size_type bucket_n, hash;
local_iterator local_it = priv_find(key, hasher, equal, bucket_n, hash);
return iterator( local_it
, this->priv_bucket_info());
}
const_iterator find(const_reference value) const
{ return find(value, this->priv_hasher(), this->priv_equal()); }
template<class KeyType, class KeyHasher, class KeyValueEqual>
const_iterator find
(const KeyType &key, KeyHasher hasher, KeyValueEqual equal) const
{
size_type bucket_n, hash;
local_iterator local_it = priv_find(key, hasher, equal, bucket_n, hash);
return const_iterator( local_it
, uncast(this->priv_bucket_info()));
}
std::pair<iterator,iterator> equal_range(const_reference value)
{ return this->equal_range(value, this->priv_hasher(), this->priv_equal()); }
template<class KeyType, class KeyHasher, class KeyValueEqual>
std::pair<iterator,iterator> equal_range
(const KeyType &key, KeyHasher hasher, KeyValueEqual equal)
{
size_type bucket_n1, bucket_n2, count;
std::pair<local_iterator, local_iterator> ret
= priv_equal_range(key, hasher, equal, bucket_n1, bucket_n2, count);
return std::pair<iterator, iterator>
( iterator( ret.first, this->priv_bucket_info() )
, iterator( ret.second, this->priv_bucket_info()) );
}
std::pair<const_iterator, const_iterator>
equal_range(const_reference value) const
{ return this->equal_range(value, this->priv_hasher(), this->priv_equal()); }
template<class KeyType, class KeyHasher, class KeyValueEqual>
std::pair<const_iterator,const_iterator> equal_range
(const KeyType &key, KeyHasher hasher, KeyValueEqual equal) const
{
size_type bucket_n1, bucket_n2, count;
std::pair<local_iterator, local_iterator> ret
= priv_equal_range(key, hasher, equal, bucket_n1, bucket_n2, count);
return std::pair<const_iterator, const_iterator>
( const_iterator( ret.first, uncast(this->priv_bucket_info()) )
, const_iterator( ret.second, uncast(this->priv_bucket_info()) ) );
}
size_type bucket_count() const
{ return this->priv_buckets_len(); }
size_type bucket_size(size_type n) const
{ return this->priv_buckets()[n].size(); }
size_type bucket(const key_type& k) const
{ return this->bucket(k, this->priv_hasher()); }
template<class KeyType, class KeyHasher>
size_type bucket(const KeyType& k, const KeyHasher &hasher) const
{ return hasher(k) % this->priv_buckets_len(); }
bucket_ptr bucket_pointer() const
{ return this->priv_buckets(); }
local_iterator begin(size_type n)
{ return this->priv_buckets()[n].begin(); }
const_local_iterator begin(size_type n) const
{ return this->cbegin(n); }
const_local_iterator cbegin(size_type n) const
{ return const_cast<const bucket_type&>(this->priv_buckets()[n]).begin(); }
local_iterator end(size_type n)
{ return this->priv_buckets()[n].end(); }
const_local_iterator end(size_type n) const
{ return this->cend(n); }
const_local_iterator cend(size_type n) const
{ return const_cast<const bucket_type&>(this->priv_buckets()[n]).end(); }
void rehash(bucket_ptr new_buckets, size_type new_buckets_len)
{
bucket_ptr old_buckets = this->priv_buckets();
size_type old_buckets_len = this->priv_buckets_len();
try{
size_type n = 0;
bool same_buffer = old_buckets == new_buckets;
//If we are shrinking the bucket array, just rehash the last nodes
if(same_buffer && (old_buckets_len > new_buckets_len)){
n = new_buckets_len;
}
//Iterate through nodes
for(; n < old_buckets_len; ++n){
bucket_type &old_bucket = old_buckets[n];
local_iterator before_i(old_bucket.before_begin());
local_iterator end(old_bucket.end());
local_iterator i(old_bucket.begin());
for(;i != end; ++i){
size_type new_n = this->priv_hasher()(*i) % new_buckets_len;
//If this is a buffer expansion don't move if it's not necessary
if(same_buffer && new_n == n){
++before_i;
}
else{
bucket_type &new_b = new_buckets[new_n];
new_b.splice_after(new_b.before_begin(), old_bucket, before_i);
i = before_i;
}
}
}
this->priv_buckets() = new_buckets;
this->priv_buckets_len() = new_buckets_len;
}
catch(...){
for(size_type n = 0; n < new_buckets_len; ++n){
new_buckets[n].clear();
old_buckets[n].clear();
}
size_traits::set_size(size_type(0));
throw;
}
}
iterator iterator_to(reference value)
{
return iterator( bucket_type::iterator_to(value)
, this->priv_bucket_info());
}
const_iterator iterator_to(const_reference value) const
{
return const_iterator( bucket_type::iterator_to(const_cast<reference>(value))
, uncast(this->priv_bucket_info()));
}
static local_iterator local_iterator_to(reference value)
{ return bucket_type::iterator_to(value); }
static const_local_iterator local_iterator_to(const_reference value)
{ return bucket_type::iterator_to(value); }
// no throw
static size_type suggested_upper_bucket_count(size_type n)
{
const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0];
const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size;
size_type const* bound =
std::lower_bound(primes, primes_end, n);
if(bound == primes_end)
bound--;
return size_type(*bound);
}
// no throw
static size_type suggested_lower_bucket_count(size_type n)
{
const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0];
const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size;
size_type const* bound =
std::upper_bound(primes, primes_end, n);
if(bound != primes_end)
bound--;
return size_type(*bound);
}
/// @cond
private:
static local_iterator invalid_local_it(const bucket_info_t &b)
{ return b.buckets_->end(); }
local_iterator priv_begin(size_type &bucket_num) const
{
size_type buckets_len = this->priv_buckets_len();
for (bucket_num = 0; bucket_num < buckets_len; ++bucket_num){
bucket_type &b = this->priv_buckets()[bucket_num];
if(!b.empty())
return b.begin();
}
return invalid_local_it(*this->priv_bucket_info());
}
void priv_clear_buckets()
{ priv_clear_buckets(this->priv_buckets(), this->priv_buckets_len()); }
static void priv_clear_buckets(bucket_ptr buckets_ptr, size_type buckets_len)
{
for(; buckets_len--; ++buckets_ptr){
buckets_ptr->clear();
}
}
template<class KeyType, class KeyHasher, class KeyValueEqual>
local_iterator priv_find
( const KeyType &key, KeyHasher hasher
, KeyValueEqual equal, size_type &bucket_number, size_type &hash) const
{
size_type b_len(this->priv_buckets_len());
hash = hasher(key);
bucket_number = hash % b_len;
if(ConstantTimeSize && this->empty()){
return invalid_local_it(*this->priv_bucket_info());
}
bucket_type &b = this->priv_buckets()[bucket_number];
local_iterator it = b.begin();
while(it != b.end()){
if(equal(key, *it)){
return it;
}
++it;
}
return invalid_local_it(*this->priv_bucket_info());
}
template<class KeyType, class KeyHasher, class KeyValueEqual>
std::pair<local_iterator, local_iterator> priv_equal_range
( const KeyType &key
, KeyHasher hasher
, KeyValueEqual equal
, size_type &bucket_number_first
, size_type &bucket_number_second
, size_type &count) const
{
size_type hash;
count = 0;
//Let's see if the element is present
std::pair<local_iterator, local_iterator> to_return
( priv_find(key, hasher, equal, bucket_number_first, hash)
, invalid_local_it(*this->priv_bucket_info()));
if(to_return.first == to_return.second){
bucket_number_second = bucket_number_first;
return to_return;
}
++count;
//If it's present, find the first that it's not equal in
//the same bucket
bucket_type &b = this->priv_buckets()[bucket_number_first];
local_iterator it = to_return.first;
++it;
while(it != b.end()){
if(!equal(key, *it)){
to_return.second = it;
bucket_number_second = bucket_number_first;
return to_return;
}
++it;
++count;
}
//If we reached the end, find the first, non-empty bucket
for(bucket_number_second = bucket_number_first+1
; bucket_number_second != this->priv_buckets_len()
; ++bucket_number_second){
bucket_type &b = this->priv_buckets()[bucket_number_second];
if(!b.empty()){
to_return.second = b.begin();
return to_return;
}
}
//Otherwise, return the end node
to_return.second = invalid_local_it(*this->priv_bucket_info());
return to_return;
}
/// @endcond
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_HASHTABLE_HPP

View File

@ -0,0 +1,154 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_FWD_HPP
#define BOOST_INTRUSIVE_FWD_HPP
#include <cstddef>
#include <boost/functional/hash_fwd.hpp>
#include <boost/intrusive/tag.hpp>
#include <boost/intrusive/linking_policy.hpp>
//std predeclarations
namespace std{
template<class T>
struct equal_to;
template<class T>
struct less;
} //namespace std{
namespace boost {
namespace intrusive {
////////////////////////////
// Node algorithms
////////////////////////////
//Algorithms predeclarations
template<class NodeTraits>
class circular_list_algorithms;
template<class NodeTraits>
class circular_slist_algorithms;
template<class NodeTraits>
class rbtree_algorithms;
////////////////////////////
// Containers
////////////////////////////
//slist
template < class ValueTraits
, bool ConstantTimeSize = true
, class SizeType = std::size_t>
class slist;
template< class Tag = tag
, linking_policy Policy = safe_link
, class VoidPointer = void *
>
class slist_base_hook;
template< linking_policy Policy = safe_link
, class VoidPointer = void *>
class slist_member_hook;
//list
template< class ValueTraits
, bool ConstantTimeSize = true
, class SizeType = std::size_t>
class list;
template< class Tag = tag
, linking_policy Policy = safe_link
, class VoidPointer = void *
>
class list_base_hook;
template< linking_policy Policy = safe_link
, class VoidPointer = void *>
class list_member_hook;
//hash/unordered
template< class ValueTraits
, class Hash = boost::hash<typename ValueTraits::value_type>
, class Equal = std::equal_to<typename ValueTraits::value_type>
, bool ConstantTimeSize = true
, class SizeType = std::size_t
>
class hashtable;
template< class ValueTraits
, class Hash = boost::hash<typename ValueTraits::value_type>
, class Equal = std::equal_to<typename ValueTraits::value_type>
, bool ConstantTimeSize = true
, class SizeType = std::size_t
>
class unordered_set;
template< class ValueTraits
, class Hash = boost::hash<typename ValueTraits::value_type>
, class Equal = std::equal_to<typename ValueTraits::value_type>
, bool ConstantTimeSize = true
, class SizeType = std::size_t
>
class unordered_multiset;
template< class Tag = tag
, linking_policy Policy = safe_link
, class VoidPointer = void *
>
class unordered_set_base_hook;
template< linking_policy Policy = safe_link
, class VoidPointer = void *>
class unordered_set_member_hook;
//rbtree/set
template < class ValueTraits
, class Compare = std::less<typename ValueTraits::value_type>
, bool ConstantTimeSize = true
, class SizeType = std::size_t
>
class rbtree;
template < class ValueTraits
, class Compare = std::less<typename ValueTraits::value_type>
, bool ConstantTimeSize = true
, class SizeType = std::size_t>
class set;
template < class ValueTraits
, class Compare = std::less<typename ValueTraits::value_type>
, bool ConstantTimeSize = true
, class SizeType = std::size_t>
class multiset;
template< class Tag = tag
, linking_policy Policy = safe_link
, class VoidPointer = void *
>
class set_base_hook;
template< linking_policy Policy = safe_link
, class VoidPointer = void *>
class set_member_hook;
} //namespace intrusive {
} //namespace boost {
#endif //#ifndef BOOST_INTRUSIVE_FWD_HPP

View File

@ -0,0 +1,46 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_VALUE_LINKING_POLICY_HPP
#define BOOST_INTRUSIVE_VALUE_LINKING_POLICY_HPP
namespace boost {
namespace intrusive {
//!This enumeration defines the type of value_traits that can be defined
//!for Boost.Intrusive containers
enum linking_policy{
//!If this linking policy is specified in a value_traits class
//!as the linking_policy, containers
//!configured with such value_traits won't set the hooks
//!of the erased values to a default state. Containers also won't
//!check that the hooks of the new values are default initialized.
normal_link,
//!If this linking policy is specified in a value_traits class
//!as the linking_policy, containers
//!configured with such value_traits will set the hooks
//!of the erased values to a default state. Containers also will
//!check that the hooks of the new values are default initialized.
safe_link,
//!Same as "safe_link" but the user type is an auto-unlink
//!type, so the containers with constant-time size features won't be
//!compatible with value_traits configured with this policy.
//!Containers also know that the a value can be silently erased from
//!the container without using any function provided by the containers.
auto_unlink
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_VALUE_LINKING_POLICY_HPP

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,400 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_LIST_HOOK_HPP
#define BOOST_INTRUSIVE_LIST_HOOK_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/detail/list_node.hpp>
#include <boost/intrusive/circular_list_algorithms.hpp>
#include <boost/intrusive/linking_policy.hpp>
#include <boost/intrusive/tag.hpp>
#include <boost/get_pointer.hpp>
#include <boost/static_assert.hpp>
#include <stdexcept>
namespace boost {
namespace intrusive {
//! Derive a class from list_base_hook in order to store objects in
//! in an list. list_base_hook holds the data necessary to maintain the
//! list and provides an appropriate value_traits class for list.
//!
//! The first integer template argument defines a tag to identify the node.
//! The same tag value can be used in different classes, but if a class is
//! derived from more than one list_base_hook, then each list_base_hook needs its
//! unique tag.
//!
//! The second boolean template parameter will specify the linking mode of the hook.
//!
//! The third argument is the pointer type that will be used internally in the hook
//! and the list configured from this hook.
template< class Tag //= tag
, linking_policy Policy //= safe_link
, class VoidPointer //= void *
>
class list_base_hook
: private detail::list_node_traits<VoidPointer>::node
{
public:
typedef detail::list_node_traits<VoidPointer> node_traits;
enum { linking_policy = Policy };
/// @cond
private:
typedef circular_list_algorithms<node_traits> node_algorithms;
public:
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef list_base_hook
<Tag, Policy, VoidPointer> this_type;
typedef typename boost::pointer_to_other
<VoidPointer, this_type>::type this_type_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const this_type>::type const_this_type_ptr;
private:
node_ptr this_as_node()
{ return node_ptr(static_cast<node *const>(this)); }
const_node_ptr this_as_node() const
{ return const_node_ptr(static_cast<const node *const>(this)); }
/// @endcond
public:
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
list_base_hook()
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using list_base_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
list_base_hook(const list_base_hook& )
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using list_base_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
list_base_hook& operator=(const list_base_hook& )
{ return *this; }
//! <b>Effects</b>: If Policy is normal_link, the destructor does
//! nothing (ie. no code is generated). If Policy is safe_link and the
//! object is stored in an list an assertion is raised. If Policy is
//! auto_unlink and "is_linked()" is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~list_base_hook()
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
//! related to those nodes in one or two containers. That is, if the node
//! this is part of the element e1, the node x is part of the element e2
//! and both elements are included in the containers s1 and s2, then after
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
//! at the position of e1. If one element is not in a container, then
//! after the swap-operation the other element is not in a container.
//! Iterators to e1 and e2 related to those nodes are invalidated.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
void swap_nodes(list_base_hook &other)
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether list::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const
{
//is_linked() can be only used in safe-mode or auto-unlink
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
return !node_algorithms::unique(this_as_node());
}
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if Policy is auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink()
{
BOOST_STATIC_ASSERT((Policy == auto_unlink));
node_algorithms::unlink(this_as_node());
node_algorithms::init(this_as_node());
}
//! The value_traits class is used as the first template argument for list.
//! The template argument T defines the class type stored in list. Objects
//! of type T and of types derived from T can be stored. T doesn't need to be
//! copy-constructible or assignable.
template<class T>
struct value_traits
: detail::derivation_value_traits<T, this_type, Tag>
{};
//! <b>Effects</b>: Converts a pointer to a node into
//! a pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static this_type_ptr to_hook_ptr(node_ptr p)
{
using boost::get_pointer;
return this_type_ptr(static_cast<list_base_hook*> (get_pointer(p)));
}
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
//! a const pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
{
using boost::get_pointer;
return const_this_type_ptr(static_cast<const list_base_hook*> (get_pointer(p)));
}
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
node_ptr to_node_ptr()
{ return this_as_node(); }
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
const_node_ptr to_node_ptr() const
{ return this_as_node(); }
};
//! Put a public data member list_member_hook in order to store objects of this class in
//! an list. list_member_hook holds the data necessary for maintaining the list and
//! provides an appropriate value_traits class for list.
//!
//! The first boolean template parameter will specify the linking mode of the hook.
//!
//! The second argument is the pointer type that will be used internally in the hook
//! and the list configured from this hook.
template< linking_policy Policy //= safe_link
, class VoidPointer //= void *
>
class list_member_hook
: private detail::list_node_traits<VoidPointer>::node
{
public:
typedef detail::list_node_traits<VoidPointer> node_traits;
enum { linking_policy = Policy };
/// @cond
private:
typedef circular_list_algorithms<node_traits> node_algorithms;
/// @endcond
public:
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef list_member_hook
<Policy, VoidPointer> this_type;
typedef typename boost::pointer_to_other
<VoidPointer, this_type >::type this_type_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const this_type >::type const_this_type_ptr;
/// @cond
private:
node_ptr this_as_node()
{ return node_ptr(static_cast<node *const>(this)); }
const_node_ptr this_as_node() const
{ return const_node_ptr(static_cast<const node *const>(this)); }
/// @endcond
public:
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
list_member_hook()
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using list_member_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
list_member_hook(const list_member_hook& )
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using list_member_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
list_member_hook& operator=(const list_member_hook& )
{ return *this; }
//! <b>Effects</b>: If Policy is normal_link, the destructor does
//! nothing (ie. no code is generated). If Policy is safe_link and the
//! object is stored in an list an assertion is raised. If Policy is
//! auto_unlink and "is_linked()" is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~list_member_hook()
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
//! related to those nodes in one or two containers. That is, if the node
//! this is part of the element e1, the node x is part of the element e2
//! and both elements are included in the containers s1 and s2, then after
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
//! at the position of e1. If one element is not in a container, then
//! after the swap-operation the other element is not in a container.
//! Iterators to e1 and e2 related to those nodes are invalidated.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
void swap_nodes(list_member_hook& other)
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether list::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const
{
//is_linked() can be only used in safe-mode or auto-unlink
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
return !node_algorithms::unique(this_as_node());
}
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if Policy is auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink()
{
BOOST_STATIC_ASSERT((Policy == auto_unlink));
node_algorithms::unlink(this_as_node());
node_algorithms::init(this_as_node());
}
//! The value_traits class is used as the first template argument for list.
//! The template argument is a pointer to member pointing to the node in
//! the class. Objects of type T and of types derived from T can be stored.
//! T doesn't need to be copy-constructible or assignable.
template<class T, this_type T::* M>
struct value_traits
: detail::member_value_traits<T, this_type, M>
{};
//! <b>Effects</b>: Converts a pointer to a node into
//! a pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static this_type_ptr to_hook_ptr(node_ptr p)
{
using boost::get_pointer;
return this_type_ptr(static_cast<this_type*> (get_pointer(p)));
}
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
//! a const pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
{
using boost::get_pointer;
return const_this_type_ptr(static_cast<const this_type*> (get_pointer(p)));
}
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
node_ptr to_node_ptr()
{ return this_as_node(); }
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
const_node_ptr to_node_ptr() const
{ return this_as_node(); }
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_LIST_HOOK_HPP

View File

@ -0,0 +1,82 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
#define BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
#include<boost/type_traits/alignment_of.hpp>
#include<boost/static_assert.hpp>
namespace boost {
namespace intrusive {
//!This trait class is used to know if a pointer
//!can embed an extra bit of information if
//!it's going to be used to point to objects
//!with an alignment of "Alignment" bytes.
template<class Pointer>
struct has_pointer_plus_bit
{
enum { value = false };
};
//!This is an specialization for raw pointers.
//!Raw pointers can embed an extra bit in the lower bit
//!if the alignment is multiple of 2.
template<class T>
struct has_pointer_plus_bit<T*>
{
enum { value = (boost::alignment_of<T>::value % 2u) == 0 };
};
//!This is class that is supposed to have static methods
//!to embed an extra bit of information in a pointer.
//!This is a declaration and there is no default implementation,
//!because operations to embed the bit change with every pointer type.
//!
//!An implementation that detects that a pointer type whose
//!has_pointer_plus_bit<>::value is non-zero can make use of these
//!operations to embed the bit in the pointer.
template<class Pointer>
struct pointer_plus_bit;
//!This is the specialization to embed an extra bit of information
//!in a raw pointer. The extra bit is stored in the lower bit of the pointer.
template<class T>
struct pointer_plus_bit<T*>
{
typedef T* pointer;
//Check that the pointer can embed the bit
BOOST_STATIC_ASSERT((has_pointer_plus_bit<T*>::value));
static pointer get_pointer(pointer n)
{ return pointer(std::size_t(n) & std::size_t(~1u)); }
static void set_pointer(pointer &n, pointer p)
{
assert(0 == (std::size_t(p) & std::size_t(1u)));
n = pointer(std::size_t(p) | (std::size_t(n) & std::size_t(1u)));
}
static bool get_bit(pointer n)
{ return (std::size_t(n) & std::size_t(1u)) != 0; }
static void set_bit(pointer &n, bool c)
{ n = pointer(std::size_t(get_pointer(n)) | std::size_t(c)); }
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,367 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_SET_HOOK_HPP
#define BOOST_INTRUSIVE_SET_HOOK_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/detail/rbtree_node.hpp>
#include <boost/intrusive/rbtree_algorithms.hpp>
#include <boost/intrusive/linking_policy.hpp>
#include <boost/intrusive/tag.hpp>
#include <boost/get_pointer.hpp>
#include <boost/static_assert.hpp>
#include <stdexcept>
namespace boost {
namespace intrusive {
//! Derive a class from set_base_hook in order to store objects in
//! in an set/multiset. set_base_hook holds the data necessary to maintain
//! the set/multiset and provides an appropriate value_traits class for set/multiset.
//!
//! The first integer template argument defines a tag to identify the node.
//! The same tag value can be used in different classes, but if a class is
//! derived from more than one set_base_hook, then each set_base_hook needs its
//! unique tag.
//!
//! The second boolean template parameter will specify the linking mode of the hook.
//!
//! The third argument is the pointer type that will be used internally in the hook
//! and the set/multiset configured from this hook.
template< class Tag //= tag
, linking_policy Policy //= safe_link
, class VoidPointer //= void *
>
class set_base_hook
: private detail::rbtree_node_traits<VoidPointer>::node
{
public:
typedef detail::rbtree_node_traits<VoidPointer> node_traits;
enum { linking_policy = Policy };
/// @cond
private:
typedef rbtree_algorithms<node_traits> node_algorithms;
/// @endcond
public:
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef set_base_hook
<Tag, Policy, VoidPointer> this_type;
typedef typename boost::pointer_to_other
<VoidPointer, this_type>::type this_type_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const this_type>::type const_this_type_ptr;
/// @cond
private:
node_ptr this_as_node()
{ return node_ptr(static_cast<node *const>(this)); }
const_node_ptr this_as_node() const
{ return const_node_ptr(static_cast<const node *const>(this)); }
/// @endcond
public:
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
set_base_hook()
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using set_base_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
set_base_hook(const set_base_hook& )
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using set_base_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
set_base_hook& operator=(const set_base_hook& )
{ return *this; }
//! <b>Effects</b>: If Policy is normal_link, the destructor does
//! nothing (ie. no code is generated). If Policy is safe_link and the
//! object is stored in an list an assertion is raised. If Policy is
//! auto_unlink and "is_linked()" is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~set_base_hook()
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether set::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const
{
//is_linked() can be only used in safe-mode or auto-unlink
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
return !node_algorithms::unique(this_as_node());
}
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if Policy is auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink()
{
BOOST_STATIC_ASSERT((Policy == auto_unlink));
node_algorithms::unlink_and_rebalance(this_as_node());
node_algorithms::init(this_as_node());
}
//! The value_traits class is used as the first template argument for multiset.
//! The template argument T defines the class type stored in multiset. Objects
//! of type T and of types derived from T can be stored. T don't need to be
//! copy-constructible or assignable.
template<class T>
struct value_traits
: detail::derivation_value_traits<T, this_type, Tag>
{};
//! <b>Effects</b>: Converts a pointer to a node into
//! a pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static this_type_ptr to_hook_ptr(node_ptr p)
{
using boost::get_pointer;
return this_type_ptr(static_cast<set_base_hook*> (get_pointer(p)));
}
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
//! a const pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
{
using boost::get_pointer;
return const_this_type_ptr(static_cast<const set_base_hook*> (get_pointer(p)));
}
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
node_ptr to_node_ptr()
{ return this_as_node(); }
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
const_node_ptr to_node_ptr() const
{ return this_as_node(); }
};
//! Put a public data member set_member_hook in order to store objects of this class in
//! an set/multiset. set_member_hook holds the data necessary for maintaining the
//! set/multiset and provides an appropriate value_traits class for set/multiset.
//!
//! The first boolean template parameter will specify the linking mode of the hook.
//!
//! The second argument is the pointer type that will be used internally in the hook
//! and the set/multiset configured from this hook.
template< linking_policy Policy //= safe_link
, class VoidPointer //= void *
>
class set_member_hook
: private detail::rbtree_node_traits<VoidPointer>::node
{
public:
typedef detail::rbtree_node_traits<VoidPointer> node_traits;
enum { linking_policy = Policy };
/// @cond
private:
typedef rbtree_algorithms<node_traits> node_algorithms;
/// @endcond
public:
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef set_member_hook
<Policy, VoidPointer> this_type;
typedef typename boost::pointer_to_other
<VoidPointer, this_type >::type this_type_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const this_type >::type const_this_type_ptr;
/// @cond
private:
node_ptr this_as_node()
{ return node_ptr(static_cast<node *const>(this)); }
const_node_ptr this_as_node() const
{ return const_node_ptr(static_cast<const node *const>(this)); }
/// @endcond
public:
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
set_member_hook()
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using set_member_hook STL-compliant without forcing the
//! user to do some additional work.
set_member_hook(const set_member_hook& )
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using set_member_hook STL-compliant without forcing the
//! user to do some additional work.
set_member_hook& operator=(const set_member_hook& )
{ return *this; }
//! <b>Effects</b>: If Policy is normal_link, the destructor does
//! nothing (ie. no code is generated). If Policy is safe_link and the
//! object is stored in an list an assertion is raised. If Policy is
//! auto_unlink and "is_linked()" is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~set_member_hook()
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const
{
//is_linked() can be only used in safe-mode or auto-unlink
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
return !node_algorithms::unique(this_as_node());
}
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if Policy is auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink()
{
BOOST_STATIC_ASSERT((Policy == auto_unlink));
node_algorithms::unlink_and_rebalance(this_as_node());
node_algorithms::init(this_as_node());
}
//! The value_traits class is used as the first template argument for multiset.
//! The template argument is a pointer to member pointing to the node in
//! the class. Objects of type T and of types derived from T can be stored.
//! T don't need to be copy-constructible or assignable.
template<class T, this_type T::* P>
struct value_traits
: detail::member_value_traits<T, this_type, P>
{};
//! <b>Effects</b>: Converts a pointer to a node into
//! a pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static this_type_ptr to_hook_ptr(node_ptr p)
{
using boost::get_pointer;
return this_type_ptr(static_cast<this_type*> (get_pointer(p)));
}
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
//! a const pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
{
using boost::get_pointer;
return const_this_type_ptr(static_cast<const this_type*> (get_pointer(p)));
}
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
node_ptr to_node_ptr()
{ return this_as_node(); }
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
const_node_ptr to_node_ptr() const
{ return this_as_node(); }
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_SET_HOOK_HPP

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,407 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_SLIST_HOOK_HPP
#define BOOST_INTRUSIVE_SLIST_HOOK_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/detail/slist_node.hpp>
#include <boost/intrusive/circular_slist_algorithms.hpp>
#include <boost/intrusive/linking_policy.hpp>
#include <boost/intrusive/tag.hpp>
#include <boost/get_pointer.hpp>
#include <boost/static_assert.hpp>
#include <stdexcept>
namespace boost {
namespace intrusive {
//! Derive a class from slist_base_hook in order to store objects in
//! in an slist. slist_base_hook holds the data necessary to maintain the
//! list and provides an appropriate value_traits class for slist.
//!
//! The first integer template argument defines a tag to identify the node.
//! The same tag value can be used in different classes, but if a class is
//! derived from more than one slist_base_hook, then each slist_base_hook needs its
//! unique tag.
//!
//! The second boolean template parameter will specify the linking mode of the hook.
//!
//! The third argument is the pointer type that will be used internally in the hook
//! and the slist configured from this hook.
template< class Tag //= tag
, linking_policy Policy //= safe_link
, class VoidPointer //= void *
>
class slist_base_hook
: private detail::slist_node_traits<VoidPointer>::node
{
public:
typedef detail::slist_node_traits<VoidPointer> node_traits;
enum { linking_policy = Policy };
/// @cond
private:
typedef circular_slist_algorithms<node_traits> node_algorithms;
/// @endcond
public:
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef slist_base_hook
<Tag, Policy, VoidPointer> this_type;
typedef typename boost::pointer_to_other
<VoidPointer, this_type>::type this_type_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const this_type>::type const_this_type_ptr;
/// @cond
private:
node_ptr this_as_node()
{ return node_ptr(static_cast<node *const>(this)); }
const_node_ptr this_as_node() const
{ return const_node_ptr(static_cast<const node *const>(this)); }
/// @endcond
public:
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
slist_base_hook()
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using slist_base_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
slist_base_hook(const slist_base_hook& )
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using slist_base_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
slist_base_hook& operator=(const slist_base_hook& )
{ return *this; }
//! <b>Effects</b>: If Policy is normal_link, the destructor does
//! nothing (ie. no code is generated). If Policy is safe_link and the
//! object is stored in an list an assertion is raised. If Policy is
//! auto_unlink and "is_linked()" is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~slist_base_hook()
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
//! related to those nodes in one or two containers. That is, if the node
//! this is part of the element e1, the node x is part of the element e2
//! and both elements are included in the containers s1 and s2, then after
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
//! at the position of e1. If one element is not in a container, then
//! after the swap-operation the other element is not in a container.
//! Iterators to e1 and e2 related to those nodes are invalidated.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
void swap_nodes(slist_base_hook &other)
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether list::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const
{
//is_linked() can be only used in safe-mode or auto-unlink
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
return !node_algorithms::unique(this_as_node());
}
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if Policy is auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink()
{
BOOST_STATIC_ASSERT((Policy == auto_unlink));
node_algorithms::unlink(this_as_node());
node_algorithms::init(this_as_node());
}
//! The value_traits class is used as the first template argument for list.
//! The template argument T defines the class type stored in list. Objects
//! of type T and of types derived from T can be stored. T doesn't need to be
//! copy-constructible or assignable.
template<class T>
struct value_traits
: detail::derivation_value_traits<T, this_type, Tag>
{};
//! <b>Effects</b>: Converts a pointer to a node into
//! a pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static this_type_ptr to_hook_ptr(node_ptr p)
{
using boost::get_pointer;
return this_type_ptr(static_cast<slist_base_hook*> (get_pointer(p)));
}
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
//! a const pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
{
using boost::get_pointer;
return const_this_type_ptr(static_cast<const slist_base_hook*> (get_pointer(p)));
}
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
node_ptr to_node_ptr()
{ return this_as_node(); }
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
const_node_ptr to_node_ptr() const
{ return this_as_node(); }
};
//! Put a public data member slist_member_hook in order to store objects of this class in
//! an slist. slist_member_hook holds the data necessary for maintaining the list and
//! provides an appropriate value_traits class for slist.
//!
//! The template argument T defines the class type stored in slist. Objects of type
//! T and of types derived from T can be stored. T doesn't need to be
//! copy-constructible or assignable.
//!
//! The second boolean template parameter will specify the linking mode of the hook.
//!
//! The third argument is the pointer type that will be used internally in the hook
//! and the slist configured from this hook.
template< linking_policy Policy //= safe_link
, class VoidPointer //= void *
>
class slist_member_hook
: private detail::slist_node_traits<VoidPointer>::node
{
public:
typedef detail::slist_node_traits<VoidPointer> node_traits;
enum { linking_policy = Policy };
/// @cond
private:
typedef circular_slist_algorithms<node_traits> node_algorithms;
/// @endcond
public:
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef slist_member_hook
<Policy, VoidPointer> this_type;
typedef typename boost::pointer_to_other
<VoidPointer, this_type >::type this_type_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const this_type >::type const_this_type_ptr;
/// @cond
private:
node_ptr this_as_node()
{ return node_ptr(static_cast<node *const>(this)); }
const_node_ptr this_as_node() const
{ return const_node_ptr(static_cast<const node *const>(this)); }
/// @endcond
public:
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
slist_member_hook()
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using slist_member_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
slist_member_hook(const slist_member_hook& )
: node()
{
if(Policy == safe_link || Policy == auto_unlink){
node_algorithms::init(this_as_node());
}
}
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using slist_member_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
slist_member_hook& operator=(const slist_member_hook& )
{ return *this; }
//! <b>Effects</b>: If Policy is normal_link, the destructor does
//! nothing (ie. no code is generated). If Policy is safe_link and the
//! object is stored in an list an assertion is raised. If Policy is
//! auto_unlink and "is_linked()" is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~slist_member_hook()
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
//! related to those nodes in one or two containers. That is, if the node
//! this is part of the element e1, the node x is part of the element e2
//! and both elements are included in the containers s1 and s2, then after
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
//! at the position of e1. If one element is not in a container, then
//! after the swap-operation the other element is not in a container.
//! Iterators to e1 and e2 related to those nodes are invalidated.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
void swap_nodes(slist_member_hook& other)
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether list::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const
{
//is_linked() can be only used in safe-mode or auto-unlink
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
return !node_algorithms::unique(this_as_node());
}
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if Policy is auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink()
{
BOOST_STATIC_ASSERT((Policy == auto_unlink));
node_algorithms::unlink(this_as_node());
node_algorithms::init(this_as_node());
}
//! The value_traits class is used as the first template argument for list.
//! The template argument is a pointer to member pointing to the node in
//! the class. Objects of type T and of types derived from T can be stored.
//! T doesn't need to be copy-constructible or assignable.
template<class T, this_type T::* M>
struct value_traits
: detail::member_value_traits<T, this_type, M>
{};
//! <b>Effects</b>: Converts a pointer to a node into
//! a pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static this_type_ptr to_hook_ptr(node_ptr p)
{
using boost::get_pointer;
return this_type_ptr(static_cast<this_type*> (get_pointer(p)));
}
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
//! a const pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
{
using boost::get_pointer;
return const_this_type_ptr(static_cast<const this_type*> (get_pointer(p)));
}
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
node_ptr to_node_ptr()
{ return this_as_node(); }
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
const_node_ptr to_node_ptr() const
{ return this_as_node(); }
};
} //namespace intrusive
} //namespace boost
#include<boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_SLIST_HOOK_HPP

View File

@ -0,0 +1,26 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DEFAULT_TAG_HPP
#define BOOST_INTRUSIVE_DEFAULT_TAG_HPP
namespace boost {
namespace intrusive {
//!This is the declaration of the default
//!hook used by base hooks
class tag;
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_DEFAULT_TAG_HPP

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,297 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztañaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_HASHSET_HOOK_HPP
#define BOOST_INTRUSIVE_HASHSET_HOOK_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/pointer_type.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include <boost/intrusive/slist_hook.hpp>
#include <boost/intrusive/linking_policy.hpp>
#include <boost/get_pointer.hpp>
#include <stdexcept>
namespace boost {
namespace intrusive {
//! Derive a class from unordered_set_base_hook in order to store objects in
//! in an unordered_set/unordered_multi_set. unordered_set_base_hook holds the data necessary to maintain
//! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
//!
//! The first integer template argument defines a tag to identify the node.
//! The same tag value can be used in different classes, but if a class is
//! derived from more than one unordered_set_base_hook, then each unordered_set_base_hook needs its
//! unique tag.
//!
//! The second boolean template parameter will specify the linking mode of the hook.
//!
//! The third argument is the pointer type that will be used internally in the hook
//! and the unordered_set/unordered_multi_set configured from this hook.
template< class Tag //= tag
, linking_policy Policy //= safe_link
, class VoidPointer //= void *
>
class unordered_set_base_hook
{
/// @cond
typedef slist_base_hook<Tag, Policy, VoidPointer> IsListHook;
IsListHook m_slisthook;
typedef IsListHook implementation_defined;
/// @endcond
public:
enum { linking_policy = Policy };
typedef typename implementation_defined::node_traits node_traits;
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef unordered_set_base_hook
<Tag, Policy, VoidPointer> this_type;
typedef typename boost::pointer_to_other
<VoidPointer, this_type>::type this_type_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const this_type>::type const_this_type_ptr;
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
unordered_set_base_hook()
: m_slisthook()
{}
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using unordered_set_base_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
unordered_set_base_hook(const unordered_set_base_hook &other)
: m_slisthook(other.m_slisthook)
{}
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using unordered_set_base_hook STL-compliant without forcing the
//! user to do some additional work. "swap" can be used to emulate
//! move-semantics.
unordered_set_base_hook& operator=(const unordered_set_base_hook &other)
{ return *this; }
//! <b>Effects</b>: If Policy is normal_link, the destructor does
//! nothing (ie. no code is generated). If Policy is safe_link and the
//! object is stored in an list an assertion is raised. If Policy is
//! auto_unlink and "is_linked()" is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~unordered_set_base_hook()
{} //m_slisthook's destructor does the job
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether unordered_set/unordered_multiset::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const
{ return m_slisthook.is_linked(); }
//! The value_traits class is used as the first template argument for unordered_set/unordered_multiset.
//! The template argument T defines the class type stored in unordered_set/unordered_multiset. Objects
//! of type T and of types derived from T can be stored. T doesn't need to be
//! copy-constructible or assignable.
template<class T>
struct value_traits
: detail::derivation_value_traits<T, this_type, Tag>
{};
//! <b>Effects</b>: Converts a pointer to a node into
//! a pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static this_type_ptr to_hook_ptr(node_ptr p)
{
using boost::get_pointer;
return this_type_ptr((this_type*)get_pointer(IsListHook::to_hook_ptr(p)));
}
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
//! a const pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
{
using boost::get_pointer;
return const_this_type_ptr((const this_type*)get_pointer(IsListHook::to_hook_ptr(p)));
}
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
node_ptr to_node_ptr()
{ return m_slisthook.to_node_ptr(); }
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
const_node_ptr to_node_ptr() const
{ return m_slisthook.to_node_ptr(); }
};
//! Put a public data member unordered_set_member_hook in order to store objects of this class in
//! an unordered_set/unordered_multi_set. unordered_set_member_hook holds the data necessary for maintaining the
//! unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
//!
//! The first boolean template parameter will specify the linking mode of the hook.
//!
//! The second argument is the pointer type that will be used internally in the hook
//! and the unordered_set/unordered_multi_set configured from this hook.
template< linking_policy Policy //= safe_link
, class VoidPointer //= void *
>
class unordered_set_member_hook
{
/// @cond
typedef slist_member_hook<Policy, VoidPointer> IsListHook;
IsListHook m_slisthook;
typedef IsListHook implementation_defined;
/// @endcond
public:
enum { linking_policy = Policy };
typedef typename implementation_defined::node_traits node_traits;
typedef typename node_traits::node node;
typedef typename boost::pointer_to_other
<VoidPointer, node>::type node_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const node>::type const_node_ptr;
typedef unordered_set_member_hook
<Policy, VoidPointer> this_type;
typedef typename boost::pointer_to_other
<VoidPointer, this_type>::type this_type_ptr;
typedef typename boost::pointer_to_other
<VoidPointer, const this_type>::type const_this_type_ptr;
public:
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
unordered_set_member_hook()
: m_slisthook()
{}
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using unordered_set_member_hook STL-compliant without forcing the
//! user to do some additional work.
unordered_set_member_hook(const unordered_set_member_hook &other)
: m_slisthook(other.m_slisthook)
{}
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using unordered_set_member_hook STL-compliant without forcing the
//! user to do some additional work.
unordered_set_member_hook& operator=(const unordered_set_member_hook &other)
{ return *this; }
//! <b>Effects</b>: If Policy is normal_link, the destructor does
//! nothing (ie. no code is generated). If Policy is safe_link and the
//! object is stored in an list an assertion is raised. If Policy is
//! auto_unlink and "is_linked()" is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~unordered_set_member_hook()
{} //m_slisthook's destructor does the job
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const
{ return m_slisthook.is_linked(); }
//! The value_traits class is used as the first template argument for unordered_set/unordered_multiset.
//! The template argument is a pointer to member pointing to the node in
//! the class. Objects of type T and of types derived from T can be stored.
//! T doesn't need to be copy-constructible or assignable.
template<class T, this_type T::* M>
struct value_traits
: detail::member_value_traits<T, this_type, M>
{};
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if Policy is auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink()
{ m_slisthook.unlink(); }
//! <b>Effects</b>: Converts a pointer to a node into
//! a pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static this_type_ptr to_hook_ptr(node_ptr p)
{
using boost::get_pointer;
return this_type_ptr((this_type*)get_pointer(IsListHook::to_hook_ptr(p)));
}
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
//! a const pointer to the hook that holds that node.
//!
//! <b>Throws</b>: Nothing.
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
{
using boost::get_pointer;
return const_this_type_ptr((const this_type*)get_pointer(IsListHook::to_hook_ptr(p)));
}
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
node_ptr to_node_ptr()
{ return m_slisthook.to_node_ptr(); }
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
//!
//! <b>Throws</b>: Nothing.
const_node_ptr to_node_ptr() const
{ return m_slisthook.to_node_ptr(); }
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_HASHSET_HOOK_HPP