1)Fixed gcc release mode warnings.

2)Replaced throw with BOOST_RETHROW when BOOST_TRY is used.
3)Fixed issues with singly linked lists


[SVN r42974]
This commit is contained in:
Ion Gaztañaga
2008-01-25 23:07:51 +00:00
parent 9f88d4a617
commit 703fd75c7a
12 changed files with 955 additions and 538 deletions

View File

@@ -154,10 +154,9 @@ class circular_list_algorithms
static void unlink(node_ptr b, node_ptr e) static void unlink(node_ptr b, node_ptr e)
{ {
if (b != e) { if (b != e) {
node_ptr prev(NodeTraits::get_previous(b)); node_ptr prevb(NodeTraits::get_previous(b));
node_ptr next(NodeTraits::get_next(e)); NodeTraits::set_previous(e, prevb);
NodeTraits::set_previous(next, prev); NodeTraits::set_next(prevb, e);
NodeTraits::set_next(prev, next);
} }
} }

View File

@@ -16,6 +16,7 @@
#include <boost/intrusive/detail/config_begin.hpp> #include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/common_slist_algorithms.hpp>
#include <boost/intrusive/detail/assert.hpp> #include <boost/intrusive/detail/assert.hpp>
#include <cstddef> #include <cstddef>
@@ -45,22 +46,98 @@ namespace intrusive {
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt> //! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
template<class NodeTraits> template<class NodeTraits>
class circular_slist_algorithms class circular_slist_algorithms
/// @cond
: public detail::common_slist_algorithms<NodeTraits>
/// @endcond
{ {
/// @cond
typedef detail::common_slist_algorithms<NodeTraits> base_t;
/// @endcond
public: public:
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
//! <tt>NodeTraits::get_next(this_node) == 0
//! //!
//! <b>Effects</b>: Returns the previous node of this_node in the circular list. //! <b>Complexity</b>: Constant
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr this_node) static void init(node_ptr this_node);
{ return get_previous_node(this_node, this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! or it's a not inserted node:
//! <tt>return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node);
//! <b>Effects</b>: Returns true is "this_node" has the same state as
//! if it was inited using "init(node_ptr)"
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr this_node);
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node);
//! <b>Requires</b>: prev_node and last_node must be in a circular list
//! or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the range (prev_node, last_node) from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node, node_ptr last_node);
//! <b>Requires</b>: prev_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node);
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//! and p must be a node of a different circular list.
//!
//! <b>Effects</b>: Removes the nodes from (b, e] range from their circular list and inserts
//! them after p in p's circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init_header(node_ptr this_node)
{ NodeTraits::set_next(this_node, this_node); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same circular list. //! <b>Requires</b>: this_node and prev_init_node must be in the same circular list.
//! //!
@@ -72,17 +149,17 @@ class circular_slist_algorithms
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node) 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); }
node_ptr p = prev_init_node;
for( node_ptr p_next //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
; this_node != (p_next = NodeTraits::get_next(p)) //!
; p = p_next){ //! <b>Effects</b>: Returns the previous node of this_node in the circular list.
//Logic error: possible use of linear lists with //!
//operations only permitted with circular lists //! <b>Complexity</b>: Linear to the number of elements in the circular list.
BOOST_INTRUSIVE_INVARIANT_ASSERT(p); //!
} //! <b>Throws</b>: Nothing.
return p; static node_ptr get_previous_node(node_ptr this_node)
} { return base_t::get_previous_node(this_node, this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list. //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//! //!
@@ -116,49 +193,6 @@ class circular_slist_algorithms
return p; return p;
} }
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init_header(node_ptr this_node)
{ NodeTraits::set_next(this_node, this_node); }
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
//! <tt>NodeTraits::get_next(this_node) == 0
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node)
{ NodeTraits::set_next(this_node, 0); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! or it's a not inserted node:
//! <tt>return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node</tt> or
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node)
{
node_ptr next = NodeTraits::get_next(this_node);
return !next || next == this_node;
}
//! <b>Effects</b>: Returns true is "this_node" has the same state as if it was inited using "init(node_ptr)"
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr this_node)
{ return !NodeTraits::get_next(this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list. //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//! //!
//! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list //! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list
@@ -178,33 +212,6 @@ class circular_slist_algorithms
return result; return result;
} }
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node)
{
node_ptr this_node(NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node));
//NodeTraits::set_next(this_node, this_node);
}
//! <b>Requires</b>: nxt_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the previous node of nxt_node from the circular list.
//!
//! <b>Complexity</b>: Linear to the elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static void unlink_before(node_ptr nxt_node)
{
node_ptr prev_to_erase(get_previous_previous_node(nxt_node));
unlink_after(prev_to_erase);
}
//! <b>Requires</b>: this_node must be in a circular list, be an empty circular list or be inited. //! <b>Requires</b>: this_node must be in a circular list, be an empty circular list or be inited.
//! //!
//! <b>Effects</b>: Unlinks the node from the circular list. //! <b>Effects</b>: Unlinks the node from the circular list.
@@ -215,20 +222,7 @@ class circular_slist_algorithms
static void unlink(node_ptr this_node) static void unlink(node_ptr this_node)
{ {
if(NodeTraits::get_next(this_node)) if(NodeTraits::get_next(this_node))
unlink_after(get_previous_node(this_node)); base_t::unlink_after(get_previous_node(this_node));
}
//! <b>Requires</b>: prev_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node)
{
NodeTraits::set_next(this_node, NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, this_node);
} }
//! <b>Requires</b>: nxt_node must be a node of a circular list. //! <b>Requires</b>: nxt_node must be a node of a circular list.
@@ -239,7 +233,7 @@ class circular_slist_algorithms
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static void link_before (node_ptr nxt_node, node_ptr this_node) 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); }
//! <b>Requires</b>: this_node and other_node must be nodes inserted //! <b>Requires</b>: this_node and other_node must be nodes inserted
//! in circular lists or be empty circular lists. //! in circular lists or be empty circular lists.
@@ -255,17 +249,17 @@ class circular_slist_algorithms
{ {
if (other_node == this_node) if (other_node == this_node)
return; return;
bool this_inited = inited(this_node); bool this_inited = base_t::inited(this_node);
bool other_inited = inited(other_node); bool other_inited = base_t::inited(other_node);
if(this_inited){ if(this_inited){
init_header(this_node); base_t::init_header(this_node);
} }
if(other_inited){ if(other_inited){
init_header(other_node); base_t::init_header(other_node);
} }
bool empty1 = unique(this_node); bool empty1 = base_t::unique(this_node);
bool empty2 = unique(other_node); bool empty2 = base_t::unique(other_node);
node_ptr prev_this (get_previous_node(this_node)); node_ptr prev_this (get_previous_node(this_node));
node_ptr prev_other(get_previous_node(other_node)); node_ptr prev_other(get_previous_node(other_node));
@@ -277,31 +271,10 @@ class circular_slist_algorithms
NodeTraits::set_next(empty2 ? this_node : prev_other, this_node); NodeTraits::set_next(empty2 ? this_node : prev_other, this_node);
if(this_inited){ if(this_inited){
init(other_node); base_t::init(other_node);
} }
if(other_inited){ if(other_inited){
init(this_node); base_t::init(this_node);
}
}
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//! and p must be a node of a different circular list.
//!
//! <b>Effects</b>: Removes the nodes from (b, e] range from their circular list and inserts
//! them after p in p's circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e)
{
if (p != b && p != e) {
node_ptr next_b = NodeTraits::get_next(b);
node_ptr next_e = NodeTraits::get_next(e);
node_ptr next_p = NodeTraits::get_next(p);
NodeTraits::set_next(b, next_e);
NodeTraits::set_next(e, next_p);
NodeTraits::set_next(p, next_b);
} }
} }
@@ -317,24 +290,27 @@ class circular_slist_algorithms
node_ptr nxt(NodeTraits::get_next(i)); node_ptr nxt(NodeTraits::get_next(i));
if (nxt == e) if (nxt == e)
break; break;
transfer_after(e, i, nxt); base_t::transfer_after(e, i, nxt);
} }
} }
//! <b>Effects</b>: Moves the node p n positions towards the end of the list. //! <b>Effects</b>: Moves the node p n positions towards the end of the list.
//! //!
//! <b>Returns</b>: The previous node of p after the function if there has been any movement,
//! Null if n leads to no movement.
//!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static void move_backwards(node_ptr p, std::size_t n) static node_ptr move_backwards(node_ptr p, std::size_t n)
{ {
//Null shift, nothing to do //Null shift, nothing to do
if(!n) return; if(!n) return 0;
node_ptr first = NodeTraits::get_next(p); node_ptr first = NodeTraits::get_next(p);
//count() == 1 or 2, nothing to do //count() == 1 or 2, nothing to do
if(NodeTraits::get_next(first) == p) if(NodeTraits::get_next(first) == p)
return; return 0;
bool end_found = false; bool end_found = false;
node_ptr new_last(0); node_ptr new_last(0);
@@ -350,11 +326,11 @@ class circular_slist_algorithms
//Shortcut the shift with the modulo of the size of the list //Shortcut the shift with the modulo of the size of the list
n %= i; n %= i;
if(!n) if(!n)
return; return 0;
i = 0; i = 0;
//Unlink p and continue the new first node search //Unlink p and continue the new first node search
first = NodeTraits::get_next(p); first = NodeTraits::get_next(p);
unlink_after(new_last); base_t::unlink_after(new_last);
end_found = true; end_found = true;
} }
} }
@@ -362,26 +338,30 @@ class circular_slist_algorithms
//If the p has not been found in the previous loop, find it //If the p has not been found in the previous loop, find it
//starting in the new first node and unlink it //starting in the new first node and unlink it
if(!end_found){ if(!end_found){
unlink_after(get_previous_node(first, p)); base_t::unlink_after(base_t::get_previous_node(first, p));
} }
//Now link p after the new last node //Now link p after the new last node
link_after(new_last, p); base_t::link_after(new_last, p);
return new_last;
} }
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list. //! <b>Effects</b>: Moves the node p n positions towards the beginning of the list.
//! //!
//! <b>Returns</b>: The previous node of p after the function if there has been any movement,
//! Null if n leads equals to no movement.
//!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static void move_forward(node_ptr p, std::size_t n) static node_ptr move_forward(node_ptr p, std::size_t n)
{ {
//Null shift, nothing to do //Null shift, nothing to do
if(!n) return; if(!n) return 0;
node_ptr first = node_traits::get_next(p); node_ptr first = node_traits::get_next(p);
//count() == 1 or 2, nothing to do //count() == 1 or 2, nothing to do
if(node_traits::get_next(first) == p) return; if(node_traits::get_next(first) == p) return 0;
//Iterate until p is found to know where the current last node is. //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 //If the shift count is less than the size of the list, we can also obtain
@@ -400,7 +380,7 @@ class circular_slist_algorithms
//Shortcut the shift with the modulo of the size of the list //Shortcut the shift with the modulo of the size of the list
std::size_t new_before_last_pos = (distance - (n % distance))% distance; 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 the shift is a multiple of the size there is nothing to do
if(!new_before_last_pos) return; if(!new_before_last_pos) return 0;
for( new_last = p for( new_last = p
; new_before_last_pos-- ; new_before_last_pos--
@@ -410,8 +390,9 @@ class circular_slist_algorithms
} }
//Now unlink p and link it after the new last node //Now unlink p and link it after the new last node
unlink_after(old_last); base_t::unlink_after(old_last);
link_after(new_last, p); base_t::link_after(new_last, p);
return new_last;
} }
}; };

