diff --git a/doc/html/reference.css b/doc/html/reference.css
index be4e64c..956d7da 100644
--- a/doc/html/reference.css
+++ b/doc/html/reference.css
@@ -1,3 +1,11 @@
+/*=============================================================================
+ Copyright (c) 2004 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
PRE.synopsis {
background-color: #e0ffff;
border: thin solid blue;
diff --git a/example/doc_list_algorithms.cpp b/example/doc_list_algorithms.cpp
index 0d1277d..7b4fc89 100644
--- a/example/doc_list_algorithms.cpp
+++ b/example/doc_list_algorithms.cpp
@@ -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"
diff --git a/example/doc_slist_algorithms.cpp b/example/doc_slist_algorithms.cpp
index d13d333..d89b678 100644
--- a/example/doc_slist_algorithms.cpp
+++ b/example/doc_slist_algorithms.cpp
@@ -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
diff --git a/example/doc_splay_algorithms.cpp b/example/doc_splay_algorithms.cpp
index 5f929fa..80797db 100644
--- a/example/doc_splay_algorithms.cpp
+++ b/example/doc_splay_algorithms.cpp
@@ -75,5 +75,4 @@ int main()
algo::erase(&header, &three);
return 0;
}
-
-//]
\ No newline at end of file
+//]
diff --git a/include/boost/intrusive/circular_list_algorithms.hpp b/include/boost/intrusive/circular_list_algorithms.hpp
index 5e28e19..97438bf 100644
--- a/include/boost/intrusive/circular_list_algorithms.hpp
+++ b/include/boost/intrusive/circular_list_algorithms.hpp
@@ -54,6 +54,27 @@ class circular_list_algorithms
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
+ //! Effects: Constructs an non-used list element, so that
+ //! inited(this_node) == true
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void init(node_ptr this_node)
+ {
+ NodeTraits::set_next(this_node, 0);
+ NodeTraits::set_previous(this_node, 0);
+ }
+
+ //! Effects: Returns true is "this_node" is in a non-used state
+ //! as if it was initialized by the "init" function.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static bool inited(const_node_ptr this_node)
+ { return !NodeTraits::get_next(this_node); }
+
//! Effects: Constructs an empty list, making this_node the only
//! node of the circular list:
//! NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
@@ -62,11 +83,12 @@ class circular_list_algorithms
//! Complexity: Constant
//!
//! Throws: 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);
- }
+ }
+
//! Requires: this_node must be in a circular list or be an empty circular list.
//!
@@ -76,8 +98,11 @@ class circular_list_algorithms
//! Complexity: Constant
//!
//! Throws: 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;
+ }
//! Requires: this_node must be in a circular list or be an empty circular list.
//!
@@ -107,11 +132,16 @@ class circular_list_algorithms
//! Throws: 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;
+ }
}
//! Requires: b and e must be nodes of the same circular list or an empty range.
@@ -124,10 +154,9 @@ class circular_list_algorithms
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);
+ node_ptr prevb(NodeTraits::get_previous(b));
+ NodeTraits::set_previous(e, prevb);
+ NodeTraits::set_next(prevb, e);
}
}
@@ -229,6 +258,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 +278,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);
+ }
}
//! Requires: b and e must be nodes of the same circular list or an empty range.
@@ -254,8 +301,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 +355,47 @@ class circular_list_algorithms
f = n;
}
}
+
+ //! Effects: Moves the node p n positions towards the end of the list.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: 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);
+ }
+
+ //! Effects: Moves the node p n positions towards the beginning of the list.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: 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
diff --git a/include/boost/intrusive/circular_slist_algorithms.hpp b/include/boost/intrusive/circular_slist_algorithms.hpp
index 20dcafa..73e4590 100644
--- a/include/boost/intrusive/circular_slist_algorithms.hpp
+++ b/include/boost/intrusive/circular_slist_algorithms.hpp
@@ -16,6 +16,8 @@
#include
#include
+#include
+#include
#include
namespace boost {
@@ -25,7 +27,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:
//!
@@ -44,22 +46,98 @@ namespace intrusive {
//! static void set_next(node_ptr n, node_ptr next);
template
class circular_slist_algorithms
+ /// @cond
+ : public detail::common_slist_algorithms
+ /// @endcond
{
+ /// @cond
+ typedef detail::common_slist_algorithms base_t;
+ /// @endcond
public:
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
- //! Requires: this_node must be in a circular list or be an empty circular list.
+ #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+ //! Effects: Constructs an non-used list element, putting the next
+ //! pointer to null:
+ //! NodeTraits::get_next(this_node) == 0
//!
- //! Effects: Returns the previous node of this_node in the circular list.
- //!
- //! Complexity: Linear to the number of elements in the circular list.
+ //! Complexity: Constant
//!
//! Throws: Nothing.
- static node_ptr get_previous_node(node_ptr this_node)
- { return get_previous_node(this_node, this_node); }
+ static void init(node_ptr this_node);
+ //! Requires: this_node must be in a circular list or be an empty circular list.
+ //!
+ //! Effects: Returns true is "this_node" is the only node of a circular list:
+ //! or it's a not inserted node:
+ //! return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static bool unique(const_node_ptr this_node);
+
+ //! Effects: Returns true is "this_node" has the same state as
+ //! if it was inited using "init(node_ptr)"
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static bool inited(const_node_ptr this_node);
+
+ //! Requires: prev_node must be in a circular list or be an empty circular list.
+ //!
+ //! Effects: Unlinks the next node of prev_node from the circular list.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void unlink_after(node_ptr prev_node);
+
+ //! Requires: prev_node and last_node must be in a circular list
+ //! or be an empty circular list.
+ //!
+ //! Effects: Unlinks the range (prev_node, last_node) from the circular list.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void unlink_after(node_ptr prev_node, node_ptr last_node);
+
+ //! Requires: prev_node must be a node of a circular list.
+ //!
+ //! Effects: Links this_node after prev_node in the circular list.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void link_after(node_ptr prev_node, node_ptr this_node);
+
+ //! Requires: 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.
+ //!
+ //! Effects: Removes the nodes from (b, e] range from their circular list and inserts
+ //! them after p in p's circular list.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
+
+ #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+ //! Effects: Constructs an empty list, making this_node the only
+ //! node of the circular list:
+ //! NodeTraits::get_next(this_node) == this_node.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void init_header(node_ptr this_node)
+ { NodeTraits::set_next(this_node, this_node); }
//! Requires: this_node and prev_init_node must be in the same circular list.
//!
@@ -71,15 +149,17 @@ class circular_slist_algorithms
//!
//! Throws: 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;
- }
+ { return base_t::get_previous_node(prev_init_node, this_node); }
+
+ //! Requires: this_node must be in a circular list or be an empty circular list.
+ //!
+ //! Effects: Returns the previous node of this_node in the circular list.
+ //!
+ //! Complexity: Linear to the number of elements in the circular list.
+ //!
+ //! Throws: Nothing.
+ static node_ptr get_previous_node(node_ptr this_node)
+ { return base_t::get_previous_node(this_node, this_node); }
//! Requires: this_node must be in a circular list or be an empty circular list.
//!
@@ -113,28 +193,6 @@ class circular_slist_algorithms
return p;
}
- //! Effects: Constructs an empty list, making this_node the only
- //! node of the circular list:
- //! NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
- //! == this_node.
- //!
- //! Complexity: Constant
- //!
- //! Throws: Nothing.
- static void init(node_ptr this_node)
- { NodeTraits::set_next(this_node, this_node); }
-
- //! Requires: this_node must be in a circular list or be an empty circular list.
- //!
- //! Effects: Returns true is "this_node" is the only node of a circular list:
- //! return NodeTraits::get_next(this_node) == this_node
- //!
- //! Complexity: Constant
- //!
- //! Throws: Nothing.
- static bool unique(const_node_ptr this_node)
- { return NodeTraits::get_next(this_node) == this_node; }
-
//! Requires: this_node must be in a circular list or be an empty circular list.
//!
//! Effects: Returns the number of nodes in a circular list. If the circular list
@@ -154,34 +212,7 @@ class circular_slist_algorithms
return result;
}
- //! Requires: prev_node must be in a circular list or be an empty circular list.
- //!
- //! Effects: Unlinks the next node of prev_node from the circular list.
- //!
- //! Complexity: Constant
- //!
- //! Throws: 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);
- }
-
- //! Requires: nxt_node must be in a circular list or be an empty circular list.
- //!
- //! Effects: Unlinks the previous node of nxt_node from the circular list.
- //!
- //! Complexity: Linear to the elements in the circular list.
- //!
- //! Throws: 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);
- }
-
- //! Requires: this_node must be in a circular list or be an empty circular list.
+ //! Requires: this_node must be in a circular list, be an empty circular list or be inited.
//!
//! Effects: Unlinks the node from the circular list.
//!
@@ -189,20 +220,9 @@ class circular_slist_algorithms
//!
//! Throws: Nothing.
static void unlink(node_ptr this_node)
- { unlink_after(get_previous_node(this_node)); }
-
- //! Requires: prev_node must be a node of a circular list.
- //!
- //! Effects: Links this_node after prev_node in the circular list.
- //!
- //! Complexity: Constant
- //!
- //! Throws: 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(prev_node, this_node);
+ if(NodeTraits::get_next(this_node))
+ base_t::unlink_after(get_previous_node(this_node));
}
//! Requires: nxt_node must be a node of a circular list.
@@ -213,7 +233,7 @@ class circular_slist_algorithms
//!
//! Throws: Nothing.
static void link_before (node_ptr nxt_node, node_ptr this_node)
- { link_after(get_previous_node(nxt_node), this_node); }
+ { base_t::link_after(get_previous_node(nxt_node), this_node); }
//! Requires: this_node and other_node must be nodes inserted
//! in circular lists or be empty circular lists.
@@ -229,8 +249,17 @@ class circular_slist_algorithms
{
if (other_node == this_node)
return;
- bool empty1 = unique(this_node);
- bool empty2 = unique(other_node);
+ bool this_inited = base_t::inited(this_node);
+ bool other_inited = base_t::inited(other_node);
+ if(this_inited){
+ base_t::init_header(this_node);
+ }
+ if(other_inited){
+ base_t::init_header(other_node);
+ }
+
+ bool empty1 = base_t::unique(this_node);
+ bool empty2 = base_t::unique(other_node);
node_ptr prev_this (get_previous_node(this_node));
node_ptr prev_other(get_previous_node(other_node));
@@ -240,26 +269,12 @@ 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);
- }
- //! Requires: 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.
- //!
- //! Effects: Removes the nodes from [b, e) range from their circular list and inserts
- //! them after p in p's circular list.
- //!
- //! Complexity: Constant
- //!
- //! Throws: 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);
+ if(this_inited){
+ base_t::init(other_node);
+ }
+ if(other_inited){
+ base_t::init(this_node);
}
}
@@ -275,9 +290,110 @@ class circular_slist_algorithms
node_ptr nxt(NodeTraits::get_next(i));
if (nxt == e)
break;
- transfer_after(e, i, nxt);
+ base_t::transfer_after(e, i, nxt);
}
}
+
+ //! Effects: Moves the node p n positions towards the end of the list.
+ //!
+ //! Returns: The previous node of p after the function if there has been any movement,
+ //! Null if n leads to no movement.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: 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, nothing to do
+ if(!n) return 0;
+ node_ptr first = NodeTraits::get_next(p);
+
+ //count() == 1 or 2, nothing to do
+ if(NodeTraits::get_next(first) == p)
+ return 0;
+
+ 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 0;
+ i = 0;
+ //Unlink p and continue the new first node search
+ first = NodeTraits::get_next(p);
+ base_t::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){
+ base_t::unlink_after(base_t::get_previous_node(first, p));
+ }
+
+ //Now link p after the new last node
+ base_t::link_after(new_last, p);
+ return new_last;
+ }
+
+ //! Effects: Moves the node p n positions towards the beginning of the list.
+ //!
+ //! Returns: The previous node of p after the function if there has been any movement,
+ //! Null if n leads equals to no movement.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: 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, nothing to do
+ if(!n) return 0;
+ node_ptr first = node_traits::get_next(p);
+
+ //count() == 1 or 2, nothing to do
+ if(node_traits::get_next(first) == p) return 0;
+
+ //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 0;
+
+ 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
+ base_t::unlink_after(old_last);
+ base_t::link_after(new_last, p);
+ return new_last;
+ }
};
} //namespace intrusive
diff --git a/include/boost/intrusive/detail/common_slist_algorithms.hpp b/include/boost/intrusive/detail/common_slist_algorithms.hpp
new file mode 100644
index 0000000..4f4a8f1
--- /dev/null
+++ b/include/boost/intrusive/detail/common_slist_algorithms.hpp
@@ -0,0 +1,95 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2008
+//
+// 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_COMMON_SLIST_ALGORITHMS_HPP
+#define BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP
+
+#include
+#include
+#include
+#include
+
+namespace boost {
+namespace intrusive {
+namespace detail {
+
+template
+class common_slist_algorithms
+{
+ public:
+ typedef typename NodeTraits::node_ptr node_ptr;
+ typedef typename NodeTraits::const_node_ptr const_node_ptr;
+ typedef NodeTraits node_traits;
+
+ 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){
+ //Logic error: possible use of linear lists with
+ //operations only permitted with lists
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(p);
+ }
+ return p;
+ }
+
+ static void init_header(node_ptr this_node)
+ { NodeTraits::set_next(this_node, this_node); }
+
+ static void init(node_ptr this_node)
+ { NodeTraits::set_next(this_node, 0); }
+
+ static bool unique(const_node_ptr this_node)
+ {
+ node_ptr next = NodeTraits::get_next(this_node);
+ return !next || next == this_node;
+ }
+
+ static bool inited(const_node_ptr this_node)
+ { return !NodeTraits::get_next(this_node); }
+
+ 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));
+ }
+
+ static void unlink_after(node_ptr prev_node, node_ptr last_node)
+ { NodeTraits::set_next(prev_node, last_node); }
+
+ 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);
+ }
+
+ 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);
+ }
+ }
+};
+
+} //namespace detail
+} //namespace intrusive
+} //namespace boost
+
+#include
+
+#endif //BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP
diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp
index 1a6c045..7cf320c 100644
--- a/include/boost/intrusive/detail/tree_algorithms.hpp
+++ b/include/boost/intrusive/detail/tree_algorithms.hpp
@@ -137,9 +137,9 @@ class tree_algorithms
{ return uncast(header); }
//! Requires: node is a node of the tree or an node initialized
- //! by init(...).
+ //! by init(...) or init_node.
//!
- //! Effects: Returns true if the node is initialized by init().
+ //! Effects: Returns true if the node is initialized by init() or init_node().
//!
//! Complexity: Constant time.
//!
diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp
index 2e018c9..e8b3bb3 100644
--- a/include/boost/intrusive/detail/utilities.hpp
+++ b/include/boost/intrusive/detail/utilities.hpp
@@ -498,7 +498,8 @@ inline std::size_t floor_log2 (std::size_t x)
inline float fast_log2 (float val)
{
- boost::uint32_t * const exp_ptr = reinterpret_cast (&val);
+ boost::uint32_t * exp_ptr =
+ static_cast(static_cast(&val));
boost::uint32_t x = *exp_ptr;
const int log_2 = (int)(((x >> 23) & 255) - 128);
x &= ~(255 << 23);
diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp
index e21f883..6947427 100644
--- a/include/boost/intrusive/hashtable.hpp
+++ b/include/boost/intrusive/hashtable.hpp
@@ -747,7 +747,7 @@ class hashtable_impl
}
BOOST_INTRUSIVE_CATCH(...){
this->clear_and_dispose(disposer);
- BOOST_RETHROW;
+ BOOST_INTRUSIVE_RETHROW;
}
BOOST_INTRUSIVE_CATCH_END
}
diff --git a/include/boost/intrusive/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp
index 67d50a7..9228bcb 100644
--- a/include/boost/intrusive/intrusive_fwd.hpp
+++ b/include/boost/intrusive/intrusive_fwd.hpp
@@ -69,6 +69,8 @@ template
, class O1 = none
, class O2 = none
, class O3 = none
+ , class O4 = none
+ , class O5 = none
>
class slist;
diff --git a/include/boost/intrusive/linear_slist_algorithms.hpp b/include/boost/intrusive/linear_slist_algorithms.hpp
new file mode 100644
index 0000000..681c13b
--- /dev/null
+++ b/include/boost/intrusive/linear_slist_algorithms.hpp
@@ -0,0 +1,326 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (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
+#include
+#include
+#include
+#include
+
+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:
+//!
+//! Typedefs:
+//!
+//! node: The type of the node that forms the linear list
+//!
+//! node_ptr: A pointer to a node
+//!
+//! const_node_ptr: A pointer to a const node
+//!
+//! Static functions:
+//!
+//! static node_ptr get_next(const_node_ptr n);
+//!
+//! static void set_next(node_ptr n, node_ptr next);
+template
+class linear_slist_algorithms
+ /// @cond
+ : public detail::common_slist_algorithms
+ /// @endcond
+{
+ /// @cond
+ typedef detail::common_slist_algorithms base_t;
+ /// @endcond
+ public:
+ typedef typename NodeTraits::node_ptr node_ptr;
+ typedef typename NodeTraits::const_node_ptr const_node_ptr;
+ typedef NodeTraits node_traits;
+
+ #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+ //! Effects: Constructs an non-used list element, putting the next
+ //! pointer to null:
+ //! NodeTraits::get_next(this_node) == 0
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void init(node_ptr this_node);
+
+ //! Requires: this_node must be in a circular list or be an empty circular list.
+ //!
+ //! Effects: Returns true is "this_node" is the only node of a circular list:
+ //! or it's a not inserted node:
+ //! return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static bool unique(const_node_ptr this_node);
+
+ //! Effects: Returns true is "this_node" has the same state as if
+ //! it was inited using "init(node_ptr)"
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static bool inited(const_node_ptr this_node);
+
+ //! Requires: prev_node must be in a circular list or be an empty circular list.
+ //!
+ //! Effects: Unlinks the next node of prev_node from the circular list.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void unlink_after(node_ptr prev_node);
+
+ //! Requires: prev_node and last_node must be in a circular list
+ //! or be an empty circular list.
+ //!
+ //! Effects: Unlinks the range (prev_node, last_node) from the linear list.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void unlink_after(node_ptr prev_node, node_ptr last_node);
+
+ //! Requires: prev_node must be a node of a linear list.
+ //!
+ //! Effects: Links this_node after prev_node in the linear list.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void link_after(node_ptr prev_node, node_ptr this_node);
+
+ //! Requires: 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.
+ //!
+ //! Effects: Removes the nodes from (b, e] range from their linear list and inserts
+ //! them after p in p's linear list.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
+
+ #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+ //! Effects: Constructs an empty list, making this_node the only
+ //! node of the circular list:
+ //! NodeTraits::get_next(this_node) == this_node.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: Nothing.
+ static void init_header(node_ptr this_node)
+ { NodeTraits::set_next(this_node, 0); }
+
+ //! Requires: this_node and prev_init_node must be in the same linear list.
+ //!
+ //! Effects: 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).
+ //!
+ //! Complexity: Linear to the number of elements between prev_init_node and this_node.
+ //!
+ //! Throws: Nothing.
+ static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node)
+ { return base_t::get_previous_node(prev_init_node, this_node); }
+
+ //! Requires: this_node must be in a linear list or be an empty linear list.
+ //!
+ //! Effects: Returns the number of nodes in a linear list. If the linear list
+ //! is empty, returns 1.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: 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;
+ }
+
+ //! Requires: this_node and other_node must be nodes inserted
+ //! in linear lists or be empty linear lists.
+ //!
+ //! Effects: Moves all the nodes previously chained after this_node after other_node
+ //! and vice-versa.
+ //!
+ //! Complexity: Constant
+ //!
+ //! Throws: 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);
+ }
+
+ //! Effects: Reverses the order of elements in the list.
+ //!
+ //! Returns: The new first node of the list.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: 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));
+ base_t::unlink_after(p);
+ NodeTraits::set_next(i, first);
+ first = i;
+ i = nxti;
+ }
+ return first;
+ }
+
+ //! Effects: Moves the first n nodes starting at p to the end of the list.
+ //!
+ //! Returns: A pair containing the new first and last node of the list or
+ //! if there has been any movement, a null pair if n leads to no movement.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: Linear to the number of elements plus the number moved positions.
+ static std::pair move_first_n_backwards(node_ptr p, std::size_t n)
+ {
+ std::pair ret(0, 0);
+ //Null shift, or count() == 0 or 1, nothing to do
+ if(!n || !p || !NodeTraits::get_next(p)){
+ return ret;
+ }
+
+ 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 ret;
+ 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 = base_t::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);
+ ret.first = first;
+ ret.second = new_last;
+ return ret;
+ }
+
+ //! Effects: Moves the first n nodes starting at p to the beginning of the list.
+ //!
+ //! Returns: A pair containing the new first and last node of the list or
+ //! if there has been any movement, a null pair if n leads to no movement.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: Linear to the number of elements plus the number moved positions.
+ static std::pair move_first_n_forward(node_ptr p, std::size_t n)
+ {
+ std::pair ret(0, 0);
+ //Null shift, or count() == 0 or 1, nothing to do
+ if(!n || !p || !NodeTraits::get_next(p))
+ return ret;
+
+ 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 ret;
+
+ 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);
+ ret.first = new_first;
+ ret.second = new_last;
+ return ret;
+ }
+};
+
+} //namespace intrusive
+} //namespace boost
+
+#include
+
+#endif //BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP
diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp
index 3b337d8..5968dd2 100644
--- a/include/boost/intrusive/list.hpp
+++ b/include/boost/intrusive/list.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());
}
//! Requires: 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();
}
@@ -290,14 +290,8 @@ class list_impl
//! Complexity: Constant.
//!
//! Note: Invalidates the iterators (but not the references) to the erased element.
- void pop_back()
- {
- node_ptr to_erase = node_traits::get_previous(this->get_root_node());
- node_algorithms::unlink(to_erase);
- this->priv_size_traits().decrement();
- if(safemode_or_autounlink)
- node_algorithms::init(to_erase);
- }
+ void pop_back()
+ { return this->pop_back_and_dispose(detail::null_disposer()); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -329,14 +323,8 @@ class list_impl
//! Complexity: Constant.
//!
//! Note: Invalidates the iterators (but not the references) to the erased element.
- void pop_front()
- {
- node_ptr to_erase = node_traits::get_next(this->get_root_node());
- node_algorithms::unlink(to_erase);
- this->priv_size_traits().decrement();
- if(safemode_or_autounlink)
- node_algorithms::init(to_erase);
- }
+ void pop_front()
+ { return this->pop_front_and_dispose(detail::null_disposer()); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -406,7 +394,7 @@ class list_impl
//!
//! Complexity: Constant.
const_iterator begin() const
- { return cbegin(); }
+ { return this->cbegin(); }
//! Effects: Returns a const_iterator to the first element contained in the list.
//!
@@ -430,7 +418,7 @@ class list_impl
//!
//! Complexity: Constant.
const_iterator end() const
- { return cend(); }
+ { return this->cend(); }
//! Effects: Returns a constant iterator to the end of the list.
//!
@@ -447,7 +435,7 @@ class list_impl
//!
//! Complexity: Constant.
reverse_iterator rbegin()
- { return reverse_iterator(end()); }
+ { return reverse_iterator(this->end()); }
//! Effects: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed list.
@@ -456,7 +444,7 @@ class list_impl
//!
//! Complexity: Constant.
const_reverse_iterator rbegin() const
- { return crbegin(); }
+ { return this->crbegin(); }
//! Effects: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed list.
@@ -483,7 +471,7 @@ class list_impl
//!
//! Complexity: Constant.
const_reverse_iterator rend() const
- { return crend(); }
+ { return this->crend(); }
//! Effects: Returns a const_reverse_iterator pointing to the end
//! of the reversed list.
@@ -492,7 +480,7 @@ class list_impl
//!
//! Complexity: Constant.
const_reverse_iterator crend() const
- { return const_reverse_iterator(begin()); }
+ { return const_reverse_iterator(this->begin()); }
//! Precondition: end_iterator must be a valid end iterator
//! of list.
@@ -503,7 +491,7 @@ class list_impl
//!
//! Complexity: Constant.
static list_impl &container_from_end_iterator(iterator end_iterator)
- { return priv_container_from_end_iterator(end_iterator); }
+ { return list_impl::priv_container_from_end_iterator(end_iterator); }
//! Precondition: end_iterator must be a valid end const_iterator
//! of list.
@@ -514,7 +502,7 @@ class list_impl
//!
//! Complexity: Constant.
static const list_impl &container_from_end_iterator(const_iterator end_iterator)
- { return priv_container_from_end_iterator(end_iterator); }
+ { return list_impl::priv_container_from_end_iterator(end_iterator); }
//! Effects: Returns the number of the elements contained in the list.
//!
@@ -540,7 +528,7 @@ class list_impl
//!
//! Note: Does not affect the validity of iterators and references.
bool empty() const
- { return node_algorithms::unique(this->get_root_node()); }
+ { return node_algorithms::unique(this->get_root_node()); }
//! Effects: Swaps the elements of x and *this.
//!
@@ -569,21 +557,7 @@ class list_impl
//!
//! Note: 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); }
//! Effects: Moves forward all the elements, so that the second
//! element becomes the first, the third becomes the second...
@@ -595,20 +569,7 @@ class list_impl
//!
//! Note: 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); }
//! Effects: Erases the element pointed by i of the list.
//! No destructors are called.
@@ -623,16 +584,7 @@ class list_impl
//! Note: Invalidates the iterators (but not the references) to the
//! erased element.
iterator erase(iterator i)
- {
- iterator erase = i;
- ++i;
- node_ptr to_erase = erase.pointed_node();
- node_algorithms::unlink(to_erase);
- this->priv_size_traits().decrement();
- if(safemode_or_autounlink)
- node_algorithms::init(to_erase);
- return i;
- }
+ { return this->erase_and_dispose(i, detail::null_disposer()); }
//! Requires: first and last must be valid iterator to elements in *this.
//!
@@ -652,10 +604,7 @@ class list_impl
iterator erase(iterator b, iterator e)
{
if(safemode_or_autounlink || constant_time_size){
- while(b != e){
- b = this->erase(b);
- }
- return b;
+ return this->erase_and_dispose(b, e, detail::null_disposer());
}
else{
node_algorithms::unlink(b.pointed_node(), e.pointed_node());
@@ -680,14 +629,13 @@ class list_impl
template
iterator erase_and_dispose(iterator i, Disposer disposer)
{
- iterator erase = i;
+ node_ptr to_erase(i.pointed_node());
++i;
- node_ptr to_erase = erase.pointed_node();
node_algorithms::unlink(to_erase);
this->priv_size_traits().decrement();
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
- disposer(get_real_value_traits().to_value_ptr(to_erase));
+ disposer(this->get_real_value_traits().to_value_ptr(to_erase));
return i;
}
@@ -708,10 +656,17 @@ class list_impl
template
iterator erase_and_dispose(iterator b, iterator e, Disposer disposer)
{
- while(b != e){
- b = this->erase_and_dispose(b, disposer);
+ node_ptr bp(b.pointed_node()), ep(e.pointed_node());
+ node_algorithms::unlink(bp, ep);
+ while(bp != ep){
+ node_ptr to_erase(bp);
+ bp = node_traits::get_next(bp);
+ if(safemode_or_autounlink)
+ node_algorithms::init(to_erase);
+ disposer(get_real_value_traits().to_value_ptr(to_erase));
+ this->priv_size_traits().decrement();
}
- return b;
+ return e;
}
//! Effects: Erases all the elements of the container.
@@ -726,10 +681,10 @@ class list_impl
void clear()
{
if(safemode_or_autounlink){
- this->erase(this->begin(), this->end());
+ this->clear_and_dispose(detail::null_disposer());
}
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));
}
}
@@ -747,7 +702,18 @@ class list_impl
//! Note: Invalidates the iterators to the erased elements.
template
void clear_and_dispose(Disposer disposer)
- { this->erase_and_dispose(this->begin(), this->end(), disposer); }
+ {
+ iterator it(this->begin()), itend(this->end());
+ while(it != itend){
+ node_ptr to_erase(it.pointed_node());
+ ++it;
+ if(safemode_or_autounlink)
+ node_algorithms::init(to_erase);
+ disposer(get_real_value_traits().to_value_ptr(to_erase));
+ }
+ node_algorithms::init_header(this->get_root_node());
+ this->priv_size_traits().set_size(0);
+ }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -792,9 +758,9 @@ class list_impl
//! Note: Does not affect the validity of iterators and references.
iterator insert(iterator p, reference value)
{
- node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
+ node_ptr to_insert = this->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);
@@ -921,19 +887,10 @@ class list_impl
//! list. Iterators of this list and all the references are not invalidated.
void splice(iterator p, list_impl&x, iterator start, iterator end)
{
- if(start != end){
- if(constant_time_size){
- size_traits &thist = this->priv_size_traits();
- size_traits &xt = x.priv_size_traits();
- size_type increment = std::distance(start, end);
- node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node());
- thist.set_size(thist.get_size() + increment);
- xt.set_size(xt.get_size() - increment);
- }
- else{
- node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node());
- }
- }
+ if(constant_time_size)
+ this->splice(p, x, start, end, std::distance(start, end));
+ else
+ this->splice(p, x, start, end, 1);//distance is a dummy value
}
//! Requires: p must be a valid iterator of *this.
@@ -978,7 +935,7 @@ class list_impl
//! Complexity: The number of comparisons is approximately N log N, where N
//! is the list's size.
void sort()
- { sort(std::less()); }
+ { this->sort(std::less()); }
//! Requires: p must be a comparison function that induces a strict weak ordering
//!
@@ -1031,7 +988,7 @@ class list_impl
//!
//! Note: Iterators and references are not invalidated
void merge(list_impl& x)
- { merge(x, std::less()); }
+ { this->merge(x, std::less()); }
//! Requires: p must be a comparison function that induces a strict weak
//! ordering and both *this and x must be sorted according to that ordering
@@ -1050,9 +1007,9 @@ class list_impl
template
void merge(list_impl& x, Predicate p)
{
- iterator e = this->end();
- iterator bx = x.begin();
- iterator ex = x.end();
+ iterator e(this->end());
+ iterator bx(x.begin());
+ iterator ex(x.end());
for (iterator b = this->begin(); b != e; ++b) {
size_type n(0);
@@ -1087,7 +1044,7 @@ class list_impl
//! Note: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
void remove(const_reference value)
- { remove_if(detail::equal_to_value(value)); }
+ { this->remove_if(detail::equal_to_value(value)); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -1102,7 +1059,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid.
template
void remove_and_dispose(const_reference value, Disposer disposer)
- { remove_and_dispose_if(detail::equal_to_value(value), disposer); }
+ { this->remove_and_dispose_if(detail::equal_to_value(value), disposer); }
//! Effects: Removes all the elements for which a specified
//! predicate is satisfied. No destructors are called.
@@ -1115,7 +1072,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid.
template
void remove_if(Pred pred)
- { remove_and_dispose_if(pred, detail::null_disposer()); }
+ { this->remove_and_dispose_if(pred, detail::null_disposer()); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -1132,17 +1089,15 @@ class list_impl
template
void remove_and_dispose_if(Pred pred, Disposer disposer)
{
- iterator first = begin();
- iterator last = end();
- while(first != last) {
- iterator next = first;
- ++next;
- if(pred(*first)){
- pointer p = first.operator->();
- this->erase(first);
- disposer(p);
+ iterator cur(this->begin());
+ iterator last(this->end());
+ while(cur != last) {
+ if(pred(*cur)){
+ cur = this->erase_and_dispose(cur, disposer);
+ }
+ else{
+ ++cur;
}
- first = next;
}
}
@@ -1156,7 +1111,7 @@ class list_impl
//! Note: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
void unique()
- { unique_and_dispose(std::equal_to(), detail::null_disposer()); }
+ { this->unique_and_dispose(std::equal_to(), detail::null_disposer()); }
//! Effects: Removes adjacent duplicate elements or adjacent
//! elements that satisfy some binary predicate from the list.
@@ -1170,7 +1125,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid.
template
void unique(BinaryPredicate pred)
- { unique_and_dispose(pred, detail::null_disposer()); }
+ { this->unique_and_dispose(pred, detail::null_disposer()); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -1186,7 +1141,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid.
template
void unique_and_dispose(Disposer disposer)
- { unique_and_dispose(std::equal_to(), disposer); }
+ { this->unique_and_dispose(std::equal_to(), disposer); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -1203,18 +1158,19 @@ class list_impl
template
void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
{
- if(!this->empty()){
- iterator first = begin();
- iterator after = first;
+ iterator itend(this->end());
+ iterator cur(this->begin());
+
+ if(cur != itend){
+ iterator after(cur);
++after;
- while(after != this->end()){
- if(pred(*first, *after)){
- pointer p = after.operator->();
- after = erase(after);
- disposer(p);
+ while(after != itend){
+ if(pred(*cur, *after)){
+ after = this->erase_and_dispose(after, disposer);
}
else{
- first = after++;
+ cur = after;
+ ++after;
}
}
}
@@ -1234,7 +1190,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 +1208,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 (value))));
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value))));
return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), 0);
}
@@ -1266,8 +1222,8 @@ class list_impl
//!
//! Note: 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);
}
@@ -1281,8 +1237,8 @@ class list_impl
//!
//! Note: 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 (value))));
+ {
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value))));
return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), this);
}
diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp
index 3ced4ea..ab1f3dc 100644
--- a/include/boost/intrusive/options.hpp
+++ b/include/boost/intrusive/options.hpp
@@ -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
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
struct optimize_size
{
@@ -350,6 +346,34 @@ struct optimize_size
/// @endcond
};
+//!This option setter specifies if the list container should
+//!use a linear implementation instead of a circular one.
+template
+struct linear
+{
+/// @cond
+ template
+ struct pack : Base
+ {
+ static const bool linear = Enabled;
+ };
+/// @endcond
+};
+
+//!This option setter specifies if the list container should
+//!use a linear implementation instead of a circular one.
+template
+struct cache_last
+{
+/// @cond
+ template
+ struct pack : Base
+ {
+ static const bool cache_last = 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 +499,7 @@ struct hook_defaults
, tag
, optimize_size
, store_hash
+ , linear
>::type
{};
diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp
index dadd25b..232ab7e 100644
--- a/include/boost/intrusive/slist.hpp
+++ b/include/boost/intrusive/slist.hpp
@@ -21,13 +21,15 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
#include
-#include
+#include //std::size_t
+#include //std::pair
namespace boost {
namespace intrusive {
@@ -46,12 +48,27 @@ template
struct get_default_slist_hook
{ typedef typename T::default_slist_hook type; };
-template
+template
struct slistopt
{
typedef ValueTraits value_traits;
typedef SizeType size_type;
- static const bool constant_time_size = ConstantTimeSize;
+ static const bool constant_time_size = ConstantTimeSize;
+ static const bool linear = Linear;
+ static const bool cache_last = CacheLast;
+};
+
+template
+struct root_plus_last
+{
+ Node root_;
+ NodePtr last_;
+};
+
+template
+struct root_plus_last
+{
+ Node root_;
};
template
@@ -66,7 +83,9 @@ struct slist_defaults
>::type
>
, constant_time_size
+ , linear
, size_type
+ , cache_last
>::type
{};
@@ -86,15 +105,15 @@ struct slist_defaults
//!
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
-//! \c constant_time_size<> and \c size_type<>.
+//! \c constant_time_size<>, \c size_type<>,
+//! \c linear<> and \c cache_last<>.
//!
//! The iterators of slist are forward iterators. slist provides a static
//! function called "previous" to compute the previous iterator of a given iterator.
//! This function has linear complexity. To improve the usability esp. with
//! the '*_after' functions, ++end() == begin() and previous(begin()) == end()
-//! are defined. In addition, whenever you have an end iterator, 'after this
-//! iterator' means 'at the beginning of the list'. To improve the self-documentation
-//! a "before_begin()" function is defined, returning the end() iterator.
+//! are defined. An new special function "before_begin()" is defined, which returns
+//! an iterator that points one less the beginning of the list: ++before_begin() == begin()
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template
#else
@@ -129,10 +148,16 @@ class slist_impl
::type node_ptr;
typedef typename boost::pointer_to_other
::type const_node_ptr;
- typedef circular_slist_algorithms node_algorithms;
+ typedef typename detail::if_c
+ < Config::linear
+ , linear_slist_algorithms
+ , circular_slist_algorithms
+ >::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::value;
+ static const bool linear = Config::linear;
+ static const bool cache_last = Config::cache_last;
/// @cond
private:
@@ -152,6 +177,16 @@ 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)));
+ //A list with cached last node is incompatible with auto-unlink hooks!
+ BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink)));
+
+ node_ptr get_end_node()
+ { return node_ptr(linear ? 0 : this->get_root_node()); }
+
+ const_node_ptr get_end_node() const
+ { return const_node_ptr(linear ? 0 : this->get_root_node()); }
node_ptr get_root_node()
{ return node_ptr(&data_.root_plus_size_.root_); }
@@ -159,16 +194,49 @@ class slist_impl
const_node_ptr get_root_node() const
{ return const_node_ptr(&data_.root_plus_size_.root_); }
+ node_ptr get_last_node()
+ { return this->get_last_node(detail::bool_()); }
+
+ const_node_ptr get_last_node() const
+ { return this->get_last_node(detail::bool_()); }
+
+ void set_last_node(node_ptr n)
+ { return this->set_last_node(n, detail::bool_()); }
+
+ node_ptr get_last_node(detail::bool_)
+ { return node_ptr(0); }
+
+ const_node_ptr get_last_node(detail::bool_) const
+ { return const_node_ptr(0); }
+
+ void set_last_node(node_ptr, detail::bool_)
+ {}
+
+ node_ptr get_last_node(detail::bool_)
+ { return node_ptr(data_.root_plus_size_.last_); }
+
+ const_node_ptr get_last_node(detail::bool_) const
+ { return const_node_ptr(data_.root_plus_size_.last_); }
+
+ void set_last_node(node_ptr n, detail::bool_)
+ { data_.root_plus_size_.last_ = n; }
+
static node_ptr uncast(const_node_ptr ptr)
+ { return node_ptr(const_cast(detail::get_pointer(ptr))); }
+
+ void set_default_constructed_state()
{
- return node_ptr(const_cast(detail::get_pointer(ptr)));
+ node_algorithms::init_header(this->get_root_node());
+ this->priv_size_traits().set_size(size_type(0));
+ if(cache_last){
+ this->set_last_node(this->get_root_node());
+ }
}
struct root_plus_size
: public size_traits
- {
- node root_;
- };
+ , public root_plus_last
+ {};
struct data_t
: public slist_impl::value_traits
@@ -218,10 +286,7 @@ class slist_impl
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
slist_impl(const value_traits &v_traits = value_traits())
: data_(v_traits)
- {
- this->priv_size_traits().set_size(size_type(0));
- node_algorithms::init(this->get_root_node());
- }
+ { this->set_default_constructed_state(); }
//! Requires: Dereferencing iterator must yield an lvalue of type value_type.
//!
@@ -235,9 +300,8 @@ class slist_impl
slist_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
: data_(v_traits)
{
- this->priv_size_traits().set_size(size_type(0));
- node_algorithms::init(this->get_root_node());
- insert_after(before_begin(), b, e);
+ this->set_default_constructed_state();
+ this->insert_after(this->before_begin(), b, e);
}
//! Effects: If it's a safe-mode
@@ -263,11 +327,10 @@ class slist_impl
void clear()
{
if(safemode_or_autounlink){
- this->erase_after(this->before_begin(), this->end());
+ this->clear_and_dispose(detail::null_disposer());
}
else{
- node_algorithms::init(this->get_root_node());
- this->priv_size_traits().set_size(size_type(0));
+ this->set_default_constructed_state();
}
}
@@ -283,7 +346,17 @@ class slist_impl
//! Note: Invalidates the iterators to the erased elements.
template
void clear_and_dispose(Disposer disposer)
- { this->erase_after_and_dispose(this->before_begin(), this->end(), disposer); }
+ {
+ iterator it(this->begin()), itend(this->end());
+ while(it != itend){
+ node_ptr to_erase(it.pointed_node());
+ ++it;
+ if(safemode_or_autounlink)
+ node_algorithms::init(to_erase);
+ disposer(get_real_value_traits().to_value_ptr(to_erase));
+ }
+ this->set_default_constructed_state();
+ }
//! Requires: value must be an lvalue.
//!
@@ -299,11 +372,33 @@ 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));
+ if(cache_last){
+ if(this->empty()){
+ this->set_last_node(to_insert);
+ }
+ }
node_algorithms::link_after(this->get_root_node(), to_insert);
this->priv_size_traits().increment();
}
+ //! Requires: value must be an lvalue.
+ //!
+ //! Effects: Inserts the value in the back of the list.
+ //! No copy constructors are called.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: Constant.
+ //!
+ //! Note: Does not affect the validity of iterators and references.
+ //! This function is only available is cache_last<> is true.
+ void push_back(reference value)
+ {
+ BOOST_STATIC_ASSERT((cache_last != 0));
+ this->insert_after(iterator(this->get_last_node(), this), value);
+ }
+
//! Effects: Erases the first element of the list.
//! No destructors are called.
//!
@@ -313,13 +408,7 @@ class slist_impl
//!
//! Note: Invalidates the iterators (but not the references) to the erased element.
void pop_front()
- {
- node_ptr to_erase = node_traits::get_next(this->get_root_node());
- node_algorithms::unlink_after(this->get_root_node());
- this->priv_size_traits().decrement();
- if(safemode_or_autounlink)
- node_algorithms::init(to_erase);
- }
+ { return this->pop_front_and_dispose(detail::null_disposer()); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -335,8 +424,16 @@ class slist_impl
void pop_front_and_dispose(Disposer disposer)
{
node_ptr to_erase = node_traits::get_next(this->get_root_node());
- this->pop_front();
+ node_algorithms::unlink_after(this->get_root_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));
+ if(cache_last){
+ if(this->empty()){
+ this->set_last_node(this->get_root_node());
+ }
+ }
}
//! Effects: Returns a reference to the first element of the list.
@@ -345,7 +442,7 @@ class slist_impl
//!
//! Complexity: Constant.
reference front()
- { return *get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
+ { return *this->get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
//! Effects: Returns a const_reference to the first element of the list.
//!
@@ -353,7 +450,35 @@ class slist_impl
//!
//! Complexity: Constant.
const_reference front() const
- { return *get_real_value_traits().to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); }
+ { return *this->get_real_value_traits().to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); }
+
+ //! Effects: Returns a reference to the last element of the list.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: Constant.
+ //!
+ //! Note: Does not affect the validity of iterators and references.
+ //! This function is only available is cache_last<> is true.
+ reference back()
+ {
+ BOOST_STATIC_ASSERT((cache_last != 0));
+ return *this->get_real_value_traits().to_value_ptr(this->get_last_node());
+ }
+
+ //! Effects: Returns a const_reference to the last element of the list.
+ //!
+ //! Throws: Nothing.
+ //!
+ //! Complexity: Constant.
+ //!
+ //! Note: Does not affect the validity of iterators and references.
+ //! This function is only available is cache_last<> is true.
+ const_reference back() const
+ {
+ BOOST_STATIC_ASSERT((cache_last != 0));
+ return *this->get_real_value_traits().to_value_ptr(this->get_last_node());
+ }
//! Effects: Returns an iterator to the first element contained in the list.
//!
@@ -377,7 +502,7 @@ class slist_impl
//!
//! Complexity: Constant.
const_iterator cbegin() const
- { return const_iterator (node_traits::get_next(this->get_root_node()), this); }
+ { return const_iterator(node_traits::get_next(this->get_root_node()), this); }
//! Effects: Returns an iterator to the end of the list.
//!
@@ -385,7 +510,7 @@ class slist_impl
//!
//! Complexity: Constant.
iterator end()
- { return iterator (this->get_root_node(), this); }
+ { return iterator(this->get_end_node(), this); }
//! Effects: Returns a const_iterator to the end of the list.
//!
@@ -393,7 +518,7 @@ class slist_impl
//!
//! Complexity: Constant.
const_iterator end() const
- { return const_iterator (uncast(this->get_root_node()), this); }
+ { return const_iterator(uncast(this->get_end_node()), this); }
//! Effects: Returns a const_iterator to the end of the list.
//!
@@ -401,7 +526,7 @@ class slist_impl
//!
//! Complexity: Constant.
const_iterator cend() const
- { return const_iterator (uncast(this->get_root_node()), this); }
+ { return this->end(); }
//! Effects: Returns an iterator that points to a position
//! before the first element. Equivalent to "end()"
@@ -410,7 +535,7 @@ class slist_impl
//!
//! Complexity: Constant.
iterator before_begin()
- { return end(); }
+ { return iterator(this->get_root_node(), this); }
//! Effects: Returns an iterator that points to a position
//! before the first element. Equivalent to "end()"
@@ -419,7 +544,7 @@ class slist_impl
//!
//! Complexity: Constant.
const_iterator before_begin() const
- { return end(); }
+ { return const_iterator(uncast(this->get_root_node()), this); }
//! Effects: Returns an iterator that points to a position
//! before the first element. Equivalent to "end()"
@@ -428,7 +553,7 @@ class slist_impl
//!
//! Complexity: Constant.
const_iterator cbefore_begin() const
- { return end(); }
+ { return this->before_begin(); }
//! Precondition: end_iterator must be a valid end iterator
//! of slist.
@@ -439,7 +564,7 @@ class slist_impl
//!
//! Complexity: Constant.
static slist_impl &container_from_end_iterator(iterator end_iterator)
- { return priv_container_from_end_iterator(end_iterator); }
+ { return slist_impl::priv_container_from_end_iterator(end_iterator); }
//! Precondition: end_iterator must be a valid end const_iterator
//! of slist.
@@ -450,7 +575,7 @@ class slist_impl
//!
//! Complexity: Constant.
static const slist_impl &container_from_end_iterator(const_iterator end_iterator)
- { return priv_container_from_end_iterator(end_iterator); }
+ { return slist_impl::priv_container_from_end_iterator(end_iterator); }
//! Effects: Returns the number of the elements contained in the list.
//!
@@ -482,12 +607,18 @@ class slist_impl
//!
//! Throws: Nothing.
//!
- //! Complexity: Linear to the number of elements of both lists.
+ //! Complexity: Linear to the number of elements of both lists.
+ //! Constant-time if linear<> and/or cache_last<> options are used.
//!
//! Note: 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());
+ if(cache_last){
+ this->priv_swap_cache_last(other);
+ }
+ else{
+ this->priv_swap_lists(this->get_root_node(), other.get_root_node(), detail::bool_());
+ }
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());
@@ -505,45 +636,7 @@ class slist_impl
//!
//! Note: 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);
- }
+ { this->priv_shift_backwards(n, detail::bool_()); }
//! Effects: Moves forward all the elements, so that the second
//! element becomes the first, the third becomes the second...
@@ -555,45 +648,7 @@ class slist_impl
//!
//! Note: 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);
- }
+ { this->priv_shift_forward(n, detail::bool_()); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -610,18 +665,18 @@ class slist_impl
//! Throws: If cloner throws.
template
void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer)
- {
+ {
this->clear_and_dispose(disposer);
BOOST_INTRUSIVE_TRY{
- iterator prev = this->before_begin();
+ iterator prev(this->before_begin());
const_iterator b(src.begin()), e(src.end());
- for(; b != e; ++b, ++prev){
- this->insert_after(prev, *cloner(*b));
+ for(; b != e; ++b){
+ prev = this->insert_after(prev, *cloner(*b));
}
}
BOOST_INTRUSIVE_CATCH(...){
this->clear_and_dispose(disposer);
- BOOST_RETHROW;
+ BOOST_INTRUSIVE_RETHROW;
}
BOOST_INTRUSIVE_CATCH_END
}
@@ -643,8 +698,12 @@ 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));
- node_algorithms::link_after(prev_p.pointed_node(), n);
+ BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n));
+ node_ptr prev_n(prev_p.pointed_node());
+ node_algorithms::link_after(prev_n, n);
+ if(cache_last && (this->get_last_node() == prev_n)){
+ this->set_last_node(n);
+ }
this->priv_size_traits().increment();
return iterator (n, this);
}
@@ -665,7 +724,7 @@ class slist_impl
void insert_after(iterator prev_p, Iterator first, Iterator last)
{
for (; first != last; ++first)
- prev_p = insert_after(prev_p, *first);
+ prev_p = this->insert_after(prev_p, *first);
}
//! Requires: value must be an lvalue and p must point to an element
@@ -676,11 +735,12 @@ class slist_impl
//!
//! Throws: Nothing.
//!
- //! Complexity: Linear to the number of elements before p.
+ //! Complexity: Linear to the number of elements before p.
+ //! Constant-time if cache_last<> is true and p == end().
//!
//! Note: Does not affect the validity of iterators and references.
iterator insert(iterator p, reference value)
- { return insert_after(this->previous(p), value); }
+ { return this->insert_after(this->previous(p), value); }
//! Requires: Dereferencing iterator must yield
//! an lvalue of type value_type and p must point to an element
@@ -693,11 +753,12 @@ class slist_impl
//!
//! Complexity: Linear to the number of elements inserted plus linear
//! to the elements before b.
+ //! Linear to the number of elements to insert if cache_last<> option is true and p == end().
//!
//! Note: Does not affect the validity of iterators and references.
template
void insert(iterator p, Iterator b, Iterator e)
- { return insert_after(this->previous(p), b, e); }
+ { return this->insert_after(this->previous(p), b, e); }
//! Effects: Erases the element after the element pointed by prev of
//! the list. No destructors are called.
@@ -712,16 +773,7 @@ class slist_impl
//! Note: 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()); }
//! Effects: Erases the range (before_first, last) from
//! the list. No destructors are called.
@@ -731,18 +783,12 @@ class slist_impl
//!
//! Throws: Nothing.
//!
- //! Complexity: Lineal to the elements (last - before_first).
+ //! Complexity: Lineal to the elements (last - before_first + 1).
//!
//! Note: 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()); }
//! Effects: Erases the element pointed by i of the list.
//! No destructors are called.
@@ -775,7 +821,7 @@ class slist_impl
//! Note: Invalidates the iterators (but not the references) to the
//! erased elements.
iterator erase(iterator first, iterator last)
- { return erase_after(this->previous(first), last); }
+ { return this->erase_after(this->previous(first), last); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -794,11 +840,20 @@ class slist_impl
template
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_ptr prev_n(prev.pointed_node());
+ node_algorithms::unlink_after(prev_n);
+ if(cache_last && (to_erase == this->get_last_node())){
+ this->set_last_node(prev_n);
+ }
+ 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;
}
//! Requires: Disposer::operator()(pointer) shouldn't throw.
@@ -818,9 +873,19 @@ class slist_impl
template
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);
+ node_ptr bfp(before_first.pointed_node()), lp(last.pointed_node());
+ node_ptr fp(node_traits::get_next(bfp));
+ node_algorithms::unlink_after(bfp, lp);
+ while(fp != lp){
+ node_ptr to_erase(fp);
+ fp = node_traits::get_next(fp);
+ if(safemode_or_autounlink)
+ node_algorithms::init(to_erase);
+ disposer(get_real_value_traits().to_value_ptr(to_erase));
+ this->priv_size_traits().decrement();
+ }
+ if(cache_last && (node_traits::get_next(bfp) == this->get_end_node())){
+ this->set_last_node(bfp);
}
return last;
}
@@ -863,7 +928,7 @@ class slist_impl
//! erased elements.
template
iterator erase_and_dispose(iterator first, iterator last, Disposer disposer)
- { return erase_after_and_dispose(this->previous(first), last, disposer); }
+ { return this->erase_after_and_dispose(this->previous(first), last, disposer); }
//! Requires: Dereferencing iterator must yield
//! an lvalue of type value_type.
@@ -884,7 +949,7 @@ class slist_impl
void assign(Iterator b, Iterator e)
{
this->clear();
- this->insert_after(before_begin(), b, e);
+ this->insert_after(this->before_begin(), b, e);
}
//! Requires: Disposer::operator()(pointer) shouldn't throw.
@@ -921,18 +986,21 @@ class slist_impl
//!
//! Throws: Nothing.
//!
- //! Complexity: Linear to the elements contained in x
+ //! Complexity: Linear to the elements contained in x.
+ //! Constant-time if cache_last<> option is true.
//!
//! Note: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
iterator splice_after(iterator prev, slist_impl &x)
{
if (!x.empty()){
- iterator last_x(x.previous(x.end()));
- node_algorithms::transfer_after
- ( prev.pointed_node()
- , x.end().pointed_node()
- , last_x.pointed_node());
+ iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active
+ node_ptr prev_n(prev.pointed_node());
+ node_ptr last_x_n(last_x.pointed_node());
+ if(cache_last && node_traits::get_next(prev_n) == this->get_end_node()){
+ this->set_last_node(last_x_n);
+ }
+ node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n);
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));
return last_x;
@@ -955,15 +1023,12 @@ class slist_impl
//!
//! Note: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice_after(iterator prev, slist_impl &x, iterator prev_ele)
+ void splice_after(iterator prev_pos, slist_impl &x, iterator prev_ele)
{
- iterator nxt = prev_ele;
- ++nxt;
- if (nxt != prev && prev_ele != prev){
- node_algorithms::transfer_after
- (prev.pointed_node(), prev_ele.pointed_node(), nxt.pointed_node());
- this->priv_size_traits().increment();
- x.priv_size_traits().decrement();
+ iterator elem = prev_ele;
+ ++elem;
+ if (elem != prev_pos && prev_ele != prev_pos){
+ this->splice_after(prev_pos, x, prev_ele, elem, 1);
}
}
@@ -984,19 +1049,11 @@ class slist_impl
//! list. Iterators of this list and all the references are not invalidated.
void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last)
{
- if (before_first != before_last){
- if(constant_time_size){
- size_type increment = std::distance(before_first, before_last);
- node_algorithms::transfer_after
- (prev_pos.pointed_node(), before_first.pointed_node(), before_last.pointed_node());
- this->priv_size_traits().set_size(this->priv_size_traits().get_size() + increment);
- x.priv_size_traits().set_size(x.priv_size_traits().get_size() - increment);
- }
- else{
- node_algorithms::transfer_after
- (prev_pos.pointed_node(), before_first.pointed_node(), before_last.pointed_node());
- }
- }
+ if(constant_time_size)
+ this->splice_after(prev_pos, x, before_first, before_last, std::distance(before_first, before_last));
+ else
+ this->priv_splice_after
+ (prev_pos.pointed_node(), x, before_first.pointed_node(), before_last.pointed_node());
}
//! Requires: prev_pos must be a dereferenceable iterator in *this or be
@@ -1016,17 +1073,13 @@ class slist_impl
void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last, difference_type n)
{
if(n){
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_first, before_last) == n);
+ this->priv_splice_after
+ (prev_pos.pointed_node(), x, before_first.pointed_node(), before_last.pointed_node());
if(constant_time_size){
- BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_first, before_last) == n);
- node_algorithms::transfer_after
- (prev_pos.pointed_node(), before_first.pointed_node(), before_last.pointed_node());
this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n);
x.priv_size_traits().set_size(x.priv_size_traits().get_size() - n);
}
- else{
- node_algorithms::transfer_after
- (prev_pos.pointed_node(), before_first.pointed_node(), before_last.pointed_node());
- }
}
}
@@ -1044,11 +1097,13 @@ class slist_impl
//!
//! Complexity: Linear to the elements contained in x plus linear to
//! the elements before it.
+ //! Linear to the elements before it if cache_last<> option is true.
+ //! Constant-time if cache_last<> option is true and it == end().
//!
//! Note: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
iterator splice(iterator it, slist_impl &x)
- { return splice_after(this->previous(it), x); }
+ { return this->splice_after(this->previous(it), x); }
//! Requires: it p must be a valid iterator of *this.
//! elem must point to an element contained in list
@@ -1060,11 +1115,12 @@ class slist_impl
//! Throws: Nothing.
//!
//! Complexity: Linear to the elements before pos and before elem.
+ //! Linear to the elements before elem if cache_last<> option is true and pos == end().
//!
//! Note: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice(iterator pos, slist_impl &x, iterator elem)
- { return splice_after(this->previous(pos), x, this->previous(elem)); }
+ { return this->splice_after(this->previous(pos), x, x.previous(elem)); }
//! Requires: pos must be a dereferenceable iterator in *this
//! and first and last belong to x and first and last a valid range on x.
@@ -1075,13 +1131,16 @@ class slist_impl
//!
//! Throws: Nothing.
//!
- //! Complexity: Linear to the sum of elements before pos, first, and last.
- //! Plus linear to the number of elements transferred if constant_time_size is true.
+ //! Complexity: Linear to the sum of elements before pos, first, and last
+ //! plus linear to the number of elements transferred if constant_time_size is true.
+ //! Linear to the sum of elements before first, and last
+ //! plus linear to the number of elements transferred if constant_time_size is true
+ //! if cache_last<> is true and pos == end()
//!
//! Note: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice(iterator pos, slist_impl &x, iterator first, iterator last)
- { return splice_after(this->previous(pos), x, this->previous(first), this->previous(last)); }
+ { return this->splice_after(this->previous(pos), x, x.previous(first), x.previous(last)); }
//! Requires: pos must be a dereferenceable iterator in *this
//! and first and last belong to x and first and last a valid range on x.
@@ -1094,11 +1153,13 @@ class slist_impl
//! Throws: Nothing.
//!
//! Complexity: Linear to the sum of elements before pos, first, and last.
+ //! Linear to the sum of elements before first and last
+ //! if cache_last<> is true and pos == end().
//!
//! Note: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice(iterator pos, slist_impl &x, iterator first, iterator last, difference_type n)
- { return splice_after(this->previous(pos), x, this->previous(first), this->previous(last), n); }
+ { return this->splice_after(this->previous(pos), x, x.previous(first), x.previous(last), n); }
//! Effects: This function sorts the list *this according to std::less.
//! The sort is stable, that is, the relative order of equivalent elements is preserved.
@@ -1133,12 +1194,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 +1214,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 +1262,14 @@ class slist_impl
template
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 +1296,7 @@ class slist_impl
//!
//! Note: Iterators and references are not invalidated
void merge(slist_impl& x)
- { this->merge(x, std::less()); }
+ { this->merge(x, std::less()); }
//! Effects: Reverses the order of elements in the list.
//!
@@ -1244,8 +1305,13 @@ class slist_impl
//! Complexity: This function is linear to the contained elements.
//!
//! Note: Iterators and references are not invalidated
- void reverse()
- { node_algorithms::reverse(this->get_root_node()); }
+ void reverse()
+ {
+ if(cache_last && !this->empty()){
+ this->set_last_node(node_traits::get_next(this->get_root_node()));
+ }
+ this->priv_reverse(detail::bool_());
+ }
//! Effects: Removes all the elements that compare equal to value.
//! No destructors are called.
@@ -1258,7 +1324,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid. This function is
//! linear time: it performs exactly size() comparisons for equality.
void remove(const_reference value)
- { remove_if(detail::equal_to_value(value)); }
+ { this->remove_if(detail::equal_to_value(value)); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -1273,7 +1339,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid.
template
void remove_and_dispose(const_reference value, Disposer disposer)
- { remove_and_dispose_if(detail::equal_to_value(value), disposer); }
+ { this->remove_and_dispose_if(detail::equal_to_value(value), disposer); }
//! Effects: Removes all the elements for which a specified
//! predicate is satisfied. No destructors are called.
@@ -1286,7 +1352,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid.
template
void remove_if(Pred pred)
- { remove_and_dispose_if(pred, detail::null_disposer()); }
+ { this->remove_and_dispose_if(pred, detail::null_disposer()); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -1303,18 +1369,20 @@ class slist_impl
template
void remove_and_dispose_if(Pred pred, Disposer disposer)
{
- iterator bcur(this->before_begin()), cur, e(this->end());
+ iterator bcur(this->before_begin()), cur(this->begin()), e(this->end());
- while(++(cur = bcur) != e){
+ while(cur != e){
if (pred(*cur)){
- pointer p = cur.operator->();
- this->erase_after(bcur);
- disposer(p);
+ cur = this->erase_after_and_dispose(bcur, disposer);
}
else{
- ++bcur;
+ bcur = cur;
+ ++cur;
}
}
+ if(cache_last){
+ this->set_last_node(bcur.pointed_node());
+ }
}
//! Effects: Removes adjacent duplicate elements or adjacent
@@ -1327,7 +1395,7 @@ class slist_impl
//! Note: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
void unique()
- { unique_and_dispose(std::equal_to(), detail::null_disposer()); }
+ { this->unique_and_dispose(std::equal_to(), detail::null_disposer()); }
//! Effects: Removes adjacent duplicate elements or adjacent
//! elements that satisfy some binary predicate from the list.
@@ -1341,7 +1409,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid.
template
void unique(BinaryPredicate pred)
- { unique_and_dispose(pred, detail::null_disposer()); }
+ { this->unique_and_dispose(pred, detail::null_disposer()); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -1357,7 +1425,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid.
template
void unique_and_dispose(Disposer disposer)
- { unique(std::equal_to(), disposer); }
+ { this->unique(std::equal_to(), disposer); }
//! Requires: Disposer::operator()(pointer) shouldn't throw.
//!
@@ -1374,21 +1442,23 @@ class slist_impl
template
void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
{
- iterator end_n(end());
- iterator cur(begin());
- iterator cur_next;
-
- if (cur != end_n) {
- while(++(cur_next = cur) != end_n) {
- if (pred(*cur, *cur_next)){
- pointer p = cur_next.operator->();
- this->erase_after(cur);
- disposer(p);
+ iterator end_n(this->end());
+ iterator bcur(this->begin());
+ if(bcur != end_n){
+ iterator cur(bcur);
+ ++cur;
+ while(cur != end_n) {
+ if (pred(*bcur, *cur)){
+ cur = this->erase_after_and_dispose(bcur, disposer);
}
else{
+ bcur = cur;
++cur;
}
}
+ if(cache_last){
+ this->set_last_node(bcur.pointed_node());
+ }
}
}
@@ -1406,7 +1476,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 +1494,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 (value))));
+ //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value))));
return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0);
}
@@ -1438,8 +1508,8 @@ class slist_impl
//!
//! Note: 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);
}
@@ -1453,8 +1523,8 @@ class slist_impl
//!
//! Note: 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 (value))));
+ {
+ //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value))));
return const_iterator (value_traits::to_node_ptr(const_cast (value)), this);
}
@@ -1464,12 +1534,16 @@ class slist_impl
//!
//! Throws: Nothing.
//!
- //! Complexity: Linear to the number of elements before i.
+ //! Complexity: Linear to the number of elements before i.
+ //! Constant if cache_last<> is true and i == end().
iterator previous(iterator i)
{
+ if(cache_last && (i.pointed_node() == this->get_end_node())){
+ return iterator(this->get_last_node(), this);
+ }
return iterator
(node_algorithms::get_previous_node
- (before_begin().pointed_node(), i.pointed_node()), 0);
+ (this->before_begin().pointed_node(), i.pointed_node()), this);
}
//! Returns: The const_iterator to the element before i in the list.
@@ -1479,18 +1553,117 @@ class slist_impl
//! Throws: Nothing.
//!
//! Complexity: Linear to the number of elements before i.
+ //! Constant if cache_last<> is true and i == end().
const_iterator previous(const_iterator i) const
{
+ if(cache_last && (i.pointed_node() == this->get_end_node())){
+ return iterator(uncast(this->get_last_node()), this);
+ }
return const_iterator
(node_algorithms::get_previous_node
- (before_begin().pointed_node(), i.pointed_node()), 0);
+ (this->before_begin().pointed_node(), i.pointed_node()), this);
}
private:
+ void priv_splice_after(node_ptr prev_pos_n, slist_impl &x, node_ptr before_first_n, node_ptr before_last_n)
+ {
+ if(cache_last){
+ if(node_traits::get_next(prev_pos_n) == this->get_end_node()){
+ this->set_last_node(before_last_n);
+ }
+ if(node_traits::get_next(before_last_n) == x.get_end_node()){
+ x.set_last_node(before_first_n);
+ }
+ }
+ node_algorithms::transfer_after(prev_pos_n, before_first_n, before_last_n);
+ }
+
+ void priv_reverse(detail::bool_)
+ { node_algorithms::reverse(this->get_root_node()); }
+
+ void priv_reverse(detail::bool_)
+ {
+ 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_)
+ {
+ node_ptr last = node_algorithms::move_forward(this->get_root_node(), (std::size_t)n);
+ if(cache_last && last){
+ this->set_last_node(last);
+ }
+ }
+
+ void priv_shift_backwards(size_type n, detail::bool_)
+ {
+ std::pair ret(
+ node_algorithms::move_first_n_forward
+ (node_traits::get_next(this->get_root_node()), (std::size_t)n));
+ if(ret.first){
+ node_traits::set_next(this->get_root_node(), ret.first);
+ if(cache_last){
+ this->set_last_node(ret.second);
+ }
+ }
+ }
+
+ void priv_shift_forward(size_type n, detail::bool_)
+ {
+ node_ptr last = node_algorithms::move_backwards(this->get_root_node(), (std::size_t)n);
+ if(cache_last && last){
+ this->set_last_node(last);
+ }
+ }
+
+ void priv_shift_forward(size_type n, detail::bool_)
+ {
+ std::pair ret(
+ node_algorithms::move_first_n_backwards
+ (node_traits::get_next(this->get_root_node()), (std::size_t)n));
+ if(ret.first){
+ node_traits::set_next(this->get_root_node(), ret.first);
+ if(cache_last){
+ this->set_last_node(ret.second);
+ }
+ }
+ }
+
+ void priv_swap_cache_last(slist_impl &other)
+ {
+ node_ptr other_last(other.get_last_node());
+ node_ptr this_last(this->get_last_node());
+ node_ptr other_bfirst(other.get_root_node());
+ node_ptr this_bfirst(this->get_root_node());
+ node_algorithms::transfer_after(this_bfirst, other_bfirst, other_last);
+ node_algorithms::transfer_after(other_bfirst, other_last != other_bfirst? other_last : this_bfirst, this_last);
+ node_ptr tmp(this->get_last_node());
+ this->set_last_node(other.get_last_node());
+ other.set_last_node(tmp);
+ if(this->get_last_node() == other_bfirst){
+ this->set_last_node(this_bfirst);
+ }
+ if(other.get_last_node() == this_bfirst){
+ other.set_last_node(other_bfirst);
+ }
+ }
+
+ //circular version
+ static void priv_swap_lists(node_ptr this_node, node_ptr other_node, detail::bool_)
+ { 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_)
+ { 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
- ( detail::get_pointer(end_iterator.pointed_node()), &root_plus_size::root_);
+ ( detail::get_pointer(end_iterator.pointed_node()), (&root_plus_size::root_));
data_t *d = detail::parent_from_member
( r, &data_t::root_plus_size_);
slist_impl *s = detail::parent_from_member(d, &slist_impl::data_);
@@ -1620,13 +1793,13 @@ inline void swap
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template
#else
-template
+template
#endif
struct make_slist
{
/// @cond
typedef typename pack_options
- < slist_defaults, O1, O2, O3>::type packed_options;
+ < slist_defaults, O1, O2, O3, O4, O5>::type packed_options;
typedef typename detail::get_value_traits
::type value_traits;
typedef slist_impl
@@ -1635,6 +1808,8 @@ struct make_slist
< value_traits
, typename packed_options::size_type
, packed_options::constant_time_size
+ , packed_options::linear
+ , packed_options::cache_last
>
> implementation_defined;
/// @endcond
@@ -1643,12 +1818,12 @@ struct make_slist
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
-template
+template
class slist
- : public make_slist::type
+ : public make_slist::type
{
typedef typename make_slist
- ::type Base;
+ ::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::value));
diff --git a/include/boost/intrusive/slist_hook.hpp b/include/boost/intrusive/slist_hook.hpp
index 547ca6f..b7d5344 100644
--- a/include/boost/intrusive/slist_hook.hpp
+++ b/include/boost/intrusive/slist_hook.hpp
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
#include
@@ -31,6 +32,7 @@ struct get_slist_node_algo
{
typedef circular_slist_algorithms > type;
};
+
/// @endcond
//! Helper metafunction to define a \c slist_base_hook that yields to the same
diff --git a/proj/vc7ide/Intrusive.sln b/proj/vc7ide/Intrusive.sln
index 4fb0638..8767b1e 100644
--- a/proj/vc7ide/Intrusive.sln
+++ b/proj/vc7ide/Intrusive.sln
@@ -1,175 +1,175 @@
-Microsoft Visual Studio Solution File, Format Version 8.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list\list.vcproj", "{977B61B4-9968-497C-9F0B-24A8145473B8}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist", "slist\slist.vcproj", "{5A02061D-3728-4C49-AFC8-0130C1F161C0}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multiset", "multiset\multiset.vcproj", "{961F0E06-C092-4AF7-ABC5-2A49999F3B79}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_intrusivelib", "_intrusivelib\_intrusivelib.vcproj", "{90F3C5BD-8E6C-4629-BC71-A1009EC88059}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set", "set\set.vcproj", "{960E01F6-92C1-F74A-BCA5-2A9F3B994979}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_set", "unordered_set\unordered_set.vcproj", "{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_multiset", "unordered_multiset\unordered_multiset.vcproj", "{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "perf_test", "perf_test\perf_test.vcproj", "{910E70E6-2C91-AA67-BF4C-A9C74A309927}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "default_hook", "default_hook\default_hook.vcproj", "{761A79B4-9968-CB81-F02B-2A4497345475}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stateful_value_traits", "stateful_value_traits\stateful_value_traits.vcproj", "{9571A7B4-9968-B9C1-17FB-134547B46975}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "virtual_base", "virtual_base\virtual_base.vcproj", "{3579B1A4-9894-02AB-CB81-297B46154345}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_functions", "make_functions\make_functions.vcproj", "{7679B41B-F2B4-9176-CB81-35449467B435}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "custom_bucket_traits", "custom_bucket_traits\custom_bucket_traits.vcproj", "{31C77B84-0B2C-9481-CB81-27A149F33825}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "external_value_traits", "external_value_traits\external_value_traits.vcproj", "{97B69A72-B9D3-7389-17FB-74612F4A9543}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_multiset", "splay_multiset\splay_multiset.vcproj", "{01E70176-B6C5-BF47-2C91-A949077BA323}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_set", "splay_set\splay_set.vcproj", "{1E6909E7-C971-F24A-6C7B-A92094B71B59}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_multiset", "avl_multiset\avl_multiset.vcproj", "{0AE70176-5B8C-4BC7-392C-A4A312B07893}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_set", "avl_set\avl_set.vcproj", "{16909EE7-24AF-97C1-C76B-204B971BA959}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_multiset", "sg_multiset\sg_multiset.vcproj", "{07022E76-6CB5-92C1-B47F-A10772A79B43}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_set", "sg_set\sg_set.vcproj", "{1690A9E7-DB57-971C-F24A-09B752A942F7}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfiguration) = preSolution
- Debug = Debug
- Release = Release
- EndGlobalSection
- GlobalSection(ProjectDependencies) = postSolution
- EndGlobalSection
- GlobalSection(ProjectConfiguration) = postSolution
- {977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.ActiveCfg = Debug|Win32
- {977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.Build.0 = Debug|Win32
- {977B61B4-9968-497C-9F0B-24A8145473B8}.Release.ActiveCfg = Release|Win32
- {977B61B4-9968-497C-9F0B-24A8145473B8}.Release.Build.0 = Release|Win32
- {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.ActiveCfg = Debug|Win32
- {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.Build.0 = Debug|Win32
- {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.ActiveCfg = Release|Win32
- {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.Build.0 = Release|Win32
- {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.ActiveCfg = Debug|Win32
- {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.Build.0 = Debug|Win32
- {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.ActiveCfg = Release|Win32
- {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.Build.0 = Release|Win32
- {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.ActiveCfg = Debug|Win32
- {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.Build.0 = Debug|Win32
- {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.ActiveCfg = Release|Win32
- {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.Build.0 = Release|Win32
- {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.ActiveCfg = Debug|Win32
- {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.Build.0 = Debug|Win32
- {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.ActiveCfg = Release|Win32
- {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.Build.0 = Release|Win32
- {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.ActiveCfg = Debug|Win32
- {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.Build.0 = Debug|Win32
- {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.ActiveCfg = Release|Win32
- {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.Build.0 = Release|Win32
- {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.ActiveCfg = Debug|Win32
- {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.Build.0 = Debug|Win32
- {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.ActiveCfg = Release|Win32
- {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.Build.0 = Release|Win32
- {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.ActiveCfg = Debug|Win32
- {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.Build.0 = Debug|Win32
- {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.ActiveCfg = Release|Win32
- {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.Build.0 = Release|Win32
- {761A79B4-9968-CB81-F02B-2A4497345475}.Debug.ActiveCfg = Debug|Win32
- {761A79B4-9968-CB81-F02B-2A4497345475}.Debug.Build.0 = Debug|Win32
- {761A79B4-9968-CB81-F02B-2A4497345475}.Release.ActiveCfg = Release|Win32
- {761A79B4-9968-CB81-F02B-2A4497345475}.Release.Build.0 = Release|Win32
- {9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.ActiveCfg = Debug|Win32
- {9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.Build.0 = Debug|Win32
- {9571A7B4-9968-B9C1-17FB-134547B46975}.Release.ActiveCfg = Release|Win32
- {9571A7B4-9968-B9C1-17FB-134547B46975}.Release.Build.0 = Release|Win32
- {3579B1A4-9894-02AB-CB81-297B46154345}.Debug.ActiveCfg = Debug|Win32
- {3579B1A4-9894-02AB-CB81-297B46154345}.Debug.Build.0 = Debug|Win32
- {3579B1A4-9894-02AB-CB81-297B46154345}.Release.ActiveCfg = Release|Win32
- {3579B1A4-9894-02AB-CB81-297B46154345}.Release.Build.0 = Release|Win32
- {7679B41B-F2B4-9176-CB81-35449467B435}.Debug.ActiveCfg = Debug|Win32
- {7679B41B-F2B4-9176-CB81-35449467B435}.Debug.Build.0 = Debug|Win32
- {7679B41B-F2B4-9176-CB81-35449467B435}.Release.ActiveCfg = Release|Win32
- {7679B41B-F2B4-9176-CB81-35449467B435}.Release.Build.0 = Release|Win32
- {31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.ActiveCfg = Debug|Win32
- {31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.Build.0 = Debug|Win32
- {31C77B84-0B2C-9481-CB81-27A149F33825}.Release.ActiveCfg = Release|Win32
- {31C77B84-0B2C-9481-CB81-27A149F33825}.Release.Build.0 = Release|Win32
- {97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.ActiveCfg = Debug|Win32
- {97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.Build.0 = Debug|Win32
- {97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.ActiveCfg = Release|Win32
- {97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.Build.0 = Release|Win32
- {01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.ActiveCfg = Debug|Win32
- {01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.Build.0 = Debug|Win32
- {01E70176-B6C5-BF47-2C91-A949077BA323}.Release.ActiveCfg = Release|Win32
- {01E70176-B6C5-BF47-2C91-A949077BA323}.Release.Build.0 = Release|Win32
- {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.ActiveCfg = Debug|Win32
- {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.Build.0 = Debug|Win32
- {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.ActiveCfg = Release|Win32
- {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.Build.0 = Release|Win32
- {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.ActiveCfg = Debug|Win32
- {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.Build.0 = Debug|Win32
- {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.ActiveCfg = Release|Win32
- {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.Build.0 = Release|Win32
- {16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.ActiveCfg = Debug|Win32
- {16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.Build.0 = Debug|Win32
- {16909EE7-24AF-97C1-C76B-204B971BA959}.Release.ActiveCfg = Release|Win32
- {16909EE7-24AF-97C1-C76B-204B971BA959}.Release.Build.0 = Release|Win32
- {07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.ActiveCfg = Debug|Win32
- {07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.Build.0 = Debug|Win32
- {07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.ActiveCfg = Release|Win32
- {07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.Build.0 = Release|Win32
- {1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.ActiveCfg = Debug|Win32
- {1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.Build.0 = Debug|Win32
- {1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.ActiveCfg = Release|Win32
- {1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- EndGlobalSection
- GlobalSection(ExtensibilityAddIns) = postSolution
- EndGlobalSection
-EndGlobal
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list\list.vcproj", "{977B61B4-9968-497C-9F0B-24A8145473B8}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist", "slist\slist.vcproj", "{5A02061D-3728-4C49-AFC8-0130C1F161C0}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multiset", "multiset\multiset.vcproj", "{961F0E06-C092-4AF7-ABC5-2A49999F3B79}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_intrusivelib", "_intrusivelib\_intrusivelib.vcproj", "{90F3C5BD-8E6C-4629-BC71-A1009EC88059}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set", "set\set.vcproj", "{960E01F6-92C1-F74A-BCA5-2A9F3B994979}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_set", "unordered_set\unordered_set.vcproj", "{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_multiset", "unordered_multiset\unordered_multiset.vcproj", "{9101EE76-BB6C-2C91-F4B7-A9F3B9490279}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "perf_test", "perf_test\perf_test.vcproj", "{910E70E6-2C91-AA67-BF4C-A9C74A309927}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "default_hook", "default_hook\default_hook.vcproj", "{761A79B4-9968-CB81-F02B-2A4497345475}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stateful_value_traits", "stateful_value_traits\stateful_value_traits.vcproj", "{9571A7B4-9968-B9C1-17FB-134547B46975}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "virtual_base", "virtual_base\virtual_base.vcproj", "{3579B1A4-9894-02AB-CB81-297B46154345}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_functions", "make_functions\make_functions.vcproj", "{7679B41B-F2B4-9176-CB81-35449467B435}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "custom_bucket_traits", "custom_bucket_traits\custom_bucket_traits.vcproj", "{31C77B84-0B2C-9481-CB81-27A149F33825}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "external_value_traits", "external_value_traits\external_value_traits.vcproj", "{97B69A72-B9D3-7389-17FB-74612F4A9543}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_multiset", "splay_multiset\splay_multiset.vcproj", "{01E70176-B6C5-BF47-2C91-A949077BA323}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_set", "splay_set\splay_set.vcproj", "{1E6909E7-C971-F24A-6C7B-A92094B71B59}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_multiset", "avl_multiset\avl_multiset.vcproj", "{0AE70176-5B8C-4BC7-392C-A4A312B07893}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_set", "avl_set\avl_set.vcproj", "{16909EE7-24AF-97C1-C76B-204B971BA959}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_multiset", "sg_multiset\sg_multiset.vcproj", "{07022E76-6CB5-92C1-B47F-A10772A79B43}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sg_set", "sg_set\sg_set.vcproj", "{1690A9E7-DB57-971C-F24A-09B752A942F7}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.ActiveCfg = Debug|Win32
+ {977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.Build.0 = Debug|Win32
+ {977B61B4-9968-497C-9F0B-24A8145473B8}.Release.ActiveCfg = Release|Win32
+ {977B61B4-9968-497C-9F0B-24A8145473B8}.Release.Build.0 = Release|Win32
+ {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.ActiveCfg = Debug|Win32
+ {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.Build.0 = Debug|Win32
+ {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.ActiveCfg = Release|Win32
+ {5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.Build.0 = Release|Win32
+ {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.ActiveCfg = Debug|Win32
+ {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.Build.0 = Debug|Win32
+ {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.ActiveCfg = Release|Win32
+ {961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.Build.0 = Release|Win32
+ {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.ActiveCfg = Debug|Win32
+ {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.Build.0 = Debug|Win32
+ {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.ActiveCfg = Release|Win32
+ {90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.Build.0 = Release|Win32
+ {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.ActiveCfg = Debug|Win32
+ {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.Build.0 = Debug|Win32
+ {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.ActiveCfg = Release|Win32
+ {960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.Build.0 = Release|Win32
+ {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.ActiveCfg = Debug|Win32
+ {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.Build.0 = Debug|Win32
+ {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.ActiveCfg = Release|Win32
+ {90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.Build.0 = Release|Win32
+ {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.ActiveCfg = Debug|Win32
+ {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Debug.Build.0 = Debug|Win32
+ {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.ActiveCfg = Release|Win32
+ {9101EE76-BB6C-2C91-F4B7-A9F3B9490279}.Release.Build.0 = Release|Win32
+ {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.ActiveCfg = Debug|Win32
+ {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Debug.Build.0 = Debug|Win32
+ {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.ActiveCfg = Release|Win32
+ {910E70E6-2C91-AA67-BF4C-A9C74A309927}.Release.Build.0 = Release|Win32
+ {761A79B4-9968-CB81-F02B-2A4497345475}.Debug.ActiveCfg = Debug|Win32
+ {761A79B4-9968-CB81-F02B-2A4497345475}.Debug.Build.0 = Debug|Win32
+ {761A79B4-9968-CB81-F02B-2A4497345475}.Release.ActiveCfg = Release|Win32
+ {761A79B4-9968-CB81-F02B-2A4497345475}.Release.Build.0 = Release|Win32
+ {9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.ActiveCfg = Debug|Win32
+ {9571A7B4-9968-B9C1-17FB-134547B46975}.Debug.Build.0 = Debug|Win32
+ {9571A7B4-9968-B9C1-17FB-134547B46975}.Release.ActiveCfg = Release|Win32
+ {9571A7B4-9968-B9C1-17FB-134547B46975}.Release.Build.0 = Release|Win32
+ {3579B1A4-9894-02AB-CB81-297B46154345}.Debug.ActiveCfg = Debug|Win32
+ {3579B1A4-9894-02AB-CB81-297B46154345}.Debug.Build.0 = Debug|Win32
+ {3579B1A4-9894-02AB-CB81-297B46154345}.Release.ActiveCfg = Release|Win32
+ {3579B1A4-9894-02AB-CB81-297B46154345}.Release.Build.0 = Release|Win32
+ {7679B41B-F2B4-9176-CB81-35449467B435}.Debug.ActiveCfg = Debug|Win32
+ {7679B41B-F2B4-9176-CB81-35449467B435}.Debug.Build.0 = Debug|Win32
+ {7679B41B-F2B4-9176-CB81-35449467B435}.Release.ActiveCfg = Release|Win32
+ {7679B41B-F2B4-9176-CB81-35449467B435}.Release.Build.0 = Release|Win32
+ {31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.ActiveCfg = Debug|Win32
+ {31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.Build.0 = Debug|Win32
+ {31C77B84-0B2C-9481-CB81-27A149F33825}.Release.ActiveCfg = Release|Win32
+ {31C77B84-0B2C-9481-CB81-27A149F33825}.Release.Build.0 = Release|Win32
+ {97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.ActiveCfg = Debug|Win32
+ {97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.Build.0 = Debug|Win32
+ {97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.ActiveCfg = Release|Win32
+ {97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.Build.0 = Release|Win32
+ {01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.ActiveCfg = Debug|Win32
+ {01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.Build.0 = Debug|Win32
+ {01E70176-B6C5-BF47-2C91-A949077BA323}.Release.ActiveCfg = Release|Win32
+ {01E70176-B6C5-BF47-2C91-A949077BA323}.Release.Build.0 = Release|Win32
+ {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.ActiveCfg = Debug|Win32
+ {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.Build.0 = Debug|Win32
+ {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.ActiveCfg = Release|Win32
+ {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.Build.0 = Release|Win32
+ {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.ActiveCfg = Debug|Win32
+ {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.Build.0 = Debug|Win32
+ {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.ActiveCfg = Release|Win32
+ {0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.Build.0 = Release|Win32
+ {16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.ActiveCfg = Debug|Win32
+ {16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.Build.0 = Debug|Win32
+ {16909EE7-24AF-97C1-C76B-204B971BA959}.Release.ActiveCfg = Release|Win32
+ {16909EE7-24AF-97C1-C76B-204B971BA959}.Release.Build.0 = Release|Win32
+ {07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.ActiveCfg = Debug|Win32
+ {07022E76-6CB5-92C1-B47F-A10772A79B43}.Debug.Build.0 = Debug|Win32
+ {07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.ActiveCfg = Release|Win32
+ {07022E76-6CB5-92C1-B47F-A10772A79B43}.Release.Build.0 = Release|Win32
+ {1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.ActiveCfg = Debug|Win32
+ {1690A9E7-DB57-971C-F24A-09B752A942F7}.Debug.Build.0 = Debug|Win32
+ {1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.ActiveCfg = Release|Win32
+ {1690A9E7-DB57-971C-F24A-09B752A942F7}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj
index 9b36d35..587661c 100644
--- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj
+++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj
@@ -135,6 +135,9 @@
+
+
@@ -213,6 +216,9 @@
+
+
diff --git a/proj/vc7ide/to-do.txt b/proj/vc7ide/to-do.txt
deleted file mode 100644
index ae66bad..0000000
--- a/proj/vc7ide/to-do.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-add includes needed for the snippets
-add section explaining splice(...,n)
-Faltaría, en mi opinión, una guía de qué headers incluyen a cuáles. P.ej.,
-los *_hook.hpp típicamente están incluidos por el header del contenedor asociado, etc.
-Add resize() to list
-Optimize rehash for when shrinking: there is no need to hash the values.
-Optimize store_hash to work with the same node and type traits as store_hash
diff --git a/test/itestvalue.hpp b/test/itestvalue.hpp
index 6878158..d6338bb 100644
--- a/test/itestvalue.hpp
+++ b/test/itestvalue.hpp
@@ -237,7 +237,7 @@ struct testvalue
// have to be handled appropriately when copied:
testvalue & operator= (const testvalue& src)
- {
+ {/*
set_base_hook_t::operator=(src);
set_auto_base_hook_t::operator=(src);
this->set_node_ = src.set_node_;
@@ -270,7 +270,7 @@ struct testvalue
slist_auto_base_hook_t::operator=(src);
this->slist_node_ = src.slist_node_;
this->slist_auto_node_ = src.slist_auto_node_;
-
+*/
value_ = src.value_;
return *this;
}
@@ -366,6 +366,14 @@ struct even_odd
}
};
+struct is_even
+{
+ template
+ bool operator()
+ (const testvalue& v1) const
+ { return (v1.value_ & 1) == 0; }
+};
+
} //namespace boost{
} //namespace intrusive{
diff --git a/test/list_test.cpp b/test/list_test.cpp
index 7b28289..3a000a9 100644
--- a/test/list_test.cpp
+++ b/test/list_test.cpp
@@ -31,6 +31,8 @@ struct test_list
static void test_all(std::vector& values);
static void test_front_back(std::vector& values);
static void test_sort(std::vector& values);
+ static void test_merge(std::vector& values);
+ static void test_remove_unique(std::vector& values);
static void test_insert(std::vector& values);
static void test_shift(std::vector& values);
static void test_swap(std::vector& values);
@@ -58,19 +60,13 @@ void test_list::test_all(std::vector
{ int init_values [] = { 5, 3, 1, 4, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
}
+
+//test: merge due to error in merge implementation:
+template
+void test_list
+ ::test_remove_unique (std::vector& values)
+{
+ typedef typename ValueTraits::value_type value_type;
+ typedef list
+ < value_type
+ , value_traits
+ , size_type
+ , constant_time_size
+ > list_type;
+ {
+ list_type list(values.begin(), values.end());
+ list.remove_if(is_even());
+ int init_values [] = { 1, 3, 5 };
+ TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
+ }
+ {
+ std::vector values2(values);
+ list_type list(values.begin(), values.end());
+ list.insert(list.end(), values2.begin(), values2.end());
+ list.sort();
+ int init_values [] = { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
+ TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
+ list.unique();
+ int init_values2 [] = { 1, 2, 3, 4, 5 };
+ TEST_INTRUSIVE_SEQUENCE( init_values2, list.begin() );
+ }
+}
+
+//test: merge due to error in merge implementation:
+template
+void test_list
+ ::test_merge (std::vector& values)
+{
+ typedef typename ValueTraits::value_type value_type;
+ typedef list
+ < value_type
+ , value_traits
+ , size_type
+ , constant_time_size
+ > list_type;
+ list_type testlist1, testlist2;
+ testlist1.push_front (values[0]);
+ testlist2.push_front (values[4]);
+ testlist2.push_front (values[3]);
+ testlist2.push_front (values[2]);
+ testlist1.merge (testlist2);
+
+ int init_values [] = { 1, 3, 4, 5 };
+ TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() );
+}
//test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template
@@ -194,26 +244,29 @@ void test_list
const int num_values = (int)values.size();
std::vector 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 +331,28 @@ void test_list
{ 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
diff --git a/test/slist_test.cpp b/test/slist_test.cpp
index 06fc38c..c8055c1 100644
--- a/test/slist_test.cpp
+++ b/test/slist_test.cpp
@@ -24,24 +24,28 @@
using namespace boost::intrusive;
-template
+template
struct test_slist
{
typedef typename ValueTraits::value_type value_type;
- static void test_all (std::vector& values);
- static void test_front_back (std::vector& values);
+ static void test_all(std::vector& values);
+ static void test_front(std::vector& values);
+ static void test_back(std::vector& values, detail::bool_);
+ static void test_back(std::vector& values, detail::bool_);
static void test_sort(std::vector& values);
- static void test_merge (std::vector& values);
+ static void test_merge(std::vector& values);
+ static void test_remove_unique(std::vector& values);
static void test_insert(std::vector& values);
static void test_shift(std::vector& values);
static void test_swap(std::vector& values);
- static void test_slow_insert (std::vector& values);
- static void test_clone (std::vector& values);
- static void test_container_from_end(std::vector &values);
+ static void test_slow_insert(std::vector& values);
+ static void test_clone(std::vector& values);
+ static void test_container_from_end(std::vector &, detail::bool_){}
+ static void test_container_from_end(std::vector &values, detail::bool_);
};
-template
-void test_slist
+template
+void test_slist
::test_all (std::vector& values)
{
typedef typename ValueTraits::value_type value_type;
@@ -50,6 +54,8 @@ void test_slist
, value_traits
, size_type
, constant_time_size
+ , linear
+ , cache_last
> list_type;
{
list_type list(values.begin(), values.end());
@@ -58,21 +64,23 @@ void test_slist
list.insert(list.end(), values.begin(), values.end());
test::test_sequence_container(list, values);
}
- test_front_back (values);
+ test_front(values);
+ test_back(values, detail::bool_());
test_sort(values);
test_merge (values);
+ test_remove_unique(values);
test_insert(values);
test_shift(values);
test_slow_insert (values);
test_swap(values);
test_clone(values);
- test_container_from_end(values);
+ test_container_from_end(values, detail::bool_());
}
//test: push_front, pop_front, front, size, empty:
-template
-void test_slist