--- /dev/null
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright Olaf Krzikalla 2004-2006.\r
+// (C) Copyright Ion GaztaƱaga 2006-2007\r
+//\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+// See http://www.boost.org/libs/intrusive for documentation.\r
+//\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef BOOST_INTRUSIVE_ISLIST_HPP\r
+#define BOOST_INTRUSIVE_ISLIST_HPP\r
+\r
+#include "detail/config_begin.hpp"\r
+#include <boost/utility.hpp>\r
+#include <boost/static_assert.hpp>\r
+#include <boost/assert.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+#include "islist_hook.hpp"\r
+#include "slist_algorithms.hpp"\r
+#include "detail/pointer_type.hpp"\r
+#include "detail/pointer_to_other.hpp"\r
+#include "linking_policy.hpp"\r
+#include <iterator>\r
+#include <cstddef>\r
+\r
+namespace boost {\r
+namespace intrusive {\r
+\r
+//! The class template islist is an intrusive container, that encapsulates \r
+//! a singly-linked list. You can use such a list to squeeze the last bit \r
+//! of performance from your application. Unfortunately, the little gains \r
+//! come with some huge drawbacks. A lot of member functions can't be \r
+//! implemented as efficiently as for standard containers. To overcome \r
+//! this limitation some other member functions with rather unusual semantics \r
+//! have to be introduced.\r
+//!\r
+//! The template parameter ValueTraits is called "value traits". It stores\r
+//! information and operations about the type to be stored in the container.\r
+//!\r
+//! If the user specifies ConstantTimeSize as "true", a member of type SizeType\r
+//! will be embedded in the class, that will keep track of the number of stored objects.\r
+//! This will allow constant-time O(1) size() member, instead of default O(N) size.\r
+//! \r
+//! The iterators of islist are forward iterators. islist provides a static \r
+//! function called "previous" to compute the previous iterator of a given iterator. \r
+//! This function has linear complexity. To improve the usability esp. with \r
+//! the '*_after' functions, ++end() == begin() and previous(begin()) == end() \r
+//! are defined. In addition, whenever you have an end iterator, 'after this \r
+//! iterator' means 'at the beginning of the list'. To improve the self-documentation\r
+//! a "before_begin()" function is defined, returning the end() iterator.\r
+template < class ValueTraits\r
+ , bool ConstantTimeSize = true\r
+ , class SizeType = std::size_t>\r
+class islist\r
+ : private detail::size_holder<ConstantTimeSize, SizeType>\r
+{\r
+ private:\r
+ typedef islist<ValueTraits, ConstantTimeSize, SizeType> this_type; \r
+ typedef typename ValueTraits::node_traits node_traits;\r
+ typedef detail::size_holder<ConstantTimeSize, SizeType> size_traits;\r
+\r
+ //! This class is\r
+ //! non-copyable\r
+ islist (const islist&);\r
+\r
+ //! This class is\r
+ //! non-asignable\r
+ islist &operator =(const islist&);\r
+\r
+ //Public typedefs\r
+ public:\r
+ typedef typename ValueTraits::value_type value_type;\r
+ typedef typename ValueTraits::pointer pointer;\r
+ typedef typename ValueTraits::const_pointer const_pointer;\r
+ typedef value_type& reference;\r
+ typedef const value_type& const_reference;\r
+ typedef SizeType size_type;\r
+ typedef typename std::iterator_traits\r
+ <pointer>::difference_type difference_type;\r
+\r
+ class iterator;\r
+ class const_iterator;\r
+ friend class iterator;\r
+ friend class const_iterator;\r
+\r
+ private:\r
+ typedef typename node_traits::node node;\r
+ typedef typename boost::pointer_to_other\r
+ <pointer, node>::type node_ptr;\r
+ typedef typename boost::pointer_to_other\r
+ <pointer, const node>::type const_node_ptr;\r
+ typedef slist_algorithms<node_traits> node_algorithms;\r
+ enum { safemode_or_autounlink = \r
+ (int)ValueTraits::linking_policy == (int)auto_unlink ||\r
+ (int)ValueTraits::linking_policy == (int)safe_mode_link };\r
+\r
+ //Constant-time size is incompatible with auto-unlink hooks!\r
+ BOOST_STATIC_ASSERT(!(ConstantTimeSize && ((int)ValueTraits::linking_policy == (int)auto_unlink)));\r
+\r
+ node root;\r
+\r
+ node_ptr get_root_node()\r
+ { return node_ptr(&root); }\r
+\r
+ const_node_ptr get_root_node() const\r
+ { return const_node_ptr(&root); }\r
+\r
+ static node_ptr uncast(const_node_ptr ptr)\r
+ {\r
+ using boost::get_pointer;\r
+ return node_ptr(const_cast<node*>(get_pointer(ptr)));\r
+ }\r
+\r
+ static iterator previous_node(iterator beg, iterator i)\r
+ {\r
+ return iterator\r
+ (node_algorithms::get_previous_node(beg.list_node(), i.list_node()));\r
+ }\r
+\r
+ static const_iterator previous_node(const_iterator beg, const_iterator i)\r
+ {\r
+ return const_iterator\r
+ (node_algorithms::get_previous_node(beg.list_node(), i.list_node()));\r
+ }\r
+\r
+ //This functor compares a stored value\r
+ //and the one passed as an argument\r
+ class equal_to_value\r
+ {\r
+ const value_type &t_;\r
+\r
+ public:\r
+ equal_to_value(const value_type &t)\r
+ : t_(t)\r
+ {}\r
+\r
+ bool operator()(const value_type &t)const\r
+ { return t_ == t; }\r
+ };\r
+\r
+ public:\r
+\r
+ //!The forward iterator of the container\r
+ class iterator\r
+ : public detail::slist_iterator<value_type, iterator, node_traits>\r
+ {\r
+ private:\r
+ // gcc warns about an ambiguity between iterator::value_type and\r
+ // islist<ValueTraits>::value_type, thus I introduce a unique name:\r
+ typedef typename islist<ValueTraits, ConstantTimeSize, SizeType>::value_type private_vt;\r
+ typedef typename islist<ValueTraits, ConstantTimeSize, SizeType>::pointer private_pointer;\r
+ typedef typename islist<ValueTraits, ConstantTimeSize, SizeType>::reference private_reference;\r
+ typedef detail::slist_iterator<private_vt, iterator, node_traits> inherited;\r
+\r
+ public:\r
+ iterator ()\r
+ {}\r
+\r
+ private_pointer operator->() const\r
+ { return ValueTraits::to_value_ptr(this->list_node()); }\r
+\r
+ private_reference operator*() const\r
+ { return *ValueTraits::to_value_ptr(this->list_node()); }\r
+\r
+ node_ptr list_node()const\r
+ { return inherited::list_node(); }\r
+\r
+ private:\r
+ explicit iterator (node_ptr node)\r
+ : inherited (node)\r
+ {}\r
+\r
+ friend class islist<ValueTraits, ConstantTimeSize, SizeType>;\r
+ friend class detail::slist_iterator<private_vt, iterator, node_traits>;\r
+ friend class const_iterator;\r
+ };\r
+\r
+ //!The forward const_iterator of the container\r
+ class const_iterator\r
+ : public detail::slist_iterator<const value_type, const_iterator, node_traits>\r
+ {\r
+ private:\r
+ typedef const typename islist<ValueTraits, ConstantTimeSize, SizeType>::value_type private_vt;\r
+ typedef typename islist<ValueTraits, ConstantTimeSize, SizeType>::const_pointer private_pointer;\r
+ typedef typename islist<ValueTraits, ConstantTimeSize, SizeType>::const_reference private_reference;\r
+ typedef detail::slist_iterator<private_vt, const_iterator, node_traits> inherited;\r
+ \r
+ public: \r
+ const_iterator()\r
+ {}\r
+\r
+ const_iterator(const typename islist::iterator& it)\r
+ : inherited (it.list_node())\r
+ {}\r
+\r
+ const_iterator & operator=(const typename islist::iterator& it)\r
+ { return inherited::operator=(it.list_node()); }\r
+\r
+ private_pointer operator->()\r
+ { return ValueTraits::to_value_ptr(this->list_node()); }\r
+\r
+ private_reference operator*()\r
+ { return *ValueTraits::to_value_ptr(this->list_node()); }\r
+ \r
+ private:\r
+ explicit const_iterator (const_node_ptr node)\r
+ : inherited (uncast(node))\r
+ {}\r
+\r
+ friend class islist<ValueTraits, ConstantTimeSize, SizeType>;\r
+ friend class detail::slist_iterator<private_vt, const_iterator, node_traits>;\r
+ };\r
+\r
+ public:\r
+\r
+ //! <b>Effects</b>: constructs an empty list. \r
+ //! \r
+ //! <b>Complexity</b>: Constant \r
+ //! \r
+ //! <b>Throws</b>: If value_traits::node_traits::node\r
+ //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).\r
+ islist()\r
+ {\r
+ size_traits::set_size(size_type(0));\r
+ node_algorithms::init(node_ptr(&root)); \r
+ }\r
+\r
+ //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.\r
+ //! \r
+ //! <b>Effects</b>: Constructs a list equal to [first,last).\r
+ //! \r
+ //! <b>Complexity</b>: Linear in std::distance(b, e). No copy constructors are called. \r
+ //! \r
+ //! <b>Throws</b>: If value_traits::node_traits::node\r
+ //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).\r
+ template<class Iterator>\r
+ islist(Iterator b, Iterator e)\r
+ {\r
+ size_traits::set_size(size_type(0));\r
+ node_algorithms::init(node_ptr(&root));\r
+ insert_after(before_begin(), b, e);\r
+ }\r
+\r
+ //! <b>Effects</b>: If it's a safe-mode\r
+ //! or auto-unlink value, the destructor does nothing\r
+ //! (ie. no code is generated). Otherwise it detaches all elements from this. \r
+ //! In this case the objects in the list are not deleted (i.e. no destructors \r
+ //! are called), but the hooks according to the ValueTraits template parameter\r
+ //! are set to their default value.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements in the list, if \r
+ //! it's a safe-mode or auto-unlink value. Otherwise constant.\r
+ ~islist()\r
+ { this->clear(); }\r
+\r
+ //! <b>Effects</b>: Erases all the elements of the container.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements of the list.\r
+ //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased elements.\r
+ void clear()\r
+ {\r
+ if(safemode_or_autounlink){\r
+ this->erase_after(this->before_begin(), this->end()); \r
+ }\r
+ else{\r
+ node_algorithms::init(node_ptr(&root));\r
+ size_traits::set_size(size_type(0));\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Erases all the elements of the container\r
+ //! Destroyer::operator()(pointer) is called for the removed elements.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements of the list.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators to the erased elements.\r
+ template <class Destroyer>\r
+ void clear_and_destroy(Destroyer destroyer)\r
+ { this->erase_after_and_destroy(this->before_begin(), this->end(), destroyer); }\r
+\r
+ //! <b>Requires</b>: value must be an lvalue.\r
+ //! \r
+ //! <b>Effects</b>: Inserts the value in the front of the list.\r
+ //! No copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ //! \r
+ //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+ void push_front(value_type &value) \r
+ {\r
+ node_ptr to_insert(ValueTraits::to_node_ptr(value));\r
+ if(safemode_or_autounlink)\r
+ BOOST_ASSERT(node_algorithms::unique(to_insert));\r
+ node_algorithms::link_after(get_root_node(), to_insert); \r
+ size_traits::increment();\r
+ }\r
+\r
+ //! <b>Effects</b>: Erases the first element of the list.\r
+ //! No destructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.\r
+ void pop_front() \r
+ {\r
+ node_ptr to_erase = node_traits::get_next(get_root_node());\r
+ node_algorithms::unlink_after(get_root_node());\r
+ size_traits::decrement();\r
+ if(safemode_or_autounlink)\r
+ node_algorithms::init(to_erase);\r
+ }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Erases the first element of the list.\r
+ //! Destroyer::operator()(pointer) is called for the removed element.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators to the erased element.\r
+ template<class Destroyer>\r
+ void pop_front_and_destroy(Destroyer destroyer)\r
+ {\r
+ node_ptr to_erase = node_traits::get_next(get_root_node());\r
+ this->pop_front();\r
+ destroyer(ValueTraits::to_value_ptr(to_erase));\r
+ }\r
+\r
+ //! <b>Effects</b>: Returns a reference to the first element of the list.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ reference front()\r
+ { return *ValueTraits::to_value_ptr(node_traits::get_next(get_root_node())); }\r
+\r
+ //! <b>Effects</b>: Returns a const_reference to the first element of the list.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ const_reference front() const\r
+ { return *ValueTraits::to_value_ptr(uncast(node_traits::get_next(const_node_ptr(&root)))); }\r
+\r
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the list.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ iterator begin() \r
+ { return iterator (node_traits::get_next(get_root_node())); }\r
+\r
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ const_iterator begin() const \r
+ { return const_iterator (node_traits::get_next(get_root_node())); }\r
+\r
+ //! <b>Effects</b>: Returns an iterator to the end of the list.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ iterator end() \r
+ { return iterator (get_root_node()); }\r
+\r
+ //! <b>Effects</b>: Returns a const_iterator to the end of the list.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ const_iterator end() const \r
+ { return const_iterator (get_root_node()); }\r
+\r
+ //! <b>Effects</b>: Returns an iterator that points to a position\r
+ //! before the first element. Equivalent to "end()"\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ iterator before_begin() \r
+ { return end(); }\r
+\r
+ //! <b>Effects</b>: Returns an iterator that points to a position\r
+ //! before the first element. Equivalent to "end()"\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ const_iterator before_begin() const \r
+ { return end(); }\r
+\r
+ //! <b>Effects</b>: Returns the number of the elements contained in the list.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements contained in the list.\r
+ //! if ConstantTimeSize is false. Constant time otherwise.\r
+ //! \r
+ //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+ size_type size() const\r
+ {\r
+ if(ConstantTimeSize)\r
+ return size_traits::get_size();\r
+ else\r
+ return node_algorithms::count(const_node_ptr(&root)) - 1; \r
+ }\r
+\r
+ //! <b>Effects</b>: Returns true if the list contains no elements.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ //! \r
+ //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+ bool empty() const\r
+ { return node_algorithms::unique(get_root_node()); }\r
+\r
+ //! <b>Effects</b>: Swaps the elements of x and *this.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements of both lists.\r
+ //! \r
+ //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+ void swap(islist& other)\r
+ {\r
+ node_algorithms::swap_nodes(get_root_node(), &other.root);\r
+ if(ConstantTimeSize){\r
+ size_type backup = size_traits::get_size();\r
+ size_traits::set_size(other.get_size());\r
+ other.set_size(backup);\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Erases all the elements from *this\r
+ //! calling Destroyer::operator()(pointer), clones all the \r
+ //! elements from src calling Cloner::operator()(const value_type &)\r
+ //! and inserts them on *this.\r
+ //!\r
+ //! If cloner throws, all cloned elements are unlinked and destroyed\r
+ //! calling Destroyer::operator()(pointer).\r
+ //! \r
+ //! <b>Complexity</b>: Linear to erased plus inserted elements.\r
+ //! \r
+ //! <b>Throws</b>: If cloner throws.\r
+ template <class Cloner, class Destroyer>\r
+ void clone_from(const islist &src, Cloner cloner, Destroyer destroyer)\r
+ { \r
+ clone_and_reverse_from(src, cloner, destroyer);\r
+ this->reverse();\r
+ }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Erases all the elements from *this\r
+ //! calling Destroyer::operator()(pointer), clones all the \r
+ //! elements from src calling Cloner::operator()(const value_type &)\r
+ //! and inserts them on *this in the reverse order than\r
+ //! the original container.\r
+ //!\r
+ //! If cloner throws, all cloned elements are unlinked and destroyed\r
+ //! calling Destroyer::operator()(pointer).\r
+ //! \r
+ //! <b>Complexity</b>: Linear to erased plus inserted elements.\r
+ //! \r
+ //! <b>Throws</b>: If cloner throws.\r
+ //! \r
+ //! <b>Note</b>: This function is more efficient than "clone_from".\r
+ template <class Cloner, class Destroyer>\r
+ void clone_and_reverse_from(const islist &src, Cloner cloner, Destroyer destroyer)\r
+ {\r
+ this->clear_and_destroy(destroyer);\r
+ try{\r
+ const_iterator b(src.begin()), e(src.end());\r
+ for(; b != e; ++b){\r
+ this->push_front(*cloner(*b));\r
+ }\r
+ }\r
+ catch(...){\r
+ clear_and_destroy(destroyer);\r
+ throw;\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: value must be an lvalue and prev_p must point to an element\r
+ //! contained by the list or to end().\r
+ //!\r
+ //! <b>Effects</b>: Inserts the value after the position pointed by prev_p.\r
+ //! No copy constructor is called.\r
+ //!\r
+ //! <b>Returns</b>: An iterator to the inserted element.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ //! \r
+ //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+ iterator insert_after(iterator prev_p, value_type &value)\r
+ {\r
+ node_ptr n = ValueTraits::to_node_ptr(value);\r
+ if(safemode_or_autounlink)\r
+ BOOST_ASSERT(node_algorithms::unique(n));\r
+ node_algorithms::link_after(prev_p.list_node(), n);\r
+ size_traits::increment();\r
+ return iterator (n);\r
+ }\r
+\r
+ //! <b>Requires</b>: Dereferencing iterator must yield \r
+ //! an lvalue of type value_type and prev_p must point to an element\r
+ //! contained by the list or to the end node.\r
+ //! \r
+ //! <b>Effects</b>: Inserts the [first, last)\r
+ //! after the position prev_p.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements inserted.\r
+ //! \r
+ //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+ template<class Iterator>\r
+ void insert_after(iterator prev_p, Iterator first, Iterator last)\r
+ {\r
+ for (; first != last; ++first)\r
+ prev_p = insert_after(prev_p, *first);\r
+ }\r
+\r
+ //! <b>Requires</b>: value must be an lvalue and p must point to an element\r
+ //! contained by the list or to end().\r
+ //!\r
+ //! <b>Effects</b>: Inserts the value before the position pointed by p.\r
+ //! No copy constructor is called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements before p. \r
+ //! \r
+ //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+ iterator insert(iterator p, value_type &value)\r
+ { return insert_after(this->previous(p), value); }\r
+\r
+ //! <b>Requires</b>: Dereferencing iterator must yield \r
+ //! an lvalue of type value_type and p must point to an element \r
+ //! contained by the list or to the end node.\r
+ //! \r
+ //! <b>Effects</b>: Inserts the pointed by b and e\r
+ //! before the position p. No copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements inserted plus linear\r
+ //! to the elements before b.\r
+ //! \r
+ //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+ template<class Iterator>\r
+ void insert(iterator p, Iterator b, Iterator e)\r
+ { return insert_after(this->previous(p), b, e); }\r
+\r
+ //! <b>Effects</b>: Erases the element after the element pointed by prev of \r
+ //! the list. No destructors are called.\r
+ //!\r
+ //! <b>Returns</b>: the first element remaining beyond the removed elements,\r
+ //! or end() if no such element exists.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references) to the\r
+ //! erased element.\r
+ iterator erase_after(iterator prev)\r
+ {\r
+ iterator it(prev); ++it;\r
+ node_ptr to_erase(it.list_node());\r
+ node_algorithms::unlink_after(prev.list_node());\r
+ size_traits::decrement();\r
+ iterator ret(++prev);\r
+ if(safemode_or_autounlink)\r
+ node_algorithms::init(to_erase);\r
+ return ret;\r
+ }\r
+\r
+ //! <b>Effects</b>: Erases the range (before_first, last) from\r
+ //! the list. No destructors are called.\r
+ //!\r
+ //! <b>Returns</b>: the first element remaining beyond the removed elements,\r
+ //! or end() if no such element exists.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Lineal to the elements (last - before_first).\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references) to the\r
+ //! erased element.\r
+ iterator erase_after(iterator before_first, iterator last)\r
+ {\r
+ iterator first;\r
+ while(++(first = before_first) != last){\r
+ this->erase_after(before_first);\r
+ }\r
+ return last;\r
+ }\r
+\r
+ //! <b>Effects</b>: Erases the element pointed by i of the list. \r
+ //! No destructors are called.\r
+ //!\r
+ //! <b>Returns</b>: the first element remaining beyond the removed element,\r
+ //! or end() if no such element exists.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the elements before i.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references) to the\r
+ //! erased element.\r
+ iterator erase(iterator i)\r
+ { return this->erase_after(this->previous(i)); }\r
+\r
+ //! <b>Requires</b>: first and last must be valid iterator to elements in *this.\r
+ //! \r
+ //! <b>Effects</b>: Erases the range pointed by b and e.\r
+ //! No destructors are called.\r
+ //!\r
+ //! <b>Returns</b>: the first element remaining beyond the removed elements,\r
+ //! or end() if no such element exists.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements erased plus linear\r
+ //! to the elements before first.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references) to the\r
+ //! erased elements.\r
+ iterator erase(iterator first, iterator last)\r
+ { return erase_after(this->previous(first), last); }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Erases the element after the element pointed by prev of \r
+ //! the list.\r
+ //! Destroyer::operator()(pointer) is called for the removed element.\r
+ //!\r
+ //! <b>Returns</b>: the first element remaining beyond the removed elements,\r
+ //! or end() if no such element exists.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators to the erased element.\r
+ template<class Destroyer>\r
+ iterator erase_after_and_destroy(iterator prev, Destroyer destroyer)\r
+ {\r
+ iterator it(prev); ++it;\r
+ node_ptr to_erase(it.list_node());\r
+ iterator ret(this->erase_after(prev));\r
+ destroyer(ValueTraits::to_value_ptr(to_erase));\r
+ return ret;\r
+ }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Erases the range (before_first, last) from\r
+ //! the list.\r
+ //! Destroyer::operator()(pointer) is called for the removed elements.\r
+ //!\r
+ //! <b>Returns</b>: the first element remaining beyond the removed elements,\r
+ //! or end() if no such element exists.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Lineal to the elements (last - before_first).\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators to the erased element.\r
+ template<class Destroyer>\r
+ iterator erase_after_and_destroy(iterator before_first, iterator last, Destroyer destroyer)\r
+ {\r
+ iterator first;\r
+ while(++(first = before_first) != last){\r
+ this->erase_after_and_destroy(before_first, destroyer);\r
+ }\r
+ return last;\r
+ }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Erases the element pointed by i of the list. \r
+ //! No destructors are called.\r
+ //! Destroyer::operator()(pointer) is called for the removed element.\r
+ //!\r
+ //! <b>Returns</b>: the first element remaining beyond the removed element,\r
+ //! or end() if no such element exists.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the elements before i.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references) to the\r
+ //! erased element.\r
+ template<class Destroyer>\r
+ iterator erase_and_destroy(iterator i, Destroyer destroyer)\r
+ { return this->erase_after_and_destroy(this->previous(i), destroyer); }\r
+\r
+ //! <b>Requires</b>: first and last must be valid iterator to elements in *this.\r
+ //! Destroyer::operator()(pointer) shouldn't throw.\r
+ //! \r
+ //! <b>Effects</b>: Erases the range pointed by b and e.\r
+ //! No destructors are called.\r
+ //! Destroyer::operator()(pointer) is called for the removed elements.\r
+ //!\r
+ //! <b>Returns</b>: the first element remaining beyond the removed elements,\r
+ //! or end() if no such element exists.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements erased plus linear\r
+ //! to the elements before first.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references) to the\r
+ //! erased elements.\r
+ template<class Destroyer>\r
+ iterator erase_and_destroy(iterator first, iterator last, Destroyer destroyer)\r
+ { return erase_after_and_destroy(this->previous(first), last, destroyer); }\r
+\r
+ //! <b>Requires</b>: Dereferencing iterator must yield \r
+ //! an lvalue of type value_type.\r
+ //! \r
+ //! <b>Effects</b>: Clears the list and inserts the range pointed by b and e.\r
+ //! No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements inserted plus\r
+ //! linear to the elements contained in the list if it's a safe-mode\r
+ //! or auto-unlink value.\r
+ //! Linear to the number of elements inserted in the list otherwise.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+ //! to the erased elements.\r
+ template<class Iterator>\r
+ void assign(Iterator b, Iterator e)\r
+ {\r
+ this->clear();\r
+ this->insert_after(before_begin(), b, e);\r
+ }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Requires</b>: Dereferencing iterator must yield \r
+ //! an lvalue of type value_type.\r
+ //! \r
+ //! <b>Effects</b>: Clears the list and inserts the range pointed by b and e.\r
+ //! No destructors or copy constructors are called.\r
+ //! Destroyer::operator()(pointer) is called for the removed elements.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements inserted plus\r
+ //! linear to the elements contained in the list.\r
+ //! \r
+ //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+ //! to the erased elements.\r
+ template<class Iterator, class Destroyer>\r
+ void assign_and_destroy(Iterator b, Iterator e, Destroyer destroyer)\r
+ {\r
+ this->clear_and_destroy(destroyer);\r
+ this->insert_after_and_destroy(before_begin(), b, e, destroyer);\r
+ }\r
+\r
+ //! <b>Requires</b>: prev is an iterator to an element or x.end()/x.before_begin() in x.\r
+ //! \r
+ //! <b>Effects</b>: Transfers all the elements of list x to this list, after the\r
+ //! the element pointed by prev. No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Returns</b>: The last element inserted of x or prev if x is empty.\r
+ //! This iterator can be used as new "prev" iterator for a new splice_after call.\r
+ //! that will splice new values after the previously spliced values.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //!\r
+ //! <b>Complexity</b>: Linear to the elements contained in x\r
+ //! \r
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this\r
+ //! list. Iterators of this list and all the references are not invalidated.\r
+ iterator splice_after(iterator prev, islist &x)\r
+ {\r
+ if (!x.empty()){\r
+ iterator last_x(x.previous(x.end()));\r
+ node_algorithms::transfer_after\r
+ ( prev.list_node()\r
+ , x.end().list_node()\r
+ , last_x.list_node());\r
+ size_traits::set_size(size_traits::get_size() + x.get_size());\r
+ x.set_size(size_type(0));\r
+ return last_x;\r
+ }\r
+ else{\r
+ return prev;\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: prev must point to an element contained by this list or\r
+ //! to the before_begin() element. prev_ele must point to an element contained in list\r
+ //! x or must be x.before_begin().\r
+ //! \r
+ //! <b>Effects</b>: Transfers the element after prev_ele, from list x to this list, \r
+ //! after the element pointed by prev. No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant.\r
+ //! \r
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this\r
+ //! list. Iterators of this list and all the references are not invalidated.\r
+ void splice_after(iterator prev, islist &x, iterator prev_ele)\r
+ {\r
+ iterator nxt = prev_ele;\r
+ ++nxt;\r
+ if (nxt != prev && prev_ele != prev){\r
+ node_algorithms::transfer_after\r
+ (prev.list_node(), prev_ele.list_node(), nxt.list_node());\r
+ size_traits::increment();\r
+ x.decrement();\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be\r
+ //! before_begin(), and before_first and before_last belong to x and\r
+ //! ++before_first != x.end() && before_last != x.end(). \r
+ //! \r
+ //! <b>Effects</b>: Transfers the range (before_first, before_last] from list x to this\r
+ //! list, after the element pointed by prev_pos.\r
+ //! No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements transferred\r
+ //! if ConstantTimeSize is true. Constant-time otherwise.\r
+ //! \r
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this\r
+ //! list. Iterators of this list and all the references are not invalidated.\r
+ void splice_after(iterator prev_pos, islist &x, iterator before_first, iterator before_last)\r
+ {\r
+ if (before_first != before_last){\r
+ if(ConstantTimeSize){\r
+ size_type increment = std::distance(before_first, before_last);\r
+ node_algorithms::transfer_after\r
+ (prev_pos.list_node(), before_first.list_node(), before_last.list_node());\r
+ size_traits::set_size(size_traits::get_size() + increment);\r
+ x.set_size(x.get_size() - increment);\r
+ }\r
+ else{\r
+ node_algorithms::transfer_after\r
+ (prev_pos.list_node(), before_first.list_node(), before_last.list_node());\r
+ }\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be\r
+ //! before_begin(), and before_first and before_last belong to x and\r
+ //! ++before_first != x.end() && before_last != x.end() and\r
+ //! n == std::distance(before_first, before_last).\r
+ //! \r
+ //! <b>Effects</b>: Transfers the range (before_first, before_last] from list x to this\r
+ //! list, after the element pointed by p. No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant time.\r
+ //! \r
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this\r
+ //! list. Iterators of this list and all the references are not invalidated.\r
+ void splice_after(iterator prev_pos, islist &x, iterator before_first, iterator before_last, difference_type n)\r
+ {\r
+ if(n){\r
+ if(ConstantTimeSize){\r
+ BOOST_ASSERT(std::distance(before_first, before_last) == n);\r
+ node_algorithms::transfer_after\r
+ (prev_pos.list_node(), before_first.list_node(), before_last.list_node());\r
+ size_traits::set_size(size_traits::get_size() + n);\r
+ x.set_size(x.get_size() - n);\r
+ }\r
+ else{\r
+ node_algorithms::transfer_after\r
+ (prev_pos.list_node(), before_first.list_node(), before_last.list_node());\r
+ }\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: it is an iterator to an element in x.\r
+ //! \r
+ //! <b>Effects</b>: Transfers all the elements of list x to this list, before the\r
+ //! the element pointed by it. No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Returns</b>: The last element inserted of x or the previous element\r
+ //! of it if x is empty.\r
+ //! This iterator can be used as new "prev" iterator for a new splice call.\r
+ //! that will splice new values after the previously spliced values.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //!\r
+ //! <b>Complexity</b>: Linear to the elements contained in x plus linear to\r
+ //! the elements before it.\r
+ //! \r
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this\r
+ //! list. Iterators of this list and all the references are not invalidated.\r
+ iterator splice(iterator it, islist &x)\r
+ { return splice_after(this->previous(it), x); }\r
+\r
+ //! <b>Requires</b>: it p must be a valid iterator of *this.\r
+ //! elem must point to an element contained in list\r
+ //! x.\r
+ //! \r
+ //! <b>Effects</b>: Transfers the element elem, from list x to this list, \r
+ //! before the element pointed by pos. No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the elements before pos and before elem.\r
+ //! \r
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this\r
+ //! list. Iterators of this list and all the references are not invalidated.\r
+ void splice(iterator pos, islist &x, iterator elem)\r
+ { return splice_after(this->previous(pos), x, this->previous(elem)); }\r
+\r
+ //! <b>Requires</b>: pos must be a dereferenceable iterator in *this\r
+ //! and first and last belong to x and first and last a valid range on x. \r
+ //! \r
+ //! <b>Effects</b>: Transfers the range [first, last) from list x to this\r
+ //! list, before the element pointed by pos.\r
+ //! No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the sum of elements before pos, first, and last.\r
+ //! Plus linear to the number of elements transferred if ConstantTimeSize is true.\r
+ //! \r
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this\r
+ //! list. Iterators of this list and all the references are not invalidated.\r
+ void splice(iterator pos, islist &x, iterator first, iterator last)\r
+ { return splice_after(this->previous(pos), x, this->previous(first), this->previous(last)); }\r
+\r
+ //! <b>Requires</b>: pos must be a dereferenceable iterator in *this\r
+ //! and first and last belong to x and first and last a valid range on x. \r
+ //! n == std::distance(first, last).\r
+ //! \r
+ //! <b>Effects</b>: Transfers the range [first, last) from list x to this\r
+ //! list, before the element pointed by pos.\r
+ //! No destructors or copy constructors are called.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the sum of elements before pos, first, and last.\r
+ //! \r
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this\r
+ //! list. Iterators of this list and all the references are not invalidated.\r
+ void splice(iterator pos, islist &x, iterator first, iterator last, difference_type n)\r
+ { return splice_after(this->previous(pos), x, this->previous(first), this->previous(last), n); }\r
+\r
+ //! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>. \r
+ //! The sort is stable, that is, the relative order of equivalent elements is preserved.\r
+ //! \r
+ //! <b>Throws</b>: If value_traits::node_traits::node\r
+ //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)\r
+ //! or the predicate throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N\r
+ //! is the list's size.\r
+ //!\r
+ //! <b>Note</b>: Iterators and references are not invalidated\r
+ template<class Predicate>\r
+ void sort(Predicate p)\r
+ {\r
+ if (!this->empty() &&\r
+ node_traits::get_next(node_traits::get_next(get_root_node()))\r
+ != this->get_root_node()) {\r
+ islist carry;\r
+ islist counter[64];\r
+ int fill = 0;\r
+ iterator last_inserted;\r
+ while(!this->empty()){\r
+ last_inserted = this->begin();\r
+ carry.splice_after(carry.before_begin(), *this, this->before_begin());\r
+ int i = 0;\r
+ while(i < fill && !counter[i].empty()) {\r
+ last_inserted = carry.merge(counter[i++], p);\r
+ }\r
+ BOOST_ASSERT(counter[i].empty());\r
+\r
+ iterator last_element(previous_node(last_inserted, carry.end()));\r
+ if(ConstantTimeSize){\r
+ counter[i].splice_after( counter[i].end(), carry\r
+ , carry.before_begin(), last_element\r
+ , carry.size());\r
+ }\r
+ else{\r
+ counter[i].splice_after( counter[i].end(), carry\r
+ , carry.before_begin(), last_element);\r
+ }\r
+ //counter[i].splice_after(counter[i].end(), carry, carry.end(), previous_node(last_inserted, carry.end()));\r
+ //carry.swap(counter[i]);\r
+ if(i == fill)\r
+ ++fill;\r
+ }\r
+\r
+ for (int i = 1; i < fill; ++i)\r
+ last_inserted = counter[i].merge(counter[i-1], p);\r
+ //this->swap(counter[fill-1]);\r
+ BOOST_ASSERT(this->empty());\r
+\r
+ iterator last_element(previous_node(last_inserted, counter[--fill].end()));\r
+ if(ConstantTimeSize){\r
+ this->splice_after( end(), counter[fill], counter[fill].before_begin()\r
+ , last_element, counter[fill].size());\r
+ }\r
+ else{\r
+ this->splice_after( end(), counter[fill], counter[fill].before_begin()\r
+ , last_element);\r
+ }\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: p must be a comparison function that induces a strict weak\r
+ //! ordering and both *this and x must be sorted according to that ordering\r
+ //! The lists x and *this must be distinct. \r
+ //! \r
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them\r
+ //! in order into *this. The merge is stable; that is, if an element from *this is \r
+ //! equivalent to one from x, then the element from *this will precede the one from x. \r
+ //! \r
+ //! <b>Throws</b>: If value_traits::node_traits::node\r
+ //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)\r
+ //! or std::less<value_type> throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: This function is linear time: it performs at most\r
+ //! size() + x.size() - 1 comparisons.\r
+ //! \r
+ //! <b>Note</b>: Iterators and references are not invalidated.\r
+ void sort()\r
+ { this->sort(std::less<value_type>()); }\r
+\r
+ //! <b>Requires</b>: p must be a comparison function that induces a strict weak\r
+ //! ordering and both *this and x must be sorted according to that ordering\r
+ //! The lists x and *this must be distinct. \r
+ //! \r
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them\r
+ //! in order into *this. The merge is stable; that is, if an element from *this is \r
+ //! equivalent to one from x, then the element from *this will precede the one from x. \r
+ //! \r
+ //! <b>Returns</b>: An iterator to the last transferred value, end() is x is empty.\r
+ //! \r
+ //! <b>Throws</b>: If the predicate throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: This function is linear time: it performs at most\r
+ //! size() + x.size() - 1 comparisons.\r
+ //! \r
+ //! <b>Note</b>: Iterators and references are not invalidated.\r
+ template<class Predicate>\r
+ iterator merge(islist& x, Predicate p) \r
+ {\r
+ iterator a(before_begin()), e(end()), ax(x.before_begin());\r
+ iterator last_inserted(e);\r
+ iterator a_next;\r
+ while(++(a_next = a) != e && !x.empty()) {\r
+ iterator ix(ax);\r
+ iterator cx;\r
+ size_type n(0);\r
+ while(++(cx = ix) != ax && p(*cx, *a_next)){\r
+ ++ix; ++n;\r
+ }\r
+ if(ax != ix){\r
+ this->splice_after(a, x, ax, ix, n);\r
+ last_inserted = ix;\r
+ }\r
+ a = a_next;\r
+ } \r
+ if (!x.empty()){\r
+ last_inserted = this->splice_after(a, x);\r
+ }\r
+ return last_inserted;\r
+ }\r
+\r
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them\r
+ //! in order into *this according to std::less<value_type>. The merge is stable; \r
+ //! that is, if an element from *this is equivalent to one from x, then the element \r
+ //! from *this will precede the one from x. \r
+ //! \r
+ //! <b>Throws</b>: if std::less<value_type> throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: This function is linear time: it performs at most\r
+ //! size() + x.size() - 1 comparisons.\r
+ //! \r
+ //! <b>Note</b>: Iterators and references are not invalidated\r
+ void merge(islist& x)\r
+ { this->merge(x, std::less<value_type>()); }\r
+\r
+ //! <b>Effects</b>: Reverses the order of elements in the list. \r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: This function is linear to the contained elements.\r
+ //! \r
+ //! <b>Note</b>: Iterators and references are not invalidated\r
+ void reverse() \r
+ { node_algorithms::reverse(node_ptr(&root)); }\r
+\r
+ //! <b>Effects</b>: Removes all the elements that compare equal to value.\r
+ //! No destructors are called.\r
+ //! \r
+ //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.\r
+ //! \r
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,\r
+ //! and iterators to elements that are not removed remain valid. This function is \r
+ //! linear time: it performs exactly size() comparisons for equality.\r
+ void remove(const value_type &value)\r
+ { remove_if(equal_to_value(value)); }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Removes all the elements that compare equal to value.\r
+ //! Destroyer::operator()(pointer) is called for every removed element.\r
+ //!\r
+ //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.\r
+ //! \r
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,\r
+ //! and iterators to elements that are not removed remain valid.\r
+ template<class Destroyer>\r
+ void remove_and_destroy(const value_type &value, Destroyer destroyer)\r
+ { remove_and_destroy_if(equal_to_value(value), destroyer); }\r
+\r
+ //! <b>Effects</b>: Removes all the elements for which a specified\r
+ //! predicate is satisfied. No destructors are called.\r
+ //! \r
+ //! <b>Throws</b>: If pred throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: Linear time. It performs exactly size() calls to the predicate.\r
+ //! \r
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,\r
+ //! and iterators to elements that are not removed remain valid.\r
+ template<class Pred>\r
+ void remove_if(Pred pred)\r
+ { remove_and_destroy_if(pred, detail::null_destroyer()); }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Removes all the elements for which a specified\r
+ //! predicate is satisfied.\r
+ //! Destroyer::operator()(pointer) is called for every removed element.\r
+ //!\r
+ //! <b>Throws</b>: If pred throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.\r
+ //!\r
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,\r
+ //! and iterators to elements that are not removed remain valid.\r
+ template<class Pred, class Destroyer>\r
+ void remove_and_destroy_if(Pred pred, Destroyer destroyer)\r
+ {\r
+ iterator bcur(this->before_begin()), cur, e(this->end());\r
+ \r
+ while(++(cur = bcur) != e){\r
+ if (pred(*cur)){\r
+ pointer p = cur.operator->();\r
+ this->erase_after(bcur);\r
+ destroyer(p);\r
+ }\r
+ else{\r
+ ++bcur;\r
+ }\r
+ }\r
+ }\r
+\r
+ //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent \r
+ //! elements that are equal from the list. No destructors are called.\r
+ //! \r
+ //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: Linear time (size()-1) comparisons calls to pred()).\r
+ //! \r
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,\r
+ //! and iterators to elements that are not removed remain valid.\r
+ void unique()\r
+ { unique_and_destroy(std::equal_to<value_type>(), detail::null_destroyer()); }\r
+\r
+ //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent \r
+ //! elements that satisfy some binary predicate from the list.\r
+ //! No destructors are called.\r
+ //! \r
+ //! <b>Throws</b>: If the predicate throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: Linear time (size()-1) comparisons equality comparisons.\r
+ //! \r
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,\r
+ //! and iterators to elements that are not removed remain valid.\r
+ template<class BinaryPredicate>\r
+ void unique(BinaryPredicate pred)\r
+ { unique_and_destroy(pred, detail::null_destroyer()); }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent \r
+ //! elements that satisfy some binary predicate from the list.\r
+ //! Destroyer::operator()(pointer) is called for every removed element.\r
+ //! \r
+ //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: Linear time (size()-1) comparisons equality comparisons.\r
+ //! \r
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,\r
+ //! and iterators to elements that are not removed remain valid.\r
+ template<class Destroyer>\r
+ void unique_and_destroy(Destroyer destroyer)\r
+ { unique(std::equal_to<value_type>(), destroyer); }\r
+\r
+ //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+ //!\r
+ //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent \r
+ //! elements that satisfy some binary predicate from the list.\r
+ //! Destroyer::operator()(pointer) is called for every removed element.\r
+ //! \r
+ //! <b>Throws</b>: If the predicate throws. Basic guarantee.\r
+ //! \r
+ //! <b>Complexity</b>: Linear time (size()-1) comparisons equality comparisons.\r
+ //! \r
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,\r
+ //! and iterators to elements that are not removed remain valid.\r
+ template<class BinaryPredicate, class Destroyer>\r
+ void unique_and_destroy(BinaryPredicate pred, Destroyer destroyer)\r
+ {\r
+ iterator end_n(end());\r
+ iterator cur(begin());\r
+ iterator cur_next;\r
+\r
+ if (cur != end_n) {\r
+ while(++(cur_next = cur) != end_n) {\r
+ if (pred(*cur, *cur_next)){\r
+ pointer p = cur_next.operator->();\r
+ this->erase_after(cur);\r
+ destroyer(p);\r
+ }\r
+ else{\r
+ ++cur;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //! <b>Requires</b>: value must be a reference to a value inserted in a list.\r
+ //! \r
+ //! <b>Effects</b>: This function returns a const_iterator pointing to the element\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant time.\r
+ //! \r
+ //! <b>Note</b>: Iterators and references are not invalidated.\r
+ static iterator current(value_type &value) \r
+ { \r
+ BOOST_ASSERT (!node_algorithms::unique(ValueTraits::to_node_ptr(value)));\r
+ return iterator (ValueTraits::to_node_ptr(value)); \r
+ }\r
+\r
+ //! <b>Requires</b>: value must be a const reference to a value inserted in a list.\r
+ //! \r
+ //! <b>Effects</b>: This function returns an iterator pointing to the element.\r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Constant time.\r
+ //! \r
+ //! <b>Note</b>: Iterators and references are not invalidated.\r
+ static const_iterator current(const value_type &value) \r
+ { \r
+ BOOST_ASSERT (!node_algorithms::unique(ValueTraits::to_node_ptr(const_cast<value_type&> (value))));\r
+ return const_iterator (ValueTraits::to_node_ptr(const_cast<value_type&> (value))); \r
+ }\r
+\r
+ //! <b>Returns</b>: The iterator to the element before i in the list. \r
+ //! Returns the end-iterator, if either i is the begin-iterator or the \r
+ //! list is empty. \r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements before i. \r
+ iterator previous(iterator i)\r
+ {\r
+ return iterator\r
+ (node_algorithms::get_previous_node\r
+ (before_begin().list_node(), i.list_node()));\r
+ }\r
+\r
+ //! <b>Returns</b>: The const_iterator to the element before i in the list. \r
+ //! Returns the end-const_iterator, if either i is the begin-const_iterator or \r
+ //! the list is empty. \r
+ //! \r
+ //! <b>Throws</b>: Nothing.\r
+ //! \r
+ //! <b>Complexity</b>: Linear to the number of elements before i. \r
+ const_iterator previous(const_iterator i) const\r
+ {\r
+ return const_iterator\r
+ (node_algorithms::get_previous_node\r
+ (before_begin().list_node(), i.list_node()));\r
+ }\r
+};\r
+\r
+template <class V, bool C, class S>\r
+inline bool operator==(const islist<V, C, S>& x, const islist<V, C, S>& y)\r
+{\r
+ if(C && x.size() != y.size()){\r
+ return false;\r
+ }\r
+ typedef typename islist<V, C, S>::const_iterator const_iterator;\r
+ const_iterator end1 = x.end();\r
+\r
+ const_iterator i1 = x.begin();\r
+ const_iterator i2 = y.begin();\r
+ if(C){\r
+ while (i1 != end1 && *i1 == *i2) {\r
+ ++i1;\r
+ ++i2;\r
+ }\r
+ return i1 == end1;\r
+ }\r
+ else{\r
+ const_iterator end2 = y.end();\r
+ while (i1 != end1 && i2 != end2 && *i1 == *i2) {\r
+ ++i1;\r
+ ++i2;\r
+ }\r
+ return i1 == end1 && i2 == end2;\r
+ }\r
+}\r
+\r
+template <class V, bool C, class S>\r
+inline bool operator<(const islist<V, C, S>& x,\r
+ const islist<V, C, S>& y)\r
+{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }\r
+\r
+template <class V, bool C, class S>\r
+inline bool operator!=(const islist<V, C, S>& x, const islist<V, C, S>& y) \r
+{ return !(x == y); }\r
+\r
+template <class V, bool C, class S>\r
+inline bool operator>(const islist<V, C, S>& x, const islist<V, C, S>& y) \r
+{ return y < x; }\r
+\r
+template <class V, bool C, class S>\r
+inline bool operator<=(const islist<V, C, S>& x, const islist<V, C, S>& y) \r
+{ return !(y < x); }\r
+\r
+template <class V, bool C, class S>\r
+inline bool operator>=(const islist<V, C, S>& x, const islist<V, C, S>& y) \r
+{ return !(x < y); }\r
+\r
+template <class V, bool C, class S>\r
+inline void swap(islist<V, C, S>& x, islist<V, C, S>& y)\r
+{ x.swap(y); }\r
+\r
+} //namespace intrusive \r
+} //namespace boost \r
+\r
+#include "detail/config_end.hpp"\r
+\r
+#endif //BOOST_INTRUSIVE_ISLIST_HPP\r