View File

@@ -747,7 +747,7 @@ class hashtable_impl
} }
BOOST_INTRUSIVE_CATCH(...){ BOOST_INTRUSIVE_CATCH(...){
this->clear_and_dispose(disposer); this->clear_and_dispose(disposer);
BOOST_RETHROW; BOOST_INTRUSIVE_RETHROW;
} }
BOOST_INTRUSIVE_CATCH_END BOOST_INTRUSIVE_CATCH_END
} }

View File

@@ -70,6 +70,7 @@ template
, class O2 = none , class O2 = none
, class O3 = none , class O3 = none
, class O4 = none , class O4 = none
, class O5 = none
> >
class slist; class slist;

View File

@@ -16,7 +16,9 @@
#include <boost/intrusive/detail/config_begin.hpp> #include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp> #include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/common_slist_algorithms.hpp>
#include <cstddef> #include <cstddef>
#include <utility>
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
@@ -43,12 +45,99 @@ namespace intrusive {
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt> //! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
template<class NodeTraits> template<class NodeTraits>
class linear_slist_algorithms class linear_slist_algorithms
/// @cond
: public detail::common_slist_algorithms<NodeTraits>
/// @endcond
{ {
/// @cond
typedef detail::common_slist_algorithms<NodeTraits> base_t;
/// @endcond
public: public:
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
//! <tt>NodeTraits::get_next(this_node) == 0
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node);
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! or it's a not inserted node:
//! <tt>return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node);
//! <b>Effects</b>: Returns true is "this_node" has the same state as if
//! it was inited using "init(node_ptr)"
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr this_node);
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node);
//! <b>Requires</b>: prev_node and last_node must be in a circular list
//! or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the range (prev_node, last_node) from the linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node, node_ptr last_node);
//! <b>Requires</b>: prev_node must be a node of a linear list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node);
//! <b>Requires</b>: b and e must be nodes of the same linear list or an empty range.
//! and p must be a node of a different linear list.
//!
//! <b>Effects</b>: Removes the nodes from (b, e] range from their linear list and inserts
//! them after p in p's linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init_header(node_ptr this_node)
{ NodeTraits::set_next(this_node, 0); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same linear list. //! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
//! //!
//! <b>Effects</b>: Returns the previous node of this_node in the linear list starting. //! <b>Effects</b>: Returns the previous node of this_node in the linear list starting.
@@ -59,60 +148,7 @@ class linear_slist_algorithms
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node) 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); }
node_ptr p = prev_init_node;
for( node_ptr p_next
; this_node != (p_next = NodeTraits::get_next(p))
; p = p_next){
//empty
}
return p;
}
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the linear list:
//! <tt>NodeTraits::get_next(this_node) == 0.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init_header(node_ptr this_node)
{ NodeTraits::set_next(this_node, 0); }
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
//! <tt>NodeTraits::get_next(this_node) == 0
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node)
{ NodeTraits::set_next(this_node, 0); }
//! <b>Requires</b>: this_node must be in a linear list or be an empty linear list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a linear list:
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node)
{
node_ptr next = NodeTraits::get_next(this_node);
return !next || next == this_node;
}
//! <b>Requires</b>: this_node must be in a linear list or be an empty linear list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a linear list:
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr this_node)
{ return !NodeTraits::get_next(this_node); }
//! <b>Requires</b>: this_node must be in a linear list or be an empty linear list. //! <b>Requires</b>: this_node must be in a linear list or be an empty linear list.
//! //!
@@ -133,32 +169,6 @@ class linear_slist_algorithms
return result; return result;
} }
//! <b>Requires</b>: prev_node must be in a linear list or be an empty linear list.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node)
{
node_ptr this_node(NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node));
}
//! <b>Requires</b>: prev_node must be a node of a linear list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node)
{
NodeTraits::set_next(this_node, NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, this_node);
}
//! <b>Requires</b>: this_node and other_node must be nodes inserted //! <b>Requires</b>: this_node and other_node must be nodes inserted
//! in linear lists or be empty linear lists. //! in linear lists or be empty linear lists.
//! //!
@@ -176,27 +186,6 @@ class linear_slist_algorithms
NodeTraits::set_next(other_node, this_nxt); NodeTraits::set_next(other_node, this_nxt);
} }
//! <b>Requires</b>: b and e must be nodes of the same linear list or an empty range.
//! and p must be a node of a different linear list.
//!
//! <b>Effects</b>: Removes the nodes from (b, e] range from their linear list and inserts
//! them after p in p's linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e)
{
if (p != b && p != e) {
node_ptr next_b = NodeTraits::get_next(b);
node_ptr next_e = NodeTraits::get_next(e);
node_ptr next_p = NodeTraits::get_next(p);
NodeTraits::set_next(b, next_e);
NodeTraits::set_next(e, next_p);
NodeTraits::set_next(p, next_b);
}
}
//! <b>Effects</b>: Reverses the order of elements in the list. //! <b>Effects</b>: Reverses the order of elements in the list.
//! //!
//! <b>Returns</b>: The new first node of the list. //! <b>Returns</b>: The new first node of the list.
@@ -211,7 +200,7 @@ class linear_slist_algorithms
node_ptr first(p); node_ptr first(p);
while(i){ while(i){
node_ptr nxti(NodeTraits::get_next(i)); node_ptr nxti(NodeTraits::get_next(i));
unlink_after(p); base_t::unlink_after(p);
NodeTraits::set_next(i, first); NodeTraits::set_next(i, first);
first = i; first = i;
i = nxti; i = nxti;
@@ -219,16 +208,21 @@ class linear_slist_algorithms
return first; return first;
} }
//! <b>Effects</b>: Moves the node p n positions towards the end of the list. //! <b>Effects</b>: Moves the first n nodes starting at p to the end of the list.
//!
//! <b>Returns</b>: 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.
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static node_ptr move_backwards(node_ptr p, std::size_t n) static std::pair<node_ptr, node_ptr> move_first_n_backwards(node_ptr p, std::size_t n)
{ {
std::pair<node_ptr, node_ptr> ret(0, 0);
//Null shift, or count() == 0 or 1, nothing to do //Null shift, or count() == 0 or 1, nothing to do
if(!n || !p || !NodeTraits::get_next(p)) if(!n || !p || !NodeTraits::get_next(p)){
return p; return ret;
}
node_ptr first = p; node_ptr first = p;
bool end_found = false; bool end_found = false;
@@ -245,7 +239,7 @@ class linear_slist_algorithms
if(first == 0){ if(first == 0){
//Shortcut the shift with the modulo of the size of the list //Shortcut the shift with the modulo of the size of the list
n %= i; n %= i;
if(!n) return p; if(!n) return ret;
old_last = new_last; old_last = new_last;
i = 0; i = 0;
//Unlink p and continue the new first node search //Unlink p and continue the new first node search
@@ -258,25 +252,31 @@ class linear_slist_algorithms
//If the p has not been found in the previous loop, find it //If the p has not been found in the previous loop, find it
//starting in the new first node and unlink it //starting in the new first node and unlink it
if(!end_found){ if(!end_found){
old_last = get_previous_node(first, 0); old_last = base_t::get_previous_node(first, 0);
} }
//Now link p after the new last node //Now link p after the new last node
NodeTraits::set_next(old_last, p); NodeTraits::set_next(old_last, p);
NodeTraits::set_next(new_last, 0); NodeTraits::set_next(new_last, 0);
return first; ret.first = first;
ret.second = new_last;
return ret;
} }
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list. //! <b>Effects</b>: Moves the first n nodes starting at p to the beginning of the list.
//!
//! <b>Returns</b>: 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.
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static node_ptr move_forward(node_ptr p, std::size_t n) static std::pair<node_ptr, node_ptr> move_first_n_forward(node_ptr p, std::size_t n)
{ {
std::pair<node_ptr, node_ptr> ret(0, 0);
//Null shift, or count() == 0 or 1, nothing to do //Null shift, or count() == 0 or 1, nothing to do
if(!n || !p || !NodeTraits::get_next(p)) if(!n || !p || !NodeTraits::get_next(p))
return p; return ret;
node_ptr first = p; node_ptr first = p;
@@ -298,7 +298,7 @@ class linear_slist_algorithms
std::size_t new_before_last_pos = (distance - (n % distance))% distance; 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 the shift is a multiple of the size there is nothing to do
if(!new_before_last_pos) if(!new_before_last_pos)
return p; return ret;
for( new_last = p for( new_last = p
; --new_before_last_pos ; --new_before_last_pos
@@ -308,11 +308,13 @@ class linear_slist_algorithms
} }
//Get the first new node //Get the first new node
node_ptr new_first = node_traits::get_next(new_last); node_ptr new_first(node_traits::get_next(new_last));
//Now put the old beginning after the old end //Now put the old beginning after the old end
NodeTraits::set_next(old_last, p); NodeTraits::set_next(old_last, p);
NodeTraits::set_next(new_last, 0); NodeTraits::set_next(new_last, 0);
return new_first; ret.first = new_first;
ret.second = new_last;
return ret;
} }
}; };

