diff --git a/include/boost/intrusive/circular_slist_algorithms.hpp b/include/boost/intrusive/circular_slist_algorithms.hpp index 92dc5cc..5ce4e8c 100644 --- a/include/boost/intrusive/circular_slist_algorithms.hpp +++ b/include/boost/intrusive/circular_slist_algorithms.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #if defined(BOOST_HAS_PRAGMA_ONCE) @@ -131,6 +132,10 @@ class circular_slist_algorithms //! //! Throws: Nothing. static void transfer_after(node_ptr p, node_ptr b, node_ptr e) BOOST_NOEXCEPT; + + #else + + using base_t::transfer_after; #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) @@ -144,6 +149,41 @@ class circular_slist_algorithms BOOST_INTRUSIVE_FORCEINLINE static void init_header(node_ptr this_node) BOOST_NOEXCEPT { NodeTraits::set_next(this_node, this_node); } + //! Requires: 'p' is the first node of a list. + //! + //! Effects: Returns a pointer to a node that represents the "end" (one past end) node + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + BOOST_INTRUSIVE_FORCEINLINE static node_ptr end_node(const_node_ptr p) BOOST_NOEXCEPT + { return detail::uncast(p); } + + //! Effects: Returns true if this_node_points to an empty list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + BOOST_INTRUSIVE_FORCEINLINE static bool is_empty(const_node_ptr this_node) BOOST_NOEXCEPT + { return NodeTraits::get_next(this_node) == this_node; } + + //! Effects: Returns true if this_node points to a sentinel node. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + BOOST_INTRUSIVE_FORCEINLINE static bool is_sentinel(const_node_ptr this_node) BOOST_NOEXCEPT + { return NodeTraits::get_next(this_node) == node_ptr(); } + + //! Effects: Marks this node as a "sentinel" node, a special state that is different from "empty", + //! that can be used to mark a special state of the list + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + BOOST_INTRUSIVE_FORCEINLINE static void set_sentinel(node_ptr this_node) BOOST_NOEXCEPT + { NodeTraits::set_next(this_node, node_ptr()); } + //! Requires: this_node and prev_init_node must be in the same circular list. //! //! Effects: Returns the previous node of this_node in the circular list starting. @@ -386,6 +426,35 @@ class circular_slist_algorithms base_t::link_after(new_last, p); return new_last; } + + //! Requires: other must be a list and p must be a node of a different list. + //! + //! Effects: Transfers all nodes from other after p in p's list. + //! + //! Complexity: Linear + //! + //! Throws: Nothing. + static void transfer_after(node_ptr p, node_ptr other) BOOST_NOEXCEPT + { + node_ptr other_last((get_previous_node)(other)); + base_t::transfer_after(p, other, other_last); + } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Unlinks all nodes reachable from p (but not p) and calls + //! void disposer::operator()(node_ptr) for every node of the list + //! where p is linked. + //! + //! Returns: The number of disposed nodes + //! + //! Complexity: Linear to the number of element of the list. + //! + //! Throws: Nothing. + template + BOOST_INTRUSIVE_FORCEINLINE static std::size_t detach_and_dispose(node_ptr p, Disposer disposer) BOOST_NOEXCEPT + { return base_t::unlink_after_and_dispose(p, p, disposer); } }; /// @cond diff --git a/include/boost/intrusive/linear_slist_algorithms.hpp b/include/boost/intrusive/linear_slist_algorithms.hpp index a9030f7..a616d7e 100644 --- a/include/boost/intrusive/linear_slist_algorithms.hpp +++ b/include/boost/intrusive/linear_slist_algorithms.hpp @@ -138,6 +138,10 @@ class linear_slist_algorithms //! Throws: Nothing. static void transfer_after(node_ptr p, node_ptr b, node_ptr e) BOOST_NOEXCEPT; + #else + + using base_t::transfer_after; + #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Constructs an empty list, making this_node the only @@ -150,6 +154,41 @@ class linear_slist_algorithms BOOST_INTRUSIVE_FORCEINLINE static void init_header(node_ptr this_node) BOOST_NOEXCEPT { NodeTraits::set_next(this_node, node_ptr ()); } + //! Requires: 'p' is the first node of a list. + //! + //! Effects: Returns a pointer to a node that represents the "end" (one past end) node + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + BOOST_INTRUSIVE_FORCEINLINE static node_ptr end_node(const_node_ptr) BOOST_NOEXCEPT + { return node_ptr(); } + + //! Effects: Returns true if this_node_points to an empty list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + BOOST_INTRUSIVE_FORCEINLINE static bool is_empty(const_node_ptr this_node) BOOST_NOEXCEPT + { return !NodeTraits::get_next(this_node); } + + //! Effects: Returns true if this_node points to a sentinel node. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + BOOST_INTRUSIVE_FORCEINLINE static bool is_sentinel(const_node_ptr this_node) BOOST_NOEXCEPT + { return NodeTraits::get_next(this_node) == this_node; } + + //! Effects: Marks this node as a "sentinel" node, a special state that is different from "empty", + //! that can be used to mark a special state of the list + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + BOOST_INTRUSIVE_FORCEINLINE static void set_sentinel(node_ptr this_node) BOOST_NOEXCEPT + { NodeTraits::set_next(this_node, this_node); } + //! Requires: this_node and prev_init_node must be in the same linear list. //! //! Effects: Returns the previous node of this_node in the linear list starting. @@ -329,6 +368,40 @@ class linear_slist_algorithms ret.second = new_last; return ret; } + + //! Requires: other must be a list and p must be a node of a different linear list. + //! + //! Effects: Transfers all nodes from other after p in p's linear list. + //! + //! Complexity: Linear + //! + //! Throws: Nothing. + static void transfer_after(node_ptr p, node_ptr other) BOOST_NOEXCEPT + { + if ((is_empty)(p)) { + (swap_trailing_nodes)(p, other); + } + else { + node_ptr other_last((get_previous_node)(other, node_ptr())); + base_t::transfer_after(p, other, other_last); + } + } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Unlinks all nodes reachable from p (but not p) and calls + //! void disposer::operator()(node_ptr) for every node of the list + //! where p is linked. + //! + //! Returns: The number of disposed nodes + //! + //! Complexity: Linear to the number of element of the list. + //! + //! Throws: Nothing. + template + BOOST_INTRUSIVE_FORCEINLINE static std::size_t detach_and_dispose(node_ptr p, Disposer disposer) BOOST_NOEXCEPT + { return base_t::unlink_after_and_dispose(p, node_ptr(), disposer); } }; /// @cond