mirror of
https://github.com/boostorg/intrusive.git
synced 2025-08-03 14:34:44 +02:00
Updated Interprocess and Intrusive:
-> Added linear slist to intrusive -> Updated all allocators to version 2 allocators in Interprocess -> Optimized rbtree_best_fit size overhead to 1 std:size_t. [SVN r42878]
This commit is contained in:
@@ -38,7 +38,7 @@ int main()
|
||||
|
||||
//Create an empty doubly linked list container:
|
||||
//"one" will be the first node of the container
|
||||
algo::init(&one);
|
||||
algo::init_header(&one);
|
||||
assert(algo::count(&one) == 1);
|
||||
|
||||
//Now add a new node before "one"
|
||||
|
@@ -36,7 +36,7 @@ int main()
|
||||
|
||||
//Create an empty singly linked list container:
|
||||
//"one" will be the first node of the container
|
||||
algo::init(&one);
|
||||
algo::init_header(&one);
|
||||
assert(algo::count(&one) == 1);
|
||||
|
||||
//Now add a new node
|
||||
|
@@ -54,6 +54,27 @@ class circular_list_algorithms
|
||||
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
||||
typedef NodeTraits node_traits;
|
||||
|
||||
//! <b>Effects</b>: Constructs an non-used list element, so that
|
||||
//! inited(this_node) == true
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void init(node_ptr this_node)
|
||||
{
|
||||
NodeTraits::set_next(this_node, 0);
|
||||
NodeTraits::set_previous(this_node, 0);
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns true is "this_node" is in a non-used state
|
||||
//! as if it was initialized by the "init" function.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static bool inited(const_node_ptr this_node)
|
||||
{ return !NodeTraits::get_next(this_node); }
|
||||
|
||||
//! <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)
|
||||
@@ -62,11 +83,12 @@ class circular_list_algorithms
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void init(node_ptr this_node)
|
||||
static void init_header(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.
|
||||
//!
|
||||
@@ -76,8 +98,11 @@ class circular_list_algorithms
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static bool unique(const_node_ptr this_node)
|
||||
{ return NodeTraits::get_next(this_node) == this_node; }
|
||||
static bool unique(const_node_ptr this_node)
|
||||
{
|
||||
node_ptr next = NodeTraits::get_next(this_node);
|
||||
return !next || next == this_node;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
@@ -107,11 +132,16 @@ class circular_list_algorithms
|
||||
//! <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;
|
||||
if(NodeTraits::get_next(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;
|
||||
}
|
||||
else{
|
||||
return this_node;
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
|
||||
@@ -229,6 +259,17 @@ class circular_list_algorithms
|
||||
public:
|
||||
static void swap_nodes(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
if (other_node == this_node)
|
||||
return;
|
||||
bool this_inited = inited(this_node);
|
||||
bool other_inited = inited(other_node);
|
||||
if(this_inited){
|
||||
init_header(this_node);
|
||||
}
|
||||
if(other_inited){
|
||||
init_header(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));
|
||||
@@ -238,6 +279,13 @@ class circular_list_algorithms
|
||||
swap_next(prev_this, prev_other);
|
||||
swap_next(this_node, other_node);
|
||||
swap_prev(this_node, other_node);
|
||||
|
||||
if(this_inited){
|
||||
init(other_node);
|
||||
}
|
||||
if(other_inited){
|
||||
init(this_node);
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
|
||||
@@ -254,8 +302,8 @@ class circular_list_algorithms
|
||||
{
|
||||
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));
|
||||
node_ptr prev_e(NodeTraits::get_previous(e));
|
||||
NodeTraits::set_next(prev_e, p);
|
||||
NodeTraits::set_previous(p, prev_e);
|
||||
NodeTraits::set_next(prev_b, e);
|
||||
@@ -308,6 +356,47 @@ class circular_list_algorithms
|
||||
f = n;
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Moves the node p n positions towards the end of the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of moved positions.
|
||||
static void move_backwards(node_ptr p, std::size_t n)
|
||||
{
|
||||
//Null shift, nothing to do
|
||||
if(!n) return;
|
||||
node_ptr first = NodeTraits::get_next(p);
|
||||
//size() == 0 or 1, nothing to do
|
||||
if(first == NodeTraits::get_previous(p)) return;
|
||||
unlink(p);
|
||||
//Now get the new first node
|
||||
while(n--){
|
||||
first = NodeTraits::get_next(first);
|
||||
}
|
||||
link_before(first, p);
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of moved positions.
|
||||
static void move_forward(node_ptr p, std::size_t n)
|
||||
{
|
||||
//Null shift, nothing to do
|
||||
if(!n) return;
|
||||
node_ptr last = NodeTraits::get_previous(p);
|
||||
//size() == 0 or 1, nothing to do
|
||||
if(last == NodeTraits::get_next(p)) return;
|
||||
|
||||
unlink(p);
|
||||
//Now get the new last node
|
||||
while(n--){
|
||||
last = NodeTraits::get_previous(last);
|
||||
}
|
||||
link_after(last, p);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
@@ -25,7 +26,7 @@ namespace intrusive {
|
||||
//! 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
|
||||
//! circular_slist_algorithms is configured with a NodeTraits class, which encapsulates the
|
||||
//! information about the node to be manipulated. NodeTraits must support the
|
||||
//! following interface:
|
||||
//!
|
||||
@@ -72,11 +73,13 @@ class circular_slist_algorithms
|
||||
//! <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;
|
||||
node_ptr p = prev_init_node;
|
||||
for( node_ptr p_next
|
||||
; this_node != (p_next = NodeTraits::get_next(p))
|
||||
; p = p_next){
|
||||
//empty
|
||||
//Logic error: possible use of linear lists with
|
||||
//operations only permitted with circular lists
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(p);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -115,25 +118,46 @@ class circular_slist_algorithms
|
||||
|
||||
//! <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>.
|
||||
//! <tt>NodeTraits::get_next(this_node) == this_node</tt>.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void init_header(node_ptr this_node)
|
||||
{ NodeTraits::set_next(this_node, this_node); }
|
||||
|
||||
//! <b>Effects</b>: Constructs an non-used list element, putting the next
|
||||
//! pointer to null:
|
||||
//! <tt>NodeTraits::get_next(this_node) == 0
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void init(node_ptr this_node)
|
||||
{ NodeTraits::set_next(this_node, this_node); }
|
||||
{ NodeTraits::set_next(this_node, 0); }
|
||||
|
||||
//! <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>
|
||||
//! or it's a not inserted node:
|
||||
//! <tt>return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node</tt> or
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static bool unique(const_node_ptr this_node)
|
||||
{ return NodeTraits::get_next(this_node) == this_node; }
|
||||
static bool unique(const_node_ptr this_node)
|
||||
{
|
||||
node_ptr next = NodeTraits::get_next(this_node);
|
||||
return !next || next == this_node;
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns true is "this_node" has the same state as if it was inited using "init(node_ptr)"
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static bool inited(const_node_ptr this_node)
|
||||
{ return !NodeTraits::get_next(this_node); }
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
@@ -165,7 +189,7 @@ class circular_slist_algorithms
|
||||
{
|
||||
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);
|
||||
//NodeTraits::set_next(this_node, this_node);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: nxt_node must be in a circular list or be an empty circular list.
|
||||
@@ -181,7 +205,7 @@ class circular_slist_algorithms
|
||||
unlink_after(prev_to_erase);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//! <b>Requires</b>: this_node must be in a circular list, be an empty circular list or be inited.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the node from the circular list.
|
||||
//!
|
||||
@@ -189,7 +213,10 @@ class circular_slist_algorithms
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void unlink(node_ptr this_node)
|
||||
{ unlink_after(get_previous_node(this_node)); }
|
||||
{
|
||||
if(NodeTraits::get_next(this_node))
|
||||
unlink_after(get_previous_node(this_node));
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: prev_node must be a node of a circular list.
|
||||
//!
|
||||
@@ -200,8 +227,7 @@ class circular_slist_algorithms
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void link_after(node_ptr prev_node, node_ptr this_node)
|
||||
{
|
||||
node_ptr this_nxt = NodeTraits::get_next(prev_node);
|
||||
NodeTraits::set_next(this_node, this_nxt);
|
||||
NodeTraits::set_next(this_node, NodeTraits::get_next(prev_node));
|
||||
NodeTraits::set_next(prev_node, this_node);
|
||||
}
|
||||
|
||||
@@ -229,6 +255,15 @@ class circular_slist_algorithms
|
||||
{
|
||||
if (other_node == this_node)
|
||||
return;
|
||||
bool this_inited = inited(this_node);
|
||||
bool other_inited = inited(other_node);
|
||||
if(this_inited){
|
||||
init_header(this_node);
|
||||
}
|
||||
if(other_inited){
|
||||
init_header(other_node);
|
||||
}
|
||||
|
||||
bool empty1 = unique(this_node);
|
||||
bool empty2 = unique(other_node);
|
||||
node_ptr prev_this (get_previous_node(this_node));
|
||||
@@ -240,12 +275,19 @@ class circular_slist_algorithms
|
||||
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);
|
||||
|
||||
if(this_inited){
|
||||
init(other_node);
|
||||
}
|
||||
if(other_inited){
|
||||
init(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
|
||||
//! <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
|
||||
@@ -278,6 +320,99 @@ class circular_slist_algorithms
|
||||
transfer_after(e, i, nxt);
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Moves the node p n positions towards the end of the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
|
||||
static void move_backwards(node_ptr p, std::size_t n)
|
||||
{
|
||||
//Null shift, nothing to do
|
||||
if(!n) return;
|
||||
node_ptr first = NodeTraits::get_next(p);
|
||||
|
||||
//count() == 1 or 2, nothing to do
|
||||
if(NodeTraits::get_next(first) == p)
|
||||
return;
|
||||
|
||||
bool end_found = false;
|
||||
node_ptr new_last(0);
|
||||
|
||||
//Now find the new last node according to the shift count.
|
||||
//If we find p before finding the new last node
|
||||
//unlink p, shortcut the search now that we know the size of the list
|
||||
//and continue.
|
||||
for(std::size_t i = 1; i <= n; ++i){
|
||||
new_last = first;
|
||||
first = NodeTraits::get_next(first);
|
||||
if(first == p){
|
||||
//Shortcut the shift with the modulo of the size of the list
|
||||
n %= i;
|
||||
if(!n)
|
||||
return;
|
||||
i = 0;
|
||||
//Unlink p and continue the new first node search
|
||||
first = NodeTraits::get_next(p);
|
||||
unlink_after(new_last);
|
||||
end_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
//If the p has not been found in the previous loop, find it
|
||||
//starting in the new first node and unlink it
|
||||
if(!end_found){
|
||||
unlink_after(get_previous_node(first, p));
|
||||
}
|
||||
|
||||
//Now link p after the new last node
|
||||
link_after(new_last, p);
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
|
||||
static void move_forward(node_ptr p, std::size_t n)
|
||||
{
|
||||
//Null shift, nothing to do
|
||||
if(!n) return;
|
||||
node_ptr first = node_traits::get_next(p);
|
||||
|
||||
//count() == 1 or 2, nothing to do
|
||||
if(node_traits::get_next(first) == p) return;
|
||||
|
||||
//Iterate until p is found to know where the current last node is.
|
||||
//If the shift count is less than the size of the list, we can also obtain
|
||||
//the position of the new last node after the shift.
|
||||
node_ptr old_last(first), next_to_it, new_last(p);
|
||||
std::size_t distance = 1;
|
||||
while(p != (next_to_it = node_traits::get_next(old_last))){
|
||||
if(++distance > n)
|
||||
new_last = node_traits::get_next(new_last);
|
||||
old_last = next_to_it;
|
||||
}
|
||||
//If the shift was bigger or equal than the size, obtain the equivalent
|
||||
//forward shifts and find the new last node.
|
||||
if(distance <= n){
|
||||
//Now find the equivalent forward shifts.
|
||||
//Shortcut the shift with the modulo of the size of the list
|
||||
std::size_t new_before_last_pos = (distance - (n % distance))% distance;
|
||||
//If the shift is a multiple of the size there is nothing to do
|
||||
if(!new_before_last_pos) return;
|
||||
|
||||
for( new_last = p
|
||||
; new_before_last_pos--
|
||||
; new_last = node_traits::get_next(new_last)){
|
||||
//empty
|
||||
}
|
||||
}
|
||||
|
||||
//Now unlink p and link it after the new last node
|
||||
unlink_after(old_last);
|
||||
link_after(new_last, p);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
|
@@ -137,9 +137,9 @@ class tree_algorithms
|
||||
{ return uncast(header); }
|
||||
|
||||
//! <b>Requires</b>: node is a node of the tree or an node initialized
|
||||
//! by init(...).
|
||||
//! by init(...) or init_node.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns true if the node is initialized by init().
|
||||
//! <b>Effects</b>: Returns true if the node is initialized by init() or init_node().
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
|
@@ -498,8 +498,8 @@ inline std::size_t floor_log2 (std::size_t x)
|
||||
|
||||
inline float fast_log2 (float val)
|
||||
{
|
||||
boost::uint32_t * const exp_ptr =
|
||||
static_cast <boost::uint32_t * const>(static_cast<void * const >(&val));
|
||||
boost::uint32_t * exp_ptr =
|
||||
static_cast<boost::uint32_t *>(static_cast<void*>(&val));
|
||||
boost::uint32_t x = *exp_ptr;
|
||||
const int log_2 = (int)(((x >> 23) & 255) - 128);
|
||||
x &= ~(255 << 23);
|
||||
|
@@ -69,6 +69,7 @@ template
|
||||
, class O1 = none
|
||||
, class O2 = none
|
||||
, class O3 = none
|
||||
, class O4 = none
|
||||
>
|
||||
class slist;
|
||||
|
||||
|
324
include/boost/intrusive/linear_slist_algorithms.hpp
Normal file
324
include/boost/intrusive/linear_slist_algorithms.hpp
Normal file
@@ -0,0 +1,324 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 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_LINEAR_SLIST_ALGORITHMS_HPP
|
||||
#define BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! linear_slist_algorithms provides basic algorithms to manipulate nodes
|
||||
//! forming a linear singly linked list.
|
||||
//!
|
||||
//! linear_slist_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 linear 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 linear_slist_algorithms
|
||||
{
|
||||
public:
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
||||
typedef NodeTraits node_traits;
|
||||
|
||||
//! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the previous node of this_node in the linear 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>Effects</b>: Constructs an empty list, making this_node the only
|
||||
//! node of the linear list:
|
||||
//! <tt>NodeTraits::get_next(this_node) == 0.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void init_header(node_ptr this_node)
|
||||
{ NodeTraits::set_next(this_node, 0); }
|
||||
|
||||
//! <b>Effects</b>: Constructs an non-used list element, putting the next
|
||||
//! pointer to null:
|
||||
//! <tt>NodeTraits::get_next(this_node) == 0
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void init(node_ptr this_node)
|
||||
{ NodeTraits::set_next(this_node, 0); }
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a linear list or be an empty linear list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns true is "this_node" is the only node of a linear 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)
|
||||
{
|
||||
node_ptr next = NodeTraits::get_next(this_node);
|
||||
return !next || next == this_node;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a linear list or be an empty linear list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns true is "this_node" is the only node of a linear list:
|
||||
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static bool inited(const_node_ptr this_node)
|
||||
{ return !NodeTraits::get_next(this_node); }
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a linear list or be an empty linear list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the number of nodes in a linear list. If the linear 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);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: prev_node must be in a linear list or be an empty linear list.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the next node of prev_node from the linear 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));
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: prev_node must be a node of a linear list.
|
||||
//!
|
||||
//! <b>Effects</b>: Links this_node after prev_node in the linear 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>: this_node and other_node must be nodes inserted
|
||||
//! in linear lists or be empty linear lists.
|
||||
//!
|
||||
//! <b>Effects</b>: Moves all the nodes previously chained after this_node after other_node
|
||||
//! and vice-versa.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void swap_trailing_nodes(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
node_ptr this_nxt = NodeTraits::get_next(this_node);
|
||||
node_ptr other_nxt = NodeTraits::get_next(other_node);
|
||||
NodeTraits::set_next(this_node, other_nxt);
|
||||
NodeTraits::set_next(other_node, this_nxt);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: b and e must be nodes of the same linear list or an empty range.
|
||||
//! and p must be a node of a different linear list.
|
||||
//!
|
||||
//! <b>Effects</b>: Removes the nodes from (b, e] range from their linear list and inserts
|
||||
//! them after p in p's linear 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>Returns</b>: The new first node of the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: This function is linear to the contained elements.
|
||||
static node_ptr reverse(node_ptr p)
|
||||
{
|
||||
if(!p) return 0;
|
||||
node_ptr i = NodeTraits::get_next(p);
|
||||
node_ptr first(p);
|
||||
while(i){
|
||||
node_ptr nxti(NodeTraits::get_next(i));
|
||||
unlink_after(p);
|
||||
NodeTraits::set_next(i, first);
|
||||
first = i;
|
||||
i = nxti;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Moves the node p n positions towards the end of the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
|
||||
static node_ptr move_backwards(node_ptr p, std::size_t n)
|
||||
{
|
||||
//Null shift, or count() == 0 or 1, nothing to do
|
||||
if(!n || !p || !NodeTraits::get_next(p))
|
||||
return p;
|
||||
|
||||
node_ptr first = p;
|
||||
bool end_found = false;
|
||||
node_ptr new_last(0);
|
||||
node_ptr old_last(0);
|
||||
|
||||
//Now find the new last node according to the shift count.
|
||||
//If we find 0 before finding the new last node
|
||||
//unlink p, shortcut the search now that we know the size of the list
|
||||
//and continue.
|
||||
for(std::size_t i = 1; i <= n; ++i){
|
||||
new_last = first;
|
||||
first = NodeTraits::get_next(first);
|
||||
if(first == 0){
|
||||
//Shortcut the shift with the modulo of the size of the list
|
||||
n %= i;
|
||||
if(!n) return p;
|
||||
old_last = new_last;
|
||||
i = 0;
|
||||
//Unlink p and continue the new first node search
|
||||
first = p;
|
||||
//unlink_after(new_last);
|
||||
end_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
//If the p has not been found in the previous loop, find it
|
||||
//starting in the new first node and unlink it
|
||||
if(!end_found){
|
||||
old_last = get_previous_node(first, 0);
|
||||
}
|
||||
|
||||
//Now link p after the new last node
|
||||
NodeTraits::set_next(old_last, p);
|
||||
NodeTraits::set_next(new_last, 0);
|
||||
return first;
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
|
||||
static node_ptr move_forward(node_ptr p, std::size_t n)
|
||||
{
|
||||
//Null shift, or count() == 0 or 1, nothing to do
|
||||
if(!n || !p || !NodeTraits::get_next(p))
|
||||
return p;
|
||||
|
||||
node_ptr first = p;
|
||||
|
||||
//Iterate until p is found to know where the current last node is.
|
||||
//If the shift count is less than the size of the list, we can also obtain
|
||||
//the position of the new last node after the shift.
|
||||
node_ptr old_last(first), next_to_it, new_last(p);
|
||||
std::size_t distance = 1;
|
||||
while(!!(next_to_it = node_traits::get_next(old_last))){
|
||||
if(distance++ > n)
|
||||
new_last = node_traits::get_next(new_last);
|
||||
old_last = next_to_it;
|
||||
}
|
||||
//If the shift was bigger or equal than the size, obtain the equivalent
|
||||
//forward shifts and find the new last node.
|
||||
if(distance <= n){
|
||||
//Now find the equivalent forward shifts.
|
||||
//Shortcut the shift with the modulo of the size of the list
|
||||
std::size_t new_before_last_pos = (distance - (n % distance))% distance;
|
||||
//If the shift is a multiple of the size there is nothing to do
|
||||
if(!new_before_last_pos)
|
||||
return p;
|
||||
|
||||
for( new_last = p
|
||||
; --new_before_last_pos
|
||||
; new_last = node_traits::get_next(new_last)){
|
||||
//empty
|
||||
}
|
||||
}
|
||||
|
||||
//Get the first new node
|
||||
node_ptr new_first = node_traits::get_next(new_last);
|
||||
//Now put the old beginning after the old end
|
||||
NodeTraits::set_next(old_last, p);
|
||||
NodeTraits::set_next(new_last, 0);
|
||||
return new_first;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP
|
@@ -208,7 +208,7 @@ class list_impl
|
||||
: data_(v_traits)
|
||||
{
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
node_algorithms::init(this->get_root_node());
|
||||
node_algorithms::init_header(this->get_root_node());
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
|
||||
@@ -224,7 +224,7 @@ class list_impl
|
||||
: data_(v_traits)
|
||||
{
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
node_algorithms::init(this->get_root_node());
|
||||
node_algorithms::init_header(this->get_root_node());
|
||||
this->insert(this->end(), b, e);
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ class list_impl
|
||||
{
|
||||
node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
|
||||
node_algorithms::link_before(this->get_root_node(), to_insert);
|
||||
this->priv_size_traits().increment();
|
||||
}
|
||||
@@ -277,7 +277,7 @@ class list_impl
|
||||
{
|
||||
node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
|
||||
node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert);
|
||||
this->priv_size_traits().increment();
|
||||
}
|
||||
@@ -569,21 +569,7 @@ class list_impl
|
||||
//!
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void shift_backwards(size_type n = 1)
|
||||
{
|
||||
//Null shift, nothing to do
|
||||
if(!n) return;
|
||||
node_ptr root = this->get_root_node();
|
||||
node_ptr last = node_traits::get_previous(root);
|
||||
//size() == 0 or 1, nothing to do
|
||||
if(last == node_traits::get_next(root)) return;
|
||||
|
||||
node_algorithms::unlink(root);
|
||||
//Now get the new last node
|
||||
while(n--){
|
||||
last = node_traits::get_previous(last);
|
||||
}
|
||||
node_algorithms::link_after(last, root);
|
||||
}
|
||||
{ node_algorithms::move_forward(this->get_root_node(), n); }
|
||||
|
||||
//! <b>Effects</b>: Moves forward all the elements, so that the second
|
||||
//! element becomes the first, the third becomes the second...
|
||||
@@ -595,20 +581,7 @@ class list_impl
|
||||
//!
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void shift_forward(size_type n = 1)
|
||||
{
|
||||
//Null shift, nothing to do
|
||||
if(!n) return;
|
||||
node_ptr root = this->get_root_node();
|
||||
node_ptr first = node_traits::get_next(root);
|
||||
//size() == 0 or 1, nothing to do
|
||||
if(first == node_traits::get_previous(root)) return;
|
||||
node_algorithms::unlink(root);
|
||||
//Now get the new first node
|
||||
while(n--){
|
||||
first = node_traits::get_next(first);
|
||||
}
|
||||
node_algorithms::link_before(first, root);
|
||||
}
|
||||
{ node_algorithms::move_backwards(this->get_root_node(), n); }
|
||||
|
||||
//! <b>Effects</b>: Erases the element pointed by i of the list.
|
||||
//! No destructors are called.
|
||||
@@ -729,7 +702,7 @@ class list_impl
|
||||
this->erase(this->begin(), this->end());
|
||||
}
|
||||
else{
|
||||
node_algorithms::init(this->get_root_node());
|
||||
node_algorithms::init_header(this->get_root_node());
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
}
|
||||
}
|
||||
@@ -794,7 +767,7 @@ class list_impl
|
||||
{
|
||||
node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
|
||||
node_algorithms::link_before(p.pointed_node(), to_insert);
|
||||
this->priv_size_traits().increment();
|
||||
return iterator(to_insert, this);
|
||||
@@ -1234,7 +1207,7 @@ class list_impl
|
||||
static iterator s_iterator_to(reference value)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!stateful_value_traits));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(value)));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value)));
|
||||
return iterator(real_value_traits::to_node_ptr(value), 0);
|
||||
}
|
||||
|
||||
@@ -1252,7 +1225,7 @@ class list_impl
|
||||
static const_iterator s_iterator_to(const_reference value)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!stateful_value_traits));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator(real_value_traits::to_node_ptr(const_cast<reference> (value)), 0);
|
||||
}
|
||||
|
||||
@@ -1267,7 +1240,7 @@ class list_impl
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
iterator iterator_to(reference value)
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(value)));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value)));
|
||||
return iterator(real_value_traits::to_node_ptr(value), this);
|
||||
}
|
||||
|
||||
@@ -1282,7 +1255,7 @@ class list_impl
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
const_iterator iterator_to(const_reference value) const
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator(real_value_traits::to_node_ptr(const_cast<reference> (value)), this);
|
||||
}
|
||||
|
||||
|
@@ -318,10 +318,8 @@ struct tag
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the type of
|
||||
//!a void pointer. This will instruct the hook
|
||||
//!to use this type of pointer instead of the
|
||||
//!default one
|
||||
//!This option setter specifies the link mode
|
||||
//!(normal_link, safe_link or auto_unlink)
|
||||
template<link_mode_type LinkType>
|
||||
struct link_mode
|
||||
{
|
||||
@@ -334,10 +332,8 @@ struct link_mode
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the type of
|
||||
//!a void pointer. This will instruct the hook
|
||||
//!to use this type of pointer instead of the
|
||||
//!default one
|
||||
//!This option setter specifies if the hook
|
||||
//!should be optimized for size instead of for speed.
|
||||
template<bool Enabled>
|
||||
struct optimize_size
|
||||
{
|
||||
@@ -350,6 +346,20 @@ struct optimize_size
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies if the list container should
|
||||
//!use a linear implementation instead of a circular one.
|
||||
template<bool Enabled>
|
||||
struct linear
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool linear = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This option setter specifies the bucket traits
|
||||
//!class for unordered associative containers. When this option is specified,
|
||||
//!instead of using the default bucket traits, a user defined holder will be defined
|
||||
@@ -475,6 +485,7 @@ struct hook_defaults
|
||||
, tag<default_tag>
|
||||
, optimize_size<false>
|
||||
, store_hash<false>
|
||||
, linear<false>
|
||||
>::type
|
||||
{};
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/slist_hook.hpp>
|
||||
#include <boost/intrusive/circular_slist_algorithms.hpp>
|
||||
#include <boost/intrusive/linear_slist_algorithms.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
@@ -46,12 +47,13 @@ template <class T>
|
||||
struct get_default_slist_hook
|
||||
{ typedef typename T::default_slist_hook type; };
|
||||
|
||||
template <class ValueTraits, class SizeType, bool ConstantTimeSize>
|
||||
template <class ValueTraits, class SizeType, bool ConstantTimeSize, bool Linear>
|
||||
struct slistopt
|
||||
{
|
||||
typedef ValueTraits value_traits;
|
||||
typedef SizeType size_type;
|
||||
static const bool constant_time_size = ConstantTimeSize;
|
||||
static const bool linear = Linear;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -66,6 +68,7 @@ struct slist_defaults
|
||||
>::type
|
||||
>
|
||||
, constant_time_size<true>
|
||||
, linear<false>
|
||||
, size_type<std::size_t>
|
||||
>::type
|
||||
{};
|
||||
@@ -129,10 +132,15 @@ class slist_impl
|
||||
<pointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, const node>::type const_node_ptr;
|
||||
typedef circular_slist_algorithms<node_traits> node_algorithms;
|
||||
typedef typename detail::if_c
|
||||
< Config::linear
|
||||
, linear_slist_algorithms<node_traits>
|
||||
, circular_slist_algorithms<node_traits>
|
||||
>::type node_algorithms;
|
||||
|
||||
static const bool constant_time_size = Config::constant_time_size;
|
||||
static const bool stateful_value_traits = detail::store_cont_ptr_on_it<slist_impl>::value;
|
||||
static const bool linear = Config::linear;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
@@ -152,6 +160,8 @@ class slist_impl
|
||||
|
||||
//Constant-time size is incompatible with auto-unlink hooks!
|
||||
BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink)));
|
||||
//Linear singly linked lists are incompatible with auto-unlink hooks!
|
||||
BOOST_STATIC_ASSERT(!(linear && ((int)real_value_traits::link_mode == (int)auto_unlink)));
|
||||
|
||||
node_ptr get_root_node()
|
||||
{ return node_ptr(&data_.root_plus_size_.root_); }
|
||||
@@ -220,7 +230,7 @@ class slist_impl
|
||||
: data_(v_traits)
|
||||
{
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
node_algorithms::init(this->get_root_node());
|
||||
node_algorithms::init_header(this->get_root_node());
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
|
||||
@@ -236,7 +246,7 @@ class slist_impl
|
||||
: data_(v_traits)
|
||||
{
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
node_algorithms::init(this->get_root_node());
|
||||
node_algorithms::init_header(this->get_root_node());
|
||||
insert_after(before_begin(), b, e);
|
||||
}
|
||||
|
||||
@@ -266,7 +276,7 @@ class slist_impl
|
||||
this->erase_after(this->before_begin(), this->end());
|
||||
}
|
||||
else{
|
||||
node_algorithms::init(this->get_root_node());
|
||||
node_algorithms::init_header(this->get_root_node());
|
||||
this->priv_size_traits().set_size(size_type(0));
|
||||
}
|
||||
}
|
||||
@@ -299,7 +309,7 @@ class slist_impl
|
||||
{
|
||||
node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
|
||||
node_algorithms::link_after(this->get_root_node(), to_insert);
|
||||
this->priv_size_traits().increment();
|
||||
}
|
||||
@@ -385,7 +395,7 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
iterator end()
|
||||
{ return iterator (this->get_root_node(), this); }
|
||||
{ return iterator (linear ? 0 : this->get_root_node(), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
|
||||
//!
|
||||
@@ -393,7 +403,7 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator end() const
|
||||
{ return const_iterator (uncast(this->get_root_node()), this); }
|
||||
{ return const_iterator (linear ? 0 : uncast(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
|
||||
//!
|
||||
@@ -401,7 +411,7 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator cend() const
|
||||
{ return const_iterator (uncast(this->get_root_node()), this); }
|
||||
{ return this->end(); }
|
||||
|
||||
//! <b>Effects</b>: Returns an iterator that points to a position
|
||||
//! before the first element. Equivalent to "end()"
|
||||
@@ -410,7 +420,7 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
iterator before_begin()
|
||||
{ return end(); }
|
||||
{ return iterator(this->get_root_node(), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns an iterator that points to a position
|
||||
//! before the first element. Equivalent to "end()"
|
||||
@@ -419,7 +429,7 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator before_begin() const
|
||||
{ return end(); }
|
||||
{ return const_iterator(uncast(this->get_root_node()), this); }
|
||||
|
||||
//! <b>Effects</b>: Returns an iterator that points to a position
|
||||
//! before the first element. Equivalent to "end()"
|
||||
@@ -428,7 +438,7 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant.
|
||||
const_iterator cbefore_begin() const
|
||||
{ return end(); }
|
||||
{ return this->before_begin(); }
|
||||
|
||||
//! <b>Precondition</b>: end_iterator must be a valid end iterator
|
||||
//! of slist.
|
||||
@@ -487,7 +497,7 @@ class slist_impl
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void swap(slist_impl& other)
|
||||
{
|
||||
node_algorithms::swap_nodes(this->get_root_node(), other.get_root_node());
|
||||
priv_swap_lists(this->get_root_node(), other.get_root_node(), detail::bool_<linear>());
|
||||
if(constant_time_size){
|
||||
size_type backup = this->priv_size_traits().get_size();
|
||||
this->priv_size_traits().set_size(other.priv_size_traits().get_size());
|
||||
@@ -506,43 +516,7 @@ class slist_impl
|
||||
//! <b>Note</b>: Iterators Does not affect the validity of iterators and references.
|
||||
void shift_backwards(size_type n = 1)
|
||||
{
|
||||
//Null shift, nothing to do
|
||||
if(!n) return;
|
||||
node_ptr root = this->get_root_node();
|
||||
node_ptr first = node_traits::get_next(root);
|
||||
|
||||
//size() == 0 or 1, nothing to do
|
||||
if(node_traits::get_next(first) == root) return;
|
||||
|
||||
//Iterate until the root node is found to know where the current last node is.
|
||||
//If the shift count is less than the size of the list, we can also obtain
|
||||
//the position of the new last node after the shift.
|
||||
node_ptr old_last(first), next_to_it, new_last(root);
|
||||
size_type distance = 1;
|
||||
while(root != (next_to_it = node_traits::get_next(old_last))){
|
||||
if(++distance > n)
|
||||
new_last = node_traits::get_next(new_last);
|
||||
old_last = next_to_it;
|
||||
}
|
||||
//If the shift was bigger or equal than the size, obtain the equivalent
|
||||
//forward shifts and find the new last node.
|
||||
if(distance <= n){
|
||||
//Now find the equivalent forward shifts.
|
||||
//Shorcut the shift with the modulo of the size of the list
|
||||
size_type new_before_last_pos = (distance - (n % distance))% distance;
|
||||
//If the shift is a multiple of the size there is nothing to do
|
||||
if(!new_before_last_pos) return;
|
||||
|
||||
for( new_last = root
|
||||
; new_before_last_pos--
|
||||
; new_last = node_traits::get_next(new_last)){
|
||||
//empty
|
||||
}
|
||||
}
|
||||
|
||||
//Now unlink the root node and link it after the new last node
|
||||
node_algorithms::unlink_after(old_last);
|
||||
node_algorithms::link_after(new_last, root);
|
||||
priv_shift_backwards(n, detail::bool_<linear>());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Moves forward all the elements, so that the second
|
||||
@@ -556,43 +530,7 @@ class slist_impl
|
||||
//! <b>Note</b>: Does not affect the validity of iterators and references.
|
||||
void shift_forward(size_type n = 1)
|
||||
{
|
||||
//Null shift, nothing to do
|
||||
if(!n) return;
|
||||
node_ptr root = this->get_root_node();
|
||||
node_ptr first = node_traits::get_next(root);
|
||||
|
||||
//size() == 0 or 1, nothing to do
|
||||
if(node_traits::get_next(first) == root) return;
|
||||
|
||||
bool end_found = false;
|
||||
node_ptr new_last(0);
|
||||
|
||||
//Now find the new last node according to the shift count.
|
||||
//If we find the root node before finding the new last node
|
||||
//unlink the root, shortcut the search now that we know the size of the list
|
||||
//and continue.
|
||||
for(size_type i = 1; i <= n; ++i){
|
||||
new_last = first;
|
||||
first = node_traits::get_next(first);
|
||||
if(first == root){
|
||||
//Shorcut the shift with the modulo of the size of the list
|
||||
n %= i;
|
||||
i = 0;
|
||||
//Unlink the root node and continue the new first node search
|
||||
first = node_traits::get_next(first);
|
||||
node_algorithms::unlink_after(new_last);
|
||||
end_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
//If the root node has not been found in the previous loop, find it
|
||||
//starting in the new first node and unlink it
|
||||
if(!end_found){
|
||||
node_algorithms::unlink_after(node_algorithms::get_previous_node(first, root));
|
||||
}
|
||||
|
||||
//Now link the root node after the new last node
|
||||
node_algorithms::link_after(new_last, root);
|
||||
priv_shift_forward(n, detail::bool_<linear>());
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
||||
@@ -643,7 +581,7 @@ class slist_impl
|
||||
{
|
||||
node_ptr n = get_real_value_traits().to_node_ptr(value);
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n));
|
||||
node_algorithms::link_after(prev_p.pointed_node(), n);
|
||||
this->priv_size_traits().increment();
|
||||
return iterator (n, this);
|
||||
@@ -712,16 +650,7 @@ class slist_impl
|
||||
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
||||
//! erased element.
|
||||
iterator erase_after(iterator prev)
|
||||
{
|
||||
iterator it(prev); ++it;
|
||||
node_ptr to_erase(it.pointed_node());
|
||||
node_algorithms::unlink_after(prev.pointed_node());
|
||||
this->priv_size_traits().decrement();
|
||||
iterator ret(++prev);
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
return ret;
|
||||
}
|
||||
{ return this->erase_after_and_dispose(prev, detail::null_disposer()); }
|
||||
|
||||
//! <b>Effects</b>: Erases the range (before_first, last) from
|
||||
//! the list. No destructors are called.
|
||||
@@ -731,18 +660,12 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Lineal to the elements (last - before_first).
|
||||
//! <b>Complexity</b>: Lineal to the elements (last - before_first + 1).
|
||||
//!
|
||||
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
||||
//! erased element.
|
||||
iterator erase_after(iterator before_first, iterator last)
|
||||
{
|
||||
iterator first;
|
||||
while(++(first = before_first) != last){
|
||||
this->erase_after(before_first);
|
||||
}
|
||||
return last;
|
||||
}
|
||||
{ return this->erase_after_and_dispose(before_first, last, detail::null_disposer()); }
|
||||
|
||||
//! <b>Effects</b>: Erases the element pointed by i of the list.
|
||||
//! No destructors are called.
|
||||
@@ -794,11 +717,16 @@ class slist_impl
|
||||
template<class Disposer>
|
||||
iterator erase_after_and_dispose(iterator prev, Disposer disposer)
|
||||
{
|
||||
iterator it(prev); ++it;
|
||||
iterator it(prev);
|
||||
++it;
|
||||
node_ptr to_erase(it.pointed_node());
|
||||
iterator ret(this->erase_after(prev));
|
||||
++it;
|
||||
node_algorithms::unlink_after(prev.pointed_node());
|
||||
this->priv_size_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
node_algorithms::init(to_erase);
|
||||
disposer(get_real_value_traits().to_value_ptr(to_erase));
|
||||
return ret;
|
||||
return it;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
||||
@@ -818,9 +746,10 @@ class slist_impl
|
||||
template<class Disposer>
|
||||
iterator erase_after_and_dispose(iterator before_first, iterator last, Disposer disposer)
|
||||
{
|
||||
iterator first;
|
||||
while(++(first = before_first) != last){
|
||||
this->erase_after_and_dispose(before_first, disposer);
|
||||
iterator next(before_first);
|
||||
++next;
|
||||
while(next != last){
|
||||
next = this->erase_after_and_dispose(before_first, disposer);
|
||||
}
|
||||
return last;
|
||||
}
|
||||
@@ -931,7 +860,7 @@ class slist_impl
|
||||
iterator last_x(x.previous(x.end()));
|
||||
node_algorithms::transfer_after
|
||||
( prev.pointed_node()
|
||||
, x.end().pointed_node()
|
||||
, x.before_begin().pointed_node()
|
||||
, last_x.pointed_node());
|
||||
this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size());
|
||||
x.priv_size_traits().set_size(size_type(0));
|
||||
@@ -1133,12 +1062,12 @@ class slist_impl
|
||||
(last_inserted.pointed_node(), carry.end().pointed_node());
|
||||
iterator last_element(p, this);
|
||||
if(constant_time_size){
|
||||
counter[i].splice_after( counter[i].end(), carry
|
||||
counter[i].splice_after( counter[i].before_begin(), carry
|
||||
, carry.before_begin(), last_element
|
||||
, carry.size());
|
||||
}
|
||||
else{
|
||||
counter[i].splice_after( counter[i].end(), carry
|
||||
counter[i].splice_after( counter[i].before_begin(), carry
|
||||
, carry.before_begin(), last_element);
|
||||
}
|
||||
if(i == fill)
|
||||
@@ -1153,11 +1082,11 @@ class slist_impl
|
||||
(last_inserted.pointed_node(), counter[--fill].end().pointed_node());
|
||||
iterator last_element(p, this);
|
||||
if(constant_time_size){
|
||||
this->splice_after( end(), counter[fill], counter[fill].before_begin()
|
||||
this->splice_after( before_begin(), counter[fill], counter[fill].before_begin()
|
||||
, last_element, counter[fill].size());
|
||||
}
|
||||
else{
|
||||
this->splice_after( end(), counter[fill], counter[fill].before_begin()
|
||||
this->splice_after( before_begin(), counter[fill], counter[fill].before_begin()
|
||||
, last_element);
|
||||
}
|
||||
}
|
||||
@@ -1201,14 +1130,14 @@ class slist_impl
|
||||
template<class Predicate>
|
||||
iterator merge(slist_impl& x, Predicate p)
|
||||
{
|
||||
iterator a(before_begin()), e(end()), ax(x.before_begin());
|
||||
iterator a(before_begin()), e(end()), ax(x.before_begin()), ex(x.end());
|
||||
iterator last_inserted(e);
|
||||
iterator a_next;
|
||||
while(++(a_next = a) != e && !x.empty()) {
|
||||
iterator ix(ax);
|
||||
iterator cx;
|
||||
size_type n(0);
|
||||
while(++(cx = ix) != ax && p(*cx, *a_next)){
|
||||
while(++(cx = ix) != ex && p(*cx, *a_next)){
|
||||
++ix; ++n;
|
||||
}
|
||||
if(ax != ix){
|
||||
@@ -1235,7 +1164,7 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated
|
||||
void merge(slist_impl& x)
|
||||
{ this->merge(x, std::less<value_type>()); }
|
||||
{ this->merge(x, std::less<value_type>()); }
|
||||
|
||||
//! <b>Effects</b>: Reverses the order of elements in the list.
|
||||
//!
|
||||
@@ -1245,7 +1174,7 @@ class slist_impl
|
||||
//!
|
||||
//! <b>Note</b>: Iterators and references are not invalidated
|
||||
void reverse()
|
||||
{ node_algorithms::reverse(this->get_root_node()); }
|
||||
{ priv_reverse(detail::bool_<linear>()); }
|
||||
|
||||
//! <b>Effects</b>: Removes all the elements that compare equal to value.
|
||||
//! No destructors are called.
|
||||
@@ -1406,7 +1335,7 @@ class slist_impl
|
||||
static iterator s_iterator_to(reference value)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!stateful_value_traits));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(value_traits::to_node_ptr(value)));
|
||||
//BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value)));
|
||||
return iterator (value_traits::to_node_ptr(value), 0);
|
||||
}
|
||||
|
||||
@@ -1424,7 +1353,7 @@ class slist_impl
|
||||
static const_iterator s_iterator_to(const_reference value)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!stateful_value_traits));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
//BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator (value_traits::to_node_ptr(const_cast<reference> (value)), 0);
|
||||
}
|
||||
|
||||
@@ -1439,7 +1368,7 @@ class slist_impl
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
iterator iterator_to(reference value)
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(value_traits::to_node_ptr(value)));
|
||||
//BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value)));
|
||||
return iterator (value_traits::to_node_ptr(value), this);
|
||||
}
|
||||
|
||||
@@ -1454,7 +1383,7 @@ class slist_impl
|
||||
//! <b>Note</b>: Iterators and references are not invalidated.
|
||||
const_iterator iterator_to(const_reference value) const
|
||||
{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::unique(value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
//BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast<reference> (value))));
|
||||
return const_iterator (value_traits::to_node_ptr(const_cast<reference> (value)), this);
|
||||
}
|
||||
|
||||
@@ -1487,8 +1416,54 @@ class slist_impl
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void priv_reverse(detail::bool_<false>)
|
||||
{ node_algorithms::reverse(this->get_root_node()); }
|
||||
|
||||
void priv_reverse(detail::bool_<true>)
|
||||
{
|
||||
node_ptr new_first = node_algorithms::reverse
|
||||
(node_traits::get_next(this->get_root_node()));
|
||||
node_traits::set_next(this->get_root_node(), new_first);
|
||||
}
|
||||
|
||||
void priv_shift_backwards(size_type n, detail::bool_<false>)
|
||||
{
|
||||
node_algorithms::move_forward(this->get_root_node(), (std::size_t)n);
|
||||
}
|
||||
|
||||
void priv_shift_backwards(size_type n, detail::bool_<true>)
|
||||
{
|
||||
node_ptr new_first = node_algorithms::move_forward
|
||||
(node_traits::get_next(this->get_root_node()), (std::size_t)n);
|
||||
node_traits::set_next(this->get_root_node(), new_first);
|
||||
}
|
||||
|
||||
void priv_shift_forward(size_type n, detail::bool_<false>)
|
||||
{
|
||||
node_algorithms::move_backwards(this->get_root_node(), (std::size_t)n);
|
||||
}
|
||||
|
||||
void priv_shift_forward(size_type n, detail::bool_<true>)
|
||||
{
|
||||
node_ptr new_first = node_algorithms::move_backwards
|
||||
(node_traits::get_next(this->get_root_node()), (std::size_t)n);
|
||||
node_traits::set_next(this->get_root_node(), new_first);
|
||||
}
|
||||
|
||||
//circular version
|
||||
static void priv_swap_lists(node_ptr this_node, node_ptr other_node, detail::bool_<false>)
|
||||
{ node_algorithms::swap_nodes(this_node, other_node); }
|
||||
|
||||
//linear version
|
||||
static void priv_swap_lists(node_ptr this_node, node_ptr other_node, detail::bool_<true>)
|
||||
{ node_algorithms::swap_trailing_nodes(this_node, other_node); }
|
||||
|
||||
static slist_impl &priv_container_from_end_iterator(const const_iterator &end_iterator)
|
||||
{
|
||||
//Obtaining the container from the end iterator is not possible with linear
|
||||
//singly linked lists (because "end" is represented by the null pointer)
|
||||
BOOST_STATIC_ASSERT(!linear);
|
||||
root_plus_size *r = detail::parent_from_member<root_plus_size, node>
|
||||
( detail::get_pointer(end_iterator.pointed_node()), &root_plus_size::root_);
|
||||
data_t *d = detail::parent_from_member<data_t, root_plus_size>
|
||||
@@ -1620,13 +1595,13 @@ inline void swap
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class ...Options>
|
||||
#else
|
||||
template<class T, class O1 = none, class O2 = none, class O3 = none>
|
||||
template<class T, class O1 = none, class O2 = none, class O3 = none, class O4 = none>
|
||||
#endif
|
||||
struct make_slist
|
||||
{
|
||||
/// @cond
|
||||
typedef typename pack_options
|
||||
< slist_defaults<T>, O1, O2, O3>::type packed_options;
|
||||
< slist_defaults<T>, O1, O2, O3, O4>::type packed_options;
|
||||
typedef typename detail::get_value_traits
|
||||
<T, typename packed_options::value_traits>::type value_traits;
|
||||
typedef slist_impl
|
||||
@@ -1635,6 +1610,7 @@ struct make_slist
|
||||
< value_traits
|
||||
, typename packed_options::size_type
|
||||
, packed_options::constant_time_size
|
||||
, packed_options::linear
|
||||
>
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
@@ -1643,12 +1619,12 @@ struct make_slist
|
||||
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
template<class T, class O1, class O2, class O3>
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
class slist
|
||||
: public make_slist<T, O1, O2, O3>::type
|
||||
: public make_slist<T, O1, O2, O3, O4>::type
|
||||
{
|
||||
typedef typename make_slist
|
||||
<T, O1, O2, O3>::type Base;
|
||||
<T, O1, O2, O3, O4>::type Base;
|
||||
typedef typename Base::real_value_traits real_value_traits;
|
||||
//Assert if passed value traits are compatible with the type
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/slist_node.hpp>
|
||||
#include <boost/intrusive/circular_slist_algorithms.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/intrusive/detail/generic_hook.hpp>
|
||||
|
||||
@@ -31,6 +32,7 @@ struct get_slist_node_algo
|
||||
{
|
||||
typedef circular_slist_algorithms<slist_node_traits<VoidPointer> > type;
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
//! Helper metafunction to define a \c slist_base_hook that yields to the same
|
||||
|
@@ -135,6 +135,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\intrusive_fwd.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\linear_slist_algorithms.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\link_mode.hpp">
|
||||
</File>
|
||||
|
@@ -63,14 +63,6 @@ void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_ty
|
||||
test_swap(values);
|
||||
test_clone(values);
|
||||
test_container_from_end(values);
|
||||
/*
|
||||
const char *list_name = typeid(list_type).name();
|
||||
std::cout << list_name << std::endl << strlen(list_name) << std::endl;
|
||||
const char *value_t = typeid(typename list_type::value_traits).name();
|
||||
std::cout << value_t << std::endl << strlen(value_t) << std::endl;
|
||||
const char *list_it_name = typeid(typename list_type::iterator).name();
|
||||
std::cout << list_it_name << std::endl << strlen(list_it_name ) << std::endl;
|
||||
*/
|
||||
}
|
||||
|
||||
//test: push_front, pop_front, push_back, pop_back, front, back, size, empty:
|
||||
@@ -194,26 +186,29 @@ void test_list<ValueTraits>
|
||||
const int num_values = (int)values.size();
|
||||
std::vector<int> expected_values(num_values);
|
||||
|
||||
//Shift forward all possible positions 3 times
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
testlist.assign(values.begin(), values.end());
|
||||
testlist.shift_forward(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + num_values - i%num_values) % num_values] = (j + 1);
|
||||
for(int s = 1; s <= num_values; ++s){
|
||||
expected_values.resize(s);
|
||||
//Shift forward all possible positions 3 times
|
||||
for(int i = 0; i < s*3; ++i){
|
||||
testlist.insert(testlist.begin(), &values[0], &values[0] + s);
|
||||
testlist.shift_forward(i);
|
||||
for(int j = 0; j < s; ++j){
|
||||
expected_values[(j + s - i%s) % s] = (j + 1);
|
||||
}
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
|
||||
testlist.clear();
|
||||
}
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
|
||||
testlist.clear();
|
||||
}
|
||||
|
||||
//Shift backwards all possible positions
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
testlist.assign(values.begin(), values.end());
|
||||
testlist.shift_backwards(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + i) % num_values] = (j + 1);
|
||||
//Shift backwards all possible positions
|
||||
for(int i = 0; i < s*3; ++i){
|
||||
testlist.insert(testlist.begin(), &values[0], &values[0] + s);
|
||||
testlist.shift_backwards(i);
|
||||
for(int j = 0; j < s; ++j){
|
||||
expected_values[(j + i) % s] = (j + 1);
|
||||
}
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
|
||||
testlist.clear();
|
||||
}
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
|
||||
testlist.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +273,28 @@ void test_list<ValueTraits>
|
||||
{ int init_values [] = { 4, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
}
|
||||
{
|
||||
list_type testlist1 (&values[0], &values[1]);
|
||||
|
||||
{ int init_values [] = { 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
values[1].swap_nodes(values[2]);
|
||||
|
||||
{ int init_values [] = { 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
values[0].swap_nodes(values[2]);
|
||||
|
||||
{ int init_values [] = { 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
values[0].swap_nodes(values[2]);
|
||||
|
||||
{ int init_values [] = { 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
|
@@ -24,7 +24,7 @@
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
template<class ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
struct test_slist
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -37,11 +37,12 @@ struct test_slist
|
||||
static void test_swap(std::vector<value_type>& values);
|
||||
static void test_slow_insert (std::vector<value_type>& values);
|
||||
static void test_clone (std::vector<value_type>& values);
|
||||
static void test_container_from_end(std::vector<value_type> &values);
|
||||
static void test_container_from_end(std::vector<value_type> &, detail::bool_<true>){}
|
||||
static void test_container_from_end(std::vector<value_type> &values, detail::bool_<false>);
|
||||
};
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -50,6 +51,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
{
|
||||
list_type list(values.begin(), values.end());
|
||||
@@ -66,12 +68,12 @@ void test_slist<ValueTraits>
|
||||
test_slow_insert (values);
|
||||
test_swap(values);
|
||||
test_clone(values);
|
||||
test_container_from_end(values);
|
||||
test_container_from_end(values, detail::bool_<Linear>());
|
||||
}
|
||||
|
||||
//test: push_front, pop_front, front, size, empty:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_front_back (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -80,6 +82,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
BOOST_TEST (testlist.empty());
|
||||
@@ -101,8 +104,8 @@ void test_slist<ValueTraits>
|
||||
}
|
||||
|
||||
//test: merge due to error in merge implementation:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_merge (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -111,6 +114,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
list_type testlist1, testlist2;
|
||||
testlist1.push_front (values[0]);
|
||||
@@ -124,8 +128,8 @@ void test_slist<ValueTraits>
|
||||
}
|
||||
|
||||
//test: constructor, iterator, sort, reverse:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -134,6 +138,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
list_type testlist (values.begin(), values.end());
|
||||
|
||||
@@ -145,13 +150,13 @@ void test_slist<ValueTraits>
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
|
||||
testlist.reverse();
|
||||
{ int init_values [] = { 5, 3, 1, 4, 2, };
|
||||
{ int init_values [] = { 5, 3, 1, 4, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
}
|
||||
|
||||
//test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -160,6 +165,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
testlist.assign (&values[0] + 2, &values[0] + 5);
|
||||
@@ -189,8 +195,8 @@ void test_slist<ValueTraits>
|
||||
}
|
||||
|
||||
//test: insert, const_iterator, erase, siterator_to:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_slow_insert (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -199,6 +205,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
testlist.push_front (values[4]);
|
||||
@@ -232,8 +239,8 @@ void test_slist<ValueTraits>
|
||||
BOOST_TEST (testlist.front().value_ == 3);
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_shift(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -242,6 +249,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
|
||||
@@ -249,33 +257,36 @@ void test_slist<ValueTraits>
|
||||
std::vector<int> expected_values(num_values);
|
||||
|
||||
//Shift forward all possible positions 3 times
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
testlist.assign(values.begin(), values.end());
|
||||
testlist.shift_forward(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + num_values - i%num_values) % num_values] = (j + 1);
|
||||
for(int s = 1; s <= num_values; ++s){
|
||||
expected_values.resize(s);
|
||||
for(int i = 0; i < s*3; ++i){
|
||||
testlist.insert_after(testlist.before_begin(), &values[0], &values[0] + s);
|
||||
testlist.shift_forward(i);
|
||||
for(int j = 0; j < s; ++j){
|
||||
expected_values[(j + s - i%s) % s] = (j + 1);
|
||||
}
|
||||
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
|
||||
testlist.clear();
|
||||
}
|
||||
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
|
||||
testlist.clear();
|
||||
}
|
||||
//Shift backwards all possible positions
|
||||
for(int i = 0; i < s*3; ++i){
|
||||
testlist.insert_after(testlist.before_begin(), &values[0], &values[0] + s);
|
||||
testlist.shift_backwards(i);
|
||||
for(int j = 0; j < s; ++j){
|
||||
expected_values[(j + i) % s] = (j + 1);
|
||||
}
|
||||
|
||||
//Shift backwards all possible positions
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
testlist.assign(values.begin(), values.end());
|
||||
testlist.shift_backwards(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + i) % num_values] = (j + 1);
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
|
||||
testlist.clear();
|
||||
}
|
||||
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
|
||||
testlist.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//test: insert_after (seq-version), swap, splice_after:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -284,11 +295,12 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
{
|
||||
list_type testlist1 (&values[0], &values[0] + 2);
|
||||
list_type testlist2;
|
||||
testlist2.insert_after (testlist2.end(), &values[0] + 2, &values[0] + 5);
|
||||
testlist2.insert_after (testlist2.before_begin(), &values[0] + 2, &values[0] + 5);
|
||||
testlist1.swap(testlist2);
|
||||
{ int init_values [] = { 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
@@ -299,19 +311,20 @@ void test_slist<ValueTraits>
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
BOOST_TEST (testlist1.empty());
|
||||
|
||||
testlist1.splice_after (testlist1.end(), testlist2, ++testlist2.begin());
|
||||
testlist1.splice_after (testlist1.before_begin(), testlist2, ++testlist2.begin());
|
||||
{ int init_values [] = { 4 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 1, 3, 5, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
|
||||
testlist1.splice_after (testlist1.begin(), testlist2,
|
||||
testlist2.end(), ++++testlist2.begin());
|
||||
testlist2.before_begin(), ++++testlist2.begin());
|
||||
{ int init_values [] = { 4, 1, 3, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
}
|
||||
if(!list_type::linear)
|
||||
{
|
||||
list_type testlist1 (&values[0], &values[0] + 2);
|
||||
list_type testlist2 (&values[0] + 3, &values[0] + 5);
|
||||
@@ -326,10 +339,32 @@ void test_slist<ValueTraits>
|
||||
{ int init_values [] = { 4, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
}
|
||||
if(!list_type::linear)
|
||||
{
|
||||
list_type testlist1 (&values[0], &values[1]);
|
||||
|
||||
{ int init_values [] = { 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
values[1].swap_nodes(values[2]);
|
||||
|
||||
{ int init_values [] = { 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
values[0].swap_nodes(values[2]);
|
||||
|
||||
{ int init_values [] = { 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
values[0].swap_nodes(values[2]);
|
||||
|
||||
{ int init_values [] = { 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
@@ -338,6 +373,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
@@ -349,9 +385,10 @@ void test_slist<ValueTraits>
|
||||
BOOST_TEST (testlist2.empty());
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
|
||||
template<class ValueTraits, bool Linear>
|
||||
void test_slist<ValueTraits, Linear>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values
|
||||
,detail::bool_<false>)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
@@ -359,6 +396,7 @@ void test_slist<ValueTraits>
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
, linear<Linear>
|
||||
> list_type;
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
|
||||
@@ -380,6 +418,7 @@ class test_main_template
|
||||
< value_type
|
||||
, typename value_type::slist_base_hook_t
|
||||
>::type
|
||||
, false
|
||||
>::test_all(data);
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
@@ -388,6 +427,25 @@ class test_main_template
|
||||
, &value_type::slist_node_
|
||||
>
|
||||
>::type
|
||||
, false
|
||||
>::test_all(data);
|
||||
|
||||
//Now linear slists
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_base_hook_t
|
||||
>::type
|
||||
, true
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::slist_member_hook_t
|
||||
, &value_type::slist_node_
|
||||
>
|
||||
>::type
|
||||
, true
|
||||
>::test_all(data);
|
||||
|
||||
return 0;
|
||||
@@ -409,6 +467,7 @@ class test_main_template<VoidPointer, false>
|
||||
< value_type
|
||||
, typename value_type::slist_base_hook_t
|
||||
>::type
|
||||
, false
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
@@ -418,12 +477,14 @@ class test_main_template<VoidPointer, false>
|
||||
, &value_type::slist_node_
|
||||
>
|
||||
>::type
|
||||
, false
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_auto_base_hook_t
|
||||
>::type
|
||||
, false
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
@@ -433,6 +494,24 @@ class test_main_template<VoidPointer, false>
|
||||
, &value_type::slist_auto_node_
|
||||
>
|
||||
>::type
|
||||
, false
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_base_hook_t
|
||||
>::type
|
||||
, true
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::slist_member_hook_t
|
||||
, &value_type::slist_node_
|
||||
>
|
||||
>::type
|
||||
, true
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user