View File

@@ -291,13 +291,7 @@ class list_impl
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element. //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.
void pop_back() void pop_back()
{ { return this->pop_back_and_dispose(detail::null_disposer()); }
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);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -330,13 +324,7 @@ class list_impl
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element. //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.
void pop_front() void pop_front()
{ { return this->pop_front_and_dispose(detail::null_disposer()); }
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);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -406,7 +394,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_iterator begin() const const_iterator begin() const
{ return cbegin(); } { return this->cbegin(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list. //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
//! //!
@@ -430,7 +418,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_iterator end() const const_iterator end() const
{ return cend(); } { return this->cend(); }
//! <b>Effects</b>: Returns a constant iterator to the end of the list. //! <b>Effects</b>: Returns a constant iterator to the end of the list.
//! //!
@@ -447,7 +435,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
reverse_iterator rbegin() reverse_iterator rbegin()
{ return reverse_iterator(end()); } { return reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed list. //! of the reversed list.
@@ -456,7 +444,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const const_reverse_iterator rbegin() const
{ return crbegin(); } { return this->crbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed list. //! of the reversed list.
@@ -483,7 +471,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const const_reverse_iterator rend() const
{ return crend(); } { return this->crend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed list. //! of the reversed list.
@@ -492,7 +480,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const const_reverse_iterator crend() const
{ return const_reverse_iterator(begin()); } { return const_reverse_iterator(this->begin()); }
//! <b>Precondition</b>: end_iterator must be a valid end iterator //! <b>Precondition</b>: end_iterator must be a valid end iterator
//! of list. //! of list.
@@ -503,7 +491,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
static list_impl &container_from_end_iterator(iterator end_iterator) 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); }
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
//! of list. //! of list.
@@ -514,7 +502,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
static const list_impl &container_from_end_iterator(const_iterator end_iterator) 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); }
//! <b>Effects</b>: Returns the number of the elements contained in the list. //! <b>Effects</b>: Returns the number of the elements contained in the list.
//! //!
@@ -596,16 +584,7 @@ class list_impl
//! <b>Note</b>: Invalidates the iterators (but not the references) to the //! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element. //! erased element.
iterator erase(iterator i) iterator erase(iterator i)
{ { return this->erase_and_dispose(i, detail::null_disposer()); }
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;
}
//! <b>Requires</b>: first and last must be valid iterator to elements in *this. //! <b>Requires</b>: first and last must be valid iterator to elements in *this.
//! //!
@@ -625,10 +604,7 @@ class list_impl
iterator erase(iterator b, iterator e) iterator erase(iterator b, iterator e)
{ {
if(safemode_or_autounlink || constant_time_size){ if(safemode_or_autounlink || constant_time_size){
while(b != e){ return this->erase_and_dispose(b, e, detail::null_disposer());
b = this->erase(b);
}
return b;
} }
else{ else{
node_algorithms::unlink(b.pointed_node(), e.pointed_node()); node_algorithms::unlink(b.pointed_node(), e.pointed_node());
@@ -653,14 +629,13 @@ class list_impl
template <class Disposer> template <class Disposer>
iterator erase_and_dispose(iterator i, Disposer disposer) iterator erase_and_dispose(iterator i, Disposer disposer)
{ {
iterator erase = i; node_ptr to_erase(i.pointed_node());
++i; ++i;
node_ptr to_erase = erase.pointed_node();
node_algorithms::unlink(to_erase); node_algorithms::unlink(to_erase);
this->priv_size_traits().decrement(); this->priv_size_traits().decrement();
if(safemode_or_autounlink) if(safemode_or_autounlink)
node_algorithms::init(to_erase); 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; return i;
} }
@@ -681,10 +656,17 @@ class list_impl
template <class Disposer> template <class Disposer>
iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) iterator erase_and_dispose(iterator b, iterator e, Disposer disposer)
{ {
while(b != e){ node_ptr bp(b.pointed_node()), ep(e.pointed_node());
b = this->erase_and_dispose(b, disposer); 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;
} }
//! <b>Effects</b>: Erases all the elements of the container. //! <b>Effects</b>: Erases all the elements of the container.
@@ -699,7 +681,7 @@ class list_impl
void clear() void clear()
{ {
if(safemode_or_autounlink){ if(safemode_or_autounlink){
this->erase(this->begin(), this->end()); this->clear_and_dispose(detail::null_disposer());
} }
else{ else{
node_algorithms::init_header(this->get_root_node()); node_algorithms::init_header(this->get_root_node());
@@ -720,7 +702,18 @@ class list_impl
//! <b>Note</b>: Invalidates the iterators to the erased elements. //! <b>Note</b>: Invalidates the iterators to the erased elements.
template <class Disposer> template <class Disposer>
void clear_and_dispose(Disposer disposer) 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);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -765,7 +758,7 @@ class list_impl
//! <b>Note</b>: Does not affect the validity of iterators and references. //! <b>Note</b>: Does not affect the validity of iterators and references.
iterator insert(iterator p, reference value) 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) if(safemode_or_autounlink)
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
node_algorithms::link_before(p.pointed_node(), to_insert); node_algorithms::link_before(p.pointed_node(), to_insert);
@@ -894,19 +887,10 @@ class list_impl
//! list. Iterators of this list and all the references are not invalidated. //! list. Iterators of this list and all the references are not invalidated.
void splice(iterator p, list_impl&x, iterator start, iterator end) void splice(iterator p, list_impl&x, iterator start, iterator end)
{ {
if(start != end){ if(constant_time_size)
if(constant_time_size){ this->splice(p, x, start, end, std::distance(start, end));
size_traits &thist = this->priv_size_traits(); else
size_traits &xt = x.priv_size_traits(); this->splice(p, x, start, end, 1);//distance is a dummy value
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());
}
}
} }
//! <b>Requires</b>: p must be a valid iterator of *this. //! <b>Requires</b>: p must be a valid iterator of *this.
@@ -951,7 +935,7 @@ class list_impl
//! <b>Complexity</b>: The number of comparisons is approximately N log N, where N //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
//! is the list's size. //! is the list's size.
void sort() void sort()
{ sort(std::less<value_type>()); } { this->sort(std::less<value_type>()); }
//! <b>Requires</b>: p must be a comparison function that induces a strict weak ordering //! <b>Requires</b>: p must be a comparison function that induces a strict weak ordering
//! //!
@@ -1004,7 +988,7 @@ class list_impl
//! //!
//! <b>Note</b>: Iterators and references are not invalidated //! <b>Note</b>: Iterators and references are not invalidated
void merge(list_impl& x) void merge(list_impl& x)
{ merge(x, std::less<value_type>()); } { this->merge(x, std::less<value_type>()); }
//! <b>Requires</b>: p must be a comparison function that induces a strict weak //! <b>Requires</b>: p must be a comparison function that induces a strict weak
//! ordering and both *this and x must be sorted according to that ordering //! ordering and both *this and x must be sorted according to that ordering
@@ -1023,9 +1007,9 @@ class list_impl
template<class Predicate> template<class Predicate>
void merge(list_impl& x, Predicate p) void merge(list_impl& x, Predicate p)
{ {
iterator e = this->end(); iterator e(this->end());
iterator bx = x.begin(); iterator bx(x.begin());
iterator ex = x.end(); iterator ex(x.end());
for (iterator b = this->begin(); b != e; ++b) { for (iterator b = this->begin(); b != e; ++b) {
size_type n(0); size_type n(0);
@@ -1060,7 +1044,7 @@ class list_impl
//! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
void remove(const_reference value) void remove(const_reference value)
{ remove_if(detail::equal_to_value<const_reference>(value)); } { this->remove_if(detail::equal_to_value<const_reference>(value)); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1075,7 +1059,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Disposer> template<class Disposer>
void remove_and_dispose(const_reference value, Disposer disposer) void remove_and_dispose(const_reference value, Disposer disposer)
{ remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); } { this->remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); }
//! <b>Effects</b>: Removes all the elements for which a specified //! <b>Effects</b>: Removes all the elements for which a specified
//! predicate is satisfied. No destructors are called. //! predicate is satisfied. No destructors are called.
@@ -1088,7 +1072,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Pred> template<class Pred>
void remove_if(Pred pred) void remove_if(Pred pred)
{ remove_and_dispose_if(pred, detail::null_disposer()); } { this->remove_and_dispose_if(pred, detail::null_disposer()); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1105,17 +1089,15 @@ class list_impl
template<class Pred, class Disposer> template<class Pred, class Disposer>
void remove_and_dispose_if(Pred pred, Disposer disposer) void remove_and_dispose_if(Pred pred, Disposer disposer)
{ {
iterator first = begin(); iterator cur(this->begin());
iterator last = end(); iterator last(this->end());
while(first != last) { while(cur != last) {
iterator next = first; if(pred(*cur)){
++next; cur = this->erase_and_dispose(cur, disposer);
if(pred(*first)){ }
pointer p = first.operator->(); else{
this->erase(first); ++cur;
disposer(p);
} }
first = next;
} }
} }
@@ -1129,7 +1111,7 @@ class list_impl
//! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
void unique() void unique()
{ unique_and_dispose(std::equal_to<value_type>(), detail::null_disposer()); } { this->unique_and_dispose(std::equal_to<value_type>(), detail::null_disposer()); }
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that satisfy some binary predicate from the list. //! elements that satisfy some binary predicate from the list.
@@ -1143,7 +1125,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class BinaryPredicate> template<class BinaryPredicate>
void unique(BinaryPredicate pred) void unique(BinaryPredicate pred)
{ unique_and_dispose(pred, detail::null_disposer()); } { this->unique_and_dispose(pred, detail::null_disposer()); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1159,7 +1141,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Disposer> template<class Disposer>
void unique_and_dispose(Disposer disposer) void unique_and_dispose(Disposer disposer)
{ unique_and_dispose(std::equal_to<value_type>(), disposer); } { this->unique_and_dispose(std::equal_to<value_type>(), disposer); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1176,18 +1158,19 @@ class list_impl
template<class BinaryPredicate, class Disposer> template<class BinaryPredicate, class Disposer>
void unique_and_dispose(BinaryPredicate pred, Disposer disposer) void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
{ {
if(!this->empty()){ iterator itend(this->end());
iterator first = begin(); iterator cur(this->begin());
iterator after = first;
if(cur != itend){
iterator after(cur);
++after; ++after;
while(after != this->end()){ while(after != itend){
if(pred(*first, *after)){ if(pred(*cur, *after)){
pointer p = after.operator->(); after = this->erase_and_dispose(after, disposer);
after = erase(after);
disposer(p);
} }
else{ else{
first = after++; cur = after;
++after;
} }
} }
} }

View File

@@ -360,6 +360,20 @@ struct linear
/// @endcond /// @endcond
}; };
//!This option setter specifies if the list container should
//!use a linear implementation instead of a circular one.
template<bool Enabled>
struct cache_last
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool cache_last = Enabled;
};
/// @endcond
};
//!This option setter specifies the bucket traits //!This option setter specifies the bucket traits
//!class for unordered associative containers. When this option is specified, //!class for unordered associative containers. When this option is specified,
//!instead of using the default bucket traits, a user defined holder will be defined //!instead of using the default bucket traits, a user defined holder will be defined

View File

@@ -28,7 +28,8 @@
#include <iterator> #include <iterator>
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef> //std::size_t
#include <utility> //std::pair
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
@@ -47,13 +48,27 @@ template <class T>
struct get_default_slist_hook struct get_default_slist_hook
{ typedef typename T::default_slist_hook type; }; { typedef typename T::default_slist_hook type; };
template <class ValueTraits, class SizeType, bool ConstantTimeSize, bool Linear> template <class ValueTraits, class SizeType, bool ConstantTimeSize, bool Linear, bool CacheLast>
struct slistopt struct slistopt
{ {
typedef ValueTraits value_traits; typedef ValueTraits value_traits;
typedef SizeType size_type; 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 linear = Linear;
static const bool cache_last = CacheLast;
};
template<class Node, class NodePtr, bool>
struct root_plus_last
{
Node root_;
NodePtr last_;
};
template<class Node, class NodePtr>
struct root_plus_last<Node, NodePtr, false>
{
Node root_;
}; };
template <class T> template <class T>
@@ -70,6 +85,7 @@ struct slist_defaults
, constant_time_size<true> , constant_time_size<true>
, linear<false> , linear<false>
, size_type<std::size_t> , size_type<std::size_t>
, cache_last<false>
>::type >::type
{}; {};
@@ -89,15 +105,15 @@ struct slist_defaults
//! //!
//! The container supports the following options: //! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>, //! \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 //! The iterators of slist are forward iterators. slist provides a static
//! function called "previous" to compute the previous iterator of a given iterator. //! function called "previous" to compute the previous iterator of a given iterator.
//! This function has linear complexity. To improve the usability esp. with //! This function has linear complexity. To improve the usability esp. with
//! the '*_after' functions, ++end() == begin() and previous(begin()) == end() //! the '*_after' functions, ++end() == begin() and previous(begin()) == end()
//! are defined. In addition, whenever you have an end iterator, 'after this //! are defined. An new special function "before_begin()" is defined, which returns
//! iterator' means 'at the beginning of the list'. To improve the self-documentation //! an iterator that points one less the beginning of the list: ++before_begin() == begin()
//! a "before_begin()" function is defined, returning the end() iterator.
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template<class T, class ...Options> template<class T, class ...Options>
#else #else
@@ -141,6 +157,7 @@ class slist_impl
static const bool constant_time_size = Config::constant_time_size; static const bool constant_time_size = Config::constant_time_size;
static const bool stateful_value_traits = detail::store_cont_ptr_on_it<slist_impl>::value; static const bool stateful_value_traits = detail::store_cont_ptr_on_it<slist_impl>::value;
static const bool linear = Config::linear; static const bool linear = Config::linear;
static const bool cache_last = Config::cache_last;
/// @cond /// @cond
private: private:
@@ -162,6 +179,14 @@ class slist_impl
BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); 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! //Linear singly linked lists are incompatible with auto-unlink hooks!
BOOST_STATIC_ASSERT(!(linear && ((int)real_value_traits::link_mode == (int)auto_unlink))); 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() node_ptr get_root_node()
{ return node_ptr(&data_.root_plus_size_.root_); } { return node_ptr(&data_.root_plus_size_.root_); }
@@ -169,16 +194,49 @@ class slist_impl
const_node_ptr get_root_node() const const_node_ptr get_root_node() const
{ return const_node_ptr(&data_.root_plus_size_.root_); } { return const_node_ptr(&data_.root_plus_size_.root_); }
node_ptr get_last_node()
{ return this->get_last_node(detail::bool_<cache_last>()); }
const_node_ptr get_last_node() const
{ return this->get_last_node(detail::bool_<cache_last>()); }
void set_last_node(node_ptr n)
{ return this->set_last_node(n, detail::bool_<cache_last>()); }
node_ptr get_last_node(detail::bool_<false>)
{ return node_ptr(0); }
const_node_ptr get_last_node(detail::bool_<false>) const
{ return const_node_ptr(0); }
void set_last_node(node_ptr, detail::bool_<false>)
{}
node_ptr get_last_node(detail::bool_<true>)
{ return node_ptr(data_.root_plus_size_.last_); }
const_node_ptr get_last_node(detail::bool_<true>) const
{ return const_node_ptr(data_.root_plus_size_.last_); }
void set_last_node(node_ptr n, detail::bool_<true>)
{ data_.root_plus_size_.last_ = n; }
static node_ptr uncast(const_node_ptr ptr) static node_ptr uncast(const_node_ptr ptr)
{ return node_ptr(const_cast<node*>(detail::get_pointer(ptr))); }
void set_default_constructed_state()
{ {
return node_ptr(const_cast<node*>(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 struct root_plus_size
: public size_traits : public size_traits
{ , public root_plus_last<node, node_ptr, cache_last>
node root_; {};
};
struct data_t struct data_t
: public slist_impl::value_traits : public slist_impl::value_traits
@@ -228,10 +286,7 @@ class slist_impl
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks). //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
slist_impl(const value_traits &v_traits = value_traits()) slist_impl(const value_traits &v_traits = value_traits())
: data_(v_traits) : data_(v_traits)
{ { this->set_default_constructed_state(); }
this->priv_size_traits().set_size(size_type(0));
node_algorithms::init_header(this->get_root_node());
}
//! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type. //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
//! //!
@@ -245,9 +300,8 @@ class slist_impl
slist_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits()) slist_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
: data_(v_traits) : data_(v_traits)
{ {
this->priv_size_traits().set_size(size_type(0)); this->set_default_constructed_state();
node_algorithms::init_header(this->get_root_node()); this->insert_after(this->before_begin(), b, e);
insert_after(before_begin(), b, e);
} }
//! <b>Effects</b>: If it's a safe-mode //! <b>Effects</b>: If it's a safe-mode
@@ -273,11 +327,10 @@ class slist_impl
void clear() void clear()
{ {
if(safemode_or_autounlink){ if(safemode_or_autounlink){
this->erase_after(this->before_begin(), this->end()); this->clear_and_dispose(detail::null_disposer());
} }
else{ else{
node_algorithms::init_header(this->get_root_node()); this->set_default_constructed_state();
this->priv_size_traits().set_size(size_type(0));
} }
} }
@@ -293,7 +346,17 @@ class slist_impl
//! <b>Note</b>: Invalidates the iterators to the erased elements. //! <b>Note</b>: Invalidates the iterators to the erased elements.
template <class Disposer> template <class Disposer>
void clear_and_dispose(Disposer disposer) 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();
}
//! <b>Requires</b>: value must be an lvalue. //! <b>Requires</b>: value must be an lvalue.
//! //!
@@ -310,10 +373,32 @@ class slist_impl
node_ptr to_insert = get_real_value_traits().to_node_ptr(value); node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
if(safemode_or_autounlink) if(safemode_or_autounlink)
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(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); node_algorithms::link_after(this->get_root_node(), to_insert);
this->priv_size_traits().increment(); this->priv_size_traits().increment();
} }
//! <b>Requires</b>: value must be an lvalue.
//!
//! <b>Effects</b>: Inserts the value in the back of the list.
//! No copy constructors are called.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: 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);
}
//! <b>Effects</b>: Erases the first element of the list. //! <b>Effects</b>: Erases the first element of the list.
//! No destructors are called. //! No destructors are called.
//! //!
@@ -323,13 +408,7 @@ class slist_impl
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element. //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.
void pop_front() void pop_front()
{ { return this->pop_front_and_dispose(detail::null_disposer()); }
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);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -345,8 +424,16 @@ class slist_impl
void pop_front_and_dispose(Disposer disposer) void pop_front_and_dispose(Disposer disposer)
{ {
node_ptr to_erase = node_traits::get_next(this->get_root_node()); 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)); disposer(get_real_value_traits().to_value_ptr(to_erase));
if(cache_last){
if(this->empty()){
this->set_last_node(this->get_root_node());
}
}
} }
//! <b>Effects</b>: Returns a reference to the first element of the list. //! <b>Effects</b>: Returns a reference to the first element of the list.
@@ -355,7 +442,7 @@ class slist_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
reference front() 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())); }
//! <b>Effects</b>: Returns a const_reference to the first element of the list. //! <b>Effects</b>: Returns a const_reference to the first element of the list.
//! //!
@@ -363,7 +450,35 @@ class slist_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reference front() const 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()))); }
//! <b>Effects</b>: Returns a reference to the last element of the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: 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());
}
//! <b>Effects</b>: Returns a const_reference to the last element of the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: 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());
}
//! <b>Effects</b>: Returns an iterator to the first element contained in the list. //! <b>Effects</b>: Returns an iterator to the first element contained in the list.
//! //!
@@ -395,7 +510,7 @@ class slist_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
iterator end() iterator end()
{ return iterator (linear ? 0 : this->get_root_node(), this); } { return iterator(this->get_end_node(), this); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list. //! <b>Effects</b>: Returns a const_iterator to the end of the list.
//! //!
@@ -403,7 +518,7 @@ class slist_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_iterator end() const const_iterator end() const
{ return const_iterator (linear ? 0 : uncast(this->get_root_node()), this); } { return const_iterator(uncast(this->get_end_node()), this); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list. //! <b>Effects</b>: Returns a const_iterator to the end of the list.
//! //!
@@ -449,7 +564,7 @@ class slist_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
static slist_impl &container_from_end_iterator(iterator end_iterator) 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); }
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
//! of slist. //! of slist.
@@ -460,7 +575,7 @@ class slist_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
static const slist_impl &container_from_end_iterator(const_iterator end_iterator) 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); }
//! <b>Effects</b>: Returns the number of the elements contained in the list. //! <b>Effects</b>: Returns the number of the elements contained in the list.
//! //!
@@ -493,11 +608,17 @@ class slist_impl
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements of both lists. //! <b>Complexity</b>: Linear to the number of elements of both lists.
//! Constant-time if linear<> and/or cache_last<> options are used.
//! //!
//! <b>Note</b>: Does not affect the validity of iterators and references. //! <b>Note</b>: Does not affect the validity of iterators and references.
void swap(slist_impl& other) void swap(slist_impl& other)
{ {
priv_swap_lists(this->get_root_node(), other.get_root_node(), detail::bool_<linear>()); if(cache_last){
this->priv_swap_cache_last(other);
}
else{
this->priv_swap_lists(this->get_root_node(), other.get_root_node(), detail::bool_<linear>());
}
if(constant_time_size){ if(constant_time_size){
size_type backup = this->priv_size_traits().get_size(); size_type backup = this->priv_size_traits().get_size();
this->priv_size_traits().set_size(other.priv_size_traits().get_size()); this->priv_size_traits().set_size(other.priv_size_traits().get_size());
@@ -515,9 +636,7 @@ class slist_impl
//! //!
//! <b>Note</b>: Iterators Does not affect the validity of iterators and references. //! <b>Note</b>: Iterators Does not affect the validity of iterators and references.
void shift_backwards(size_type n = 1) void shift_backwards(size_type n = 1)
{ { this->priv_shift_backwards(n, detail::bool_<linear>()); }
priv_shift_backwards(n, detail::bool_<linear>());
}
//! <b>Effects</b>: Moves forward all the elements, so that the second //! <b>Effects</b>: Moves forward all the elements, so that the second
//! element becomes the first, the third becomes the second... //! element becomes the first, the third becomes the second...
@@ -529,9 +648,7 @@ class slist_impl
//! //!
//! <b>Note</b>: Does not affect the validity of iterators and references. //! <b>Note</b>: Does not affect the validity of iterators and references.
void shift_forward(size_type n = 1) void shift_forward(size_type n = 1)
{ { this->priv_shift_forward(n, detail::bool_<linear>()); }
priv_shift_forward(n, detail::bool_<linear>());
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -551,15 +668,15 @@ class slist_impl
{ {
this->clear_and_dispose(disposer); this->clear_and_dispose(disposer);
BOOST_INTRUSIVE_TRY{ BOOST_INTRUSIVE_TRY{
iterator prev = this->before_begin(); iterator prev(this->before_begin());
const_iterator b(src.begin()), e(src.end()); const_iterator b(src.begin()), e(src.end());
for(; b != e; ++b, ++prev){ for(; b != e; ++b){
this->insert_after(prev, *cloner(*b)); prev = this->insert_after(prev, *cloner(*b));
} }
} }
BOOST_INTRUSIVE_CATCH(...){ BOOST_INTRUSIVE_CATCH(...){
this->clear_and_dispose(disposer); this->clear_and_dispose(disposer);
BOOST_RETHROW; BOOST_INTRUSIVE_RETHROW;
} }
BOOST_INTRUSIVE_CATCH_END BOOST_INTRUSIVE_CATCH_END
} }
@@ -582,7 +699,11 @@ class slist_impl
node_ptr n = get_real_value_traits().to_node_ptr(value); node_ptr n = get_real_value_traits().to_node_ptr(value);
if(safemode_or_autounlink) if(safemode_or_autounlink)
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n));
node_algorithms::link_after(prev_p.pointed_node(), 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(); this->priv_size_traits().increment();
return iterator (n, this); return iterator (n, this);
} }
@@ -603,7 +724,7 @@ class slist_impl
void insert_after(iterator prev_p, Iterator first, Iterator last) void insert_after(iterator prev_p, Iterator first, Iterator last)
{ {
for (; first != last; ++first) for (; first != last; ++first)
prev_p = insert_after(prev_p, *first); prev_p = this->insert_after(prev_p, *first);
} }
//! <b>Requires</b>: value must be an lvalue and p must point to an element //! <b>Requires</b>: value must be an lvalue and p must point to an element
@@ -615,10 +736,11 @@ class slist_impl
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements before p. //! <b>Complexity</b>: Linear to the number of elements before p.
//! Constant-time if cache_last<> is true and p == end().
//! //!
//! <b>Note</b>: Does not affect the validity of iterators and references. //! <b>Note</b>: Does not affect the validity of iterators and references.
iterator insert(iterator p, reference value) iterator insert(iterator p, reference value)
{ return insert_after(this->previous(p), value); } { return this->insert_after(this->previous(p), value); }
//! <b>Requires</b>: Dereferencing iterator must yield //! <b>Requires</b>: Dereferencing iterator must yield
//! an lvalue of type value_type and p must point to an element //! an lvalue of type value_type and p must point to an element
@@ -631,11 +753,12 @@ class slist_impl
//! //!
//! <b>Complexity</b>: Linear to the number of elements inserted plus linear //! <b>Complexity</b>: Linear to the number of elements inserted plus linear
//! to the elements before b. //! to the elements before b.
//! Linear to the number of elements to insert if cache_last<> option is true and p == end().
//! //!
//! <b>Note</b>: Does not affect the validity of iterators and references. //! <b>Note</b>: Does not affect the validity of iterators and references.
template<class Iterator> template<class Iterator>
void insert(iterator p, Iterator b, Iterator e) 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); }
//! <b>Effects</b>: Erases the element after the element pointed by prev of //! <b>Effects</b>: Erases the element after the element pointed by prev of
//! the list. No destructors are called. //! the list. No destructors are called.
@@ -698,7 +821,7 @@ class slist_impl
//! <b>Note</b>: Invalidates the iterators (but not the references) to the //! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased elements. //! erased elements.
iterator erase(iterator first, iterator last) iterator erase(iterator first, iterator last)
{ return erase_after(this->previous(first), last); } { return this->erase_after(this->previous(first), last); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -721,7 +844,11 @@ class slist_impl
++it; ++it;
node_ptr to_erase(it.pointed_node()); node_ptr to_erase(it.pointed_node());
++it; ++it;
node_algorithms::unlink_after(prev.pointed_node()); 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(); this->priv_size_traits().decrement();
if(safemode_or_autounlink) if(safemode_or_autounlink)
node_algorithms::init(to_erase); node_algorithms::init(to_erase);
@@ -746,10 +873,19 @@ class slist_impl
template<class Disposer> template<class Disposer>
iterator erase_after_and_dispose(iterator before_first, iterator last, Disposer disposer) iterator erase_after_and_dispose(iterator before_first, iterator last, Disposer disposer)
{ {
iterator next(before_first); node_ptr bfp(before_first.pointed_node()), lp(last.pointed_node());
++next; node_ptr fp(node_traits::get_next(bfp));
while(next != last){ node_algorithms::unlink_after(bfp, lp);
next = this->erase_after_and_dispose(before_first, disposer); 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; return last;
} }
@@ -792,7 +928,7 @@ class slist_impl
//! erased elements. //! erased elements.
template<class Disposer> template<class Disposer>
iterator erase_and_dispose(iterator first, iterator last, Disposer disposer) 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); }
//! <b>Requires</b>: Dereferencing iterator must yield //! <b>Requires</b>: Dereferencing iterator must yield
//! an lvalue of type value_type. //! an lvalue of type value_type.
@@ -813,7 +949,7 @@ class slist_impl
void assign(Iterator b, Iterator e) void assign(Iterator b, Iterator e)
{ {
this->clear(); this->clear();
this->insert_after(before_begin(), b, e); this->insert_after(this->before_begin(), b, e);
} }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
@@ -850,18 +986,21 @@ class slist_impl
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the elements contained in x //! <b>Complexity</b>: Linear to the elements contained in x.
//! Constant-time if cache_last<> option is true.
//! //!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! <b>Note</b>: 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. //! list. Iterators of this list and all the references are not invalidated.
iterator splice_after(iterator prev, slist_impl &x) iterator splice_after(iterator prev, slist_impl &x)
{ {
if (!x.empty()){ if (!x.empty()){
iterator last_x(x.previous(x.end())); iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active
node_algorithms::transfer_after node_ptr prev_n(prev.pointed_node());
( prev.pointed_node() node_ptr last_x_n(last_x.pointed_node());
, x.before_begin().pointed_node() if(cache_last && node_traits::get_next(prev_n) == this->get_end_node()){
, last_x.pointed_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()); 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)); x.priv_size_traits().set_size(size_type(0));
return last_x; return last_x;
@@ -884,15 +1023,12 @@ class slist_impl
//! //!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! <b>Note</b>: 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. //! 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; iterator elem = prev_ele;
++nxt; ++elem;
if (nxt != prev && prev_ele != prev){ if (elem != prev_pos && prev_ele != prev_pos){
node_algorithms::transfer_after this->splice_after(prev_pos, x, prev_ele, elem, 1);
(prev.pointed_node(), prev_ele.pointed_node(), nxt.pointed_node());
this->priv_size_traits().increment();
x.priv_size_traits().decrement();
} }
} }
@@ -913,19 +1049,11 @@ class slist_impl
//! list. Iterators of this list and all the references are not invalidated. //! 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) void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last)
{ {
if (before_first != before_last){ if(constant_time_size)
if(constant_time_size){ this->splice_after(prev_pos, x, before_first, before_last, std::distance(before_first, before_last));
size_type increment = std::distance(before_first, before_last); else
node_algorithms::transfer_after this->priv_splice_after
(prev_pos.pointed_node(), before_first.pointed_node(), before_last.pointed_node()); (prev_pos.pointed_node(), x, 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());
}
}
} }
//! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be //! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be
@@ -945,17 +1073,13 @@ class slist_impl
void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last, difference_type n) void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last, difference_type n)
{ {
if(n){ if(n){
if(constant_time_size){
BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_first, before_last) == n); BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_first, before_last) == n);
node_algorithms::transfer_after this->priv_splice_after
(prev_pos.pointed_node(), before_first.pointed_node(), before_last.pointed_node()); (prev_pos.pointed_node(), x, before_first.pointed_node(), before_last.pointed_node());
if(constant_time_size){
this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n); 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); 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());
}
} }
} }
@@ -973,11 +1097,13 @@ class slist_impl
//! //!
//! <b>Complexity</b>: Linear to the elements contained in x plus linear to //! <b>Complexity</b>: Linear to the elements contained in x plus linear to
//! the elements before it. //! 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().
//! //!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! <b>Note</b>: 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. //! list. Iterators of this list and all the references are not invalidated.
iterator splice(iterator it, slist_impl &x) iterator splice(iterator it, slist_impl &x)
{ return splice_after(this->previous(it), x); } { return this->splice_after(this->previous(it), x); }
//! <b>Requires</b>: it p must be a valid iterator of *this. //! <b>Requires</b>: it p must be a valid iterator of *this.
//! elem must point to an element contained in list //! elem must point to an element contained in list
@@ -989,11 +1115,12 @@ class slist_impl
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the elements before pos and before elem. //! <b>Complexity</b>: Linear to the elements before pos and before elem.
//! Linear to the elements before elem if cache_last<> option is true and pos == end().
//! //!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! <b>Note</b>: 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. //! list. Iterators of this list and all the references are not invalidated.
void splice(iterator pos, slist_impl &x, iterator elem) 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)); }
//! <b>Requires</b>: pos must be a dereferenceable iterator in *this //! <b>Requires</b>: pos must be a dereferenceable iterator in *this
//! and first and last belong to x and first and last a valid range on x. //! and first and last belong to x and first and last a valid range on x.
@@ -1004,13 +1131,16 @@ class slist_impl
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the sum of elements before pos, first, and last. //! <b>Complexity</b>: 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. //! 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()
//! //!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! <b>Note</b>: 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. //! list. Iterators of this list and all the references are not invalidated.
void splice(iterator pos, slist_impl &x, iterator first, iterator last) 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)); }
//! <b>Requires</b>: pos must be a dereferenceable iterator in *this //! <b>Requires</b>: pos must be a dereferenceable iterator in *this
//! and first and last belong to x and first and last a valid range on x. //! and first and last belong to x and first and last a valid range on x.
@@ -1023,11 +1153,13 @@ class slist_impl
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the sum of elements before pos, first, and last. //! <b>Complexity</b>: 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().
//! //!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! <b>Note</b>: 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. //! 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) 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); }
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>. //! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
//! The sort is stable, that is, the relative order of equivalent elements is preserved. //! The sort is stable, that is, the relative order of equivalent elements is preserved.
@@ -1174,7 +1306,12 @@ class slist_impl
//! //!
//! <b>Note</b>: Iterators and references are not invalidated //! <b>Note</b>: Iterators and references are not invalidated
void reverse() void reverse()
{ priv_reverse(detail::bool_<linear>()); } {
if(cache_last && !this->empty()){
this->set_last_node(node_traits::get_next(this->get_root_node()));
}
this->priv_reverse(detail::bool_<linear>());
}
//! <b>Effects</b>: Removes all the elements that compare equal to value. //! <b>Effects</b>: Removes all the elements that compare equal to value.
//! No destructors are called. //! No destructors are called.
@@ -1187,7 +1324,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid. This function is //! and iterators to elements that are not removed remain valid. This function is
//! linear time: it performs exactly size() comparisons for equality. //! linear time: it performs exactly size() comparisons for equality.
void remove(const_reference value) void remove(const_reference value)
{ remove_if(detail::equal_to_value<const_reference>(value)); } { this->remove_if(detail::equal_to_value<const_reference>(value)); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1202,7 +1339,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Disposer> template<class Disposer>
void remove_and_dispose(const_reference value, Disposer disposer) void remove_and_dispose(const_reference value, Disposer disposer)
{ remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); } { this->remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); }
//! <b>Effects</b>: Removes all the elements for which a specified //! <b>Effects</b>: Removes all the elements for which a specified
//! predicate is satisfied. No destructors are called. //! predicate is satisfied. No destructors are called.
@@ -1215,7 +1352,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Pred> template<class Pred>
void remove_if(Pred pred) void remove_if(Pred pred)
{ remove_and_dispose_if(pred, detail::null_disposer()); } { this->remove_and_dispose_if(pred, detail::null_disposer()); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1232,18 +1369,20 @@ class slist_impl
template<class Pred, class Disposer> template<class Pred, class Disposer>
void remove_and_dispose_if(Pred pred, Disposer disposer) 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)){ if (pred(*cur)){
pointer p = cur.operator->(); cur = this->erase_after_and_dispose(bcur, disposer);
this->erase_after(bcur);
disposer(p);
} }
else{ else{
++bcur; bcur = cur;
++cur;
} }
} }
if(cache_last){
this->set_last_node(bcur.pointed_node());
}
} }
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
@@ -1256,7 +1395,7 @@ class slist_impl
//! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
void unique() void unique()
{ unique_and_dispose(std::equal_to<value_type>(), detail::null_disposer()); } { this->unique_and_dispose(std::equal_to<value_type>(), detail::null_disposer()); }
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that satisfy some binary predicate from the list. //! elements that satisfy some binary predicate from the list.
@@ -1270,7 +1409,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class BinaryPredicate> template<class BinaryPredicate>
void unique(BinaryPredicate pred) void unique(BinaryPredicate pred)
{ unique_and_dispose(pred, detail::null_disposer()); } { this->unique_and_dispose(pred, detail::null_disposer()); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1286,7 +1425,7 @@ class slist_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Disposer> template<class Disposer>
void unique_and_dispose(Disposer disposer) void unique_and_dispose(Disposer disposer)
{ unique(std::equal_to<value_type>(), disposer); } { this->unique(std::equal_to<value_type>(), disposer); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1303,21 +1442,23 @@ class slist_impl
template<class BinaryPredicate, class Disposer> template<class BinaryPredicate, class Disposer>
void unique_and_dispose(BinaryPredicate pred, Disposer disposer) void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
{ {
iterator end_n(end()); iterator end_n(this->end());
iterator cur(begin()); iterator bcur(this->begin());
iterator cur_next; if(bcur != end_n){
iterator cur(bcur);
if (cur != end_n) { ++cur;
while(++(cur_next = cur) != end_n) { while(cur != end_n) {
if (pred(*cur, *cur_next)){ if (pred(*bcur, *cur)){
pointer p = cur_next.operator->(); cur = this->erase_after_and_dispose(bcur, disposer);
this->erase_after(cur);
disposer(p);
} }
else{ else{
bcur = cur;
++cur; ++cur;
} }
} }
if(cache_last){
this->set_last_node(bcur.pointed_node());
}
} }
} }
@@ -1394,11 +1535,15 @@ class slist_impl
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements before i. //! <b>Complexity</b>: Linear to the number of elements before i.
//! Constant if cache_last<> is true and i == end().
iterator previous(iterator i) iterator previous(iterator i)
{ {
if(cache_last && (i.pointed_node() == this->get_end_node())){
return iterator(this->get_last_node(), this);
}
return iterator return iterator
(node_algorithms::get_previous_node (node_algorithms::get_previous_node
(before_begin().pointed_node(), i.pointed_node()), 0); (this->before_begin().pointed_node(), i.pointed_node()), this);
} }
//! <b>Returns</b>: The const_iterator to the element before i in the list. //! <b>Returns</b>: The const_iterator to the element before i in the list.
@@ -1408,14 +1553,30 @@ class slist_impl
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Linear to the number of elements before i. //! <b>Complexity</b>: Linear to the number of elements before i.
//! Constant if cache_last<> is true and i == end().
const_iterator previous(const_iterator i) const 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 return const_iterator
(node_algorithms::get_previous_node (node_algorithms::get_previous_node
(before_begin().pointed_node(), i.pointed_node()), 0); (this->before_begin().pointed_node(), i.pointed_node()), this);
} }
private: 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_<false>) void priv_reverse(detail::bool_<false>)
{ node_algorithms::reverse(this->get_root_node()); } { node_algorithms::reverse(this->get_root_node()); }
@@ -1429,26 +1590,63 @@ class slist_impl
void priv_shift_backwards(size_type n, detail::bool_<false>) void priv_shift_backwards(size_type n, detail::bool_<false>)
{ {
node_algorithms::move_forward(this->get_root_node(), (std::size_t)n); 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_<true>) void priv_shift_backwards(size_type n, detail::bool_<true>)
{ {
node_ptr new_first = node_algorithms::move_forward std::pair<node_ptr, node_ptr> ret(
(node_traits::get_next(this->get_root_node()), (std::size_t)n); node_algorithms::move_first_n_forward
node_traits::set_next(this->get_root_node(), new_first); (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_<false>) void priv_shift_forward(size_type n, detail::bool_<false>)
{ {
node_algorithms::move_backwards(this->get_root_node(), (std::size_t)n); 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_<true>) void priv_shift_forward(size_type n, detail::bool_<true>)
{ {
node_ptr new_first = node_algorithms::move_backwards std::pair<node_ptr, node_ptr> ret(
(node_traits::get_next(this->get_root_node()), (std::size_t)n); node_algorithms::move_first_n_backwards
node_traits::set_next(this->get_root_node(), new_first); (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 //circular version
@@ -1465,7 +1663,7 @@ class slist_impl
//singly linked lists (because "end" is represented by the null pointer) //singly linked lists (because "end" is represented by the null pointer)
BOOST_STATIC_ASSERT(!linear); BOOST_STATIC_ASSERT(!linear);
root_plus_size *r = detail::parent_from_member<root_plus_size, node> root_plus_size *r = detail::parent_from_member<root_plus_size, node>
( 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<data_t, root_plus_size> data_t *d = detail::parent_from_member<data_t, root_plus_size>
( r, &data_t::root_plus_size_); ( r, &data_t::root_plus_size_);
slist_impl *s = detail::parent_from_member<slist_impl, data_t>(d, &slist_impl::data_); slist_impl *s = detail::parent_from_member<slist_impl, data_t>(d, &slist_impl::data_);
@@ -1595,13 +1793,13 @@ inline void swap
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template<class T, class ...Options> template<class T, class ...Options>
#else #else
template<class T, class O1 = none, class O2 = none, class O3 = none, class O4 = none> template<class T, class O1 = none, class O2 = none, class O3 = none, class O4 = none, class O5 = none>
#endif #endif
struct make_slist struct make_slist
{ {
/// @cond /// @cond
typedef typename pack_options typedef typename pack_options
< slist_defaults<T>, O1, O2, O3, O4>::type packed_options; < slist_defaults<T>, O1, O2, O3, O4, O5>::type packed_options;
typedef typename detail::get_value_traits typedef typename detail::get_value_traits
<T, typename packed_options::value_traits>::type value_traits; <T, typename packed_options::value_traits>::type value_traits;
typedef slist_impl typedef slist_impl
@@ -1611,6 +1809,7 @@ struct make_slist
, typename packed_options::size_type , typename packed_options::size_type
, packed_options::constant_time_size , packed_options::constant_time_size
, packed_options::linear , packed_options::linear
, packed_options::cache_last
> >
> implementation_defined; > implementation_defined;
/// @endcond /// @endcond
@@ -1619,12 +1818,12 @@ struct make_slist
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template<class T, class O1, class O2, class O3, class O4> template<class T, class O1, class O2, class O3, class O4, class O5>
class slist class slist
: public make_slist<T, O1, O2, O3, O4>::type : public make_slist<T, O1, O2, O3, O4, O5>::type
{ {
typedef typename make_slist typedef typename make_slist
<T, O1, O2, O3, O4>::type Base; <T, O1, O2, O3, O4, O5>::type Base;
typedef typename Base::real_value_traits real_value_traits; typedef typename Base::real_value_traits real_value_traits;
//Assert if passed value traits are compatible with the type //Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value)); BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));

View File

@@ -216,6 +216,9 @@
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\avltree_node.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\avltree_node.hpp">
</File> </File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\common_slist_algorithms.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\config_begin.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\config_begin.hpp">
</File> </File>

View File

@@ -237,7 +237,7 @@ struct testvalue
// have to be handled appropriately when copied: // have to be handled appropriately when copied:
testvalue & operator= (const testvalue& src) testvalue & operator= (const testvalue& src)
{ {/*
set_base_hook_t::operator=(src); set_base_hook_t::operator=(src);
set_auto_base_hook_t::operator=(src); set_auto_base_hook_t::operator=(src);
this->set_node_ = src.set_node_; this->set_node_ = src.set_node_;
@@ -270,7 +270,7 @@ struct testvalue
slist_auto_base_hook_t::operator=(src); slist_auto_base_hook_t::operator=(src);
this->slist_node_ = src.slist_node_; this->slist_node_ = src.slist_node_;
this->slist_auto_node_ = src.slist_auto_node_; this->slist_auto_node_ = src.slist_auto_node_;
*/
value_ = src.value_; value_ = src.value_;
return *this; return *this;
} }
@@ -366,6 +366,14 @@ struct even_odd
} }
}; };
struct is_even
{
template<class VoidPointer, bool constant_time_size>
bool operator()
(const testvalue<VoidPointer, constant_time_size>& v1) const
{ return (v1.value_ & 1) == 0; }
};
} //namespace boost{ } //namespace boost{
} //namespace intrusive{ } //namespace intrusive{

View File

@@ -31,6 +31,8 @@ struct test_list
static void test_all(std::vector<value_type>& values); static void test_all(std::vector<value_type>& values);
static void test_front_back(std::vector<value_type>& values); static void test_front_back(std::vector<value_type>& values);
static void test_sort(std::vector<value_type>& values); static void test_sort(std::vector<value_type>& values);
static void test_merge(std::vector<value_type>& values);
static void test_remove_unique(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values); static void test_insert(std::vector<value_type>& values);
static void test_shift(std::vector<value_type>& values); static void test_shift(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values); static void test_swap(std::vector<value_type>& values);
@@ -58,6 +60,8 @@ void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_ty
test_front_back(values); test_front_back(values);
test_sort(values); test_sort(values);
test_merge(values);
test_remove_unique(values);
test_insert(values); test_insert(values);
test_shift(values); test_shift(values);
test_swap(values); test_swap(values);
@@ -127,6 +131,60 @@ void test_list<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
} }
//test: merge due to error in merge implementation:
template<class ValueTraits>
void test_list<ValueTraits>
::test_remove_unique (std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef list
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_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<typename ValueTraits::value_type> 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<class ValueTraits>
void test_list<ValueTraits>
::test_merge (std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef list
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_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: //test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ValueTraits> template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>

View File

@@ -24,14 +24,17 @@
using namespace boost::intrusive; using namespace boost::intrusive;
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
struct test_slist struct test_slist
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
static void test_all(std::vector<value_type>& values); static void test_all(std::vector<value_type>& values);
static void test_front_back (std::vector<value_type>& values); static void test_front(std::vector<value_type>& values);
static void test_back(std::vector<value_type>& values, detail::bool_<true>);
static void test_back(std::vector<value_type>& values, detail::bool_<false>);
static void test_sort(std::vector<value_type>& values); static void test_sort(std::vector<value_type>& values);
static void test_merge(std::vector<value_type>& values); static void test_merge(std::vector<value_type>& values);
static void test_remove_unique(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values); static void test_insert(std::vector<value_type>& values);
static void test_shift(std::vector<value_type>& values); static void test_shift(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values); static void test_swap(std::vector<value_type>& values);
@@ -41,8 +44,8 @@ struct test_slist
static void test_container_from_end(std::vector<value_type> &values, detail::bool_<false>); static void test_container_from_end(std::vector<value_type> &values, detail::bool_<false>);
}; };
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_all (std::vector<typename ValueTraits::value_type>& values) ::test_all (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -52,6 +55,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
{ {
list_type list(values.begin(), values.end()); list_type list(values.begin(), values.end());
@@ -60,9 +64,11 @@ void test_slist<ValueTraits, Linear>
list.insert(list.end(), values.begin(), values.end()); list.insert(list.end(), values.begin(), values.end());
test::test_sequence_container(list, values); test::test_sequence_container(list, values);
} }
test_front_back (values); test_front(values);
test_back(values, detail::bool_<CacheLast>());
test_sort(values); test_sort(values);
test_merge (values); test_merge (values);
test_remove_unique(values);
test_insert(values); test_insert(values);
test_shift(values); test_shift(values);
test_slow_insert (values); test_slow_insert (values);
@@ -72,9 +78,9 @@ void test_slist<ValueTraits, Linear>
} }
//test: push_front, pop_front, front, size, empty: //test: push_front, pop_front, front, size, empty:
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_front_back (std::vector<typename ValueTraits::value_type>& values) ::test_front(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef slist typedef slist
@@ -83,6 +89,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist; list_type testlist;
BOOST_TEST (testlist.empty()); BOOST_TEST (testlist.empty());
@@ -103,9 +110,43 @@ void test_slist<ValueTraits, Linear>
BOOST_TEST (testlist.empty()); BOOST_TEST (testlist.empty());
} }
//test: push_front, pop_front, front, size, empty:
template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear, CacheLast>
::test_back(std::vector<typename ValueTraits::value_type>& values, detail::bool_<true>)
{
typedef typename ValueTraits::value_type value_type;
typedef slist
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type;
list_type testlist;
BOOST_TEST (testlist.empty());
testlist.push_back (values[0]);
BOOST_TEST (testlist.size() == 1);
BOOST_TEST (&testlist.front() == &values[0]);
BOOST_TEST (&testlist.back() == &values[0]);
testlist.push_back(values[1]);
BOOST_TEST(*testlist.previous(testlist.end()) == values[1]);
BOOST_TEST (&testlist.front() == &values[0]);
BOOST_TEST (&testlist.back() == &values[1]);
}
//test: push_front, pop_front, front, size, empty:
template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear, CacheLast>
::test_back(std::vector<typename ValueTraits::value_type>&, detail::bool_<false>)
{}
//test: merge due to error in merge implementation: //test: merge due to error in merge implementation:
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_merge (std::vector<typename ValueTraits::value_type>& values) ::test_merge (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -115,6 +156,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist1, testlist2; list_type testlist1, testlist2;
testlist1.push_front (values[0]); testlist1.push_front (values[0]);
@@ -127,9 +169,42 @@ void test_slist<ValueTraits, Linear>
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() );
} }
//test: merge due to error in merge implementation:
template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear, CacheLast>
::test_remove_unique (std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef slist
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> 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<typename ValueTraits::value_type> values2(values);
list_type list(values.begin(), values.end());
list.insert_after(list.before_begin(), 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: constructor, iterator, sort, reverse: //test: constructor, iterator, sort, reverse:
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_sort(std::vector<typename ValueTraits::value_type>& values) ::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -139,6 +214,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist (values.begin(), values.end()); list_type testlist (values.begin(), values.end());
@@ -155,8 +231,8 @@ void test_slist<ValueTraits, Linear>
} }
//test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous: //test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous:
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_insert(std::vector<typename ValueTraits::value_type>& values) ::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -166,6 +242,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist; list_type testlist;
testlist.assign (&values[0] + 2, &values[0] + 5); testlist.assign (&values[0] + 2, &values[0] + 5);
@@ -195,8 +272,8 @@ void test_slist<ValueTraits, Linear>
} }
//test: insert, const_iterator, erase, siterator_to: //test: insert, const_iterator, erase, siterator_to:
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_slow_insert (std::vector<typename ValueTraits::value_type>& values) ::test_slow_insert (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -206,6 +283,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist; list_type testlist;
testlist.push_front (values[4]); testlist.push_front (values[4]);
@@ -239,8 +317,8 @@ void test_slist<ValueTraits, Linear>
BOOST_TEST (testlist.front().value_ == 3); BOOST_TEST (testlist.front().value_ == 3);
} }
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_shift(std::vector<typename ValueTraits::value_type>& values) ::test_shift(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -250,6 +328,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist; list_type testlist;
@@ -285,8 +364,8 @@ void test_slist<ValueTraits, Linear>
} }
//test: insert_after (seq-version), swap, splice_after: //test: insert_after (seq-version), swap, splice_after:
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_swap(std::vector<typename ValueTraits::value_type>& values) ::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -296,6 +375,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
{ {
list_type testlist1 (&values[0], &values[0] + 2); list_type testlist1 (&values[0], &values[0] + 2);
@@ -363,8 +443,8 @@ void test_slist<ValueTraits, Linear>
} }
} }
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -374,6 +454,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist1 (&values[0], &values[0] + values.size()); list_type testlist1 (&values[0], &values[0] + values.size());
@@ -385,8 +466,8 @@ void test_slist<ValueTraits, Linear>
BOOST_TEST (testlist2.empty()); BOOST_TEST (testlist2.empty());
} }
template<class ValueTraits, bool Linear> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear> void test_slist<ValueTraits, Linear, CacheLast>
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values ::test_container_from_end(std::vector<typename ValueTraits::value_type>& values
,detail::bool_<false>) ,detail::bool_<false>)
{ {
@@ -397,6 +478,7 @@ void test_slist<ValueTraits, Linear>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear> , linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist1 (&values[0], &values[0] + values.size()); list_type testlist1 (&values[0], &values[0] + values.size());
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end())); BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
@@ -419,6 +501,7 @@ class test_main_template
, typename value_type::slist_base_hook_t , typename value_type::slist_base_hook_t
>::type >::type
, false , false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits test_slist < typename detail::get_member_value_traits
< value_type < value_type
@@ -428,6 +511,7 @@ class test_main_template
> >
>::type >::type
, false , false
, false
>::test_all(data); >::test_all(data);
//Now linear slists //Now linear slists
@@ -436,6 +520,46 @@ class test_main_template
, typename value_type::slist_base_hook_t , typename value_type::slist_base_hook_t
>::type >::type
, true , true
, false
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, true
, false
>::test_all(data);
//Now the same but caching the last node
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, false
, true
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, false
, true
>::test_all(data);
//Now linear slists
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, true
, true
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits test_slist < typename detail::get_member_value_traits
@@ -446,8 +570,8 @@ class test_main_template
> >
>::type >::type
, true , true
, true
>::test_all(data); >::test_all(data);
return 0; return 0;
} }
}; };
@@ -468,6 +592,7 @@ class test_main_template<VoidPointer, false>
, typename value_type::slist_base_hook_t , typename value_type::slist_base_hook_t
>::type >::type
, false , false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits test_slist < typename detail::get_member_value_traits
@@ -478,6 +603,7 @@ class test_main_template<VoidPointer, false>
> >
>::type >::type
, false , false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_base_value_traits test_slist < typename detail::get_base_value_traits
@@ -485,6 +611,7 @@ class test_main_template<VoidPointer, false>
, typename value_type::slist_auto_base_hook_t , typename value_type::slist_auto_base_hook_t
>::type >::type
, false , false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits test_slist < typename detail::get_member_value_traits
@@ -495,6 +622,7 @@ class test_main_template<VoidPointer, false>
> >
>::type >::type
, false , false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_base_value_traits test_slist < typename detail::get_base_value_traits
@@ -502,6 +630,27 @@ class test_main_template<VoidPointer, false>
, typename value_type::slist_base_hook_t , typename value_type::slist_base_hook_t
>::type >::type
, true , true
, false
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, true
, false
>::test_all(data);
//Now cache last
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, false
, true
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits test_slist < typename detail::get_member_value_traits
@@ -511,6 +660,26 @@ class test_main_template<VoidPointer, false>
, &value_type::slist_node_ , &value_type::slist_node_
> >
>::type >::type
, false
, true
>::test_all(data);
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, true
, true
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, true
, true , true
>::test_all(data); >::test_all(data);
return 0; return 0;