diff options
Diffstat (limited to 'boost/container/list.hpp')
-rw-r--r-- | boost/container/list.hpp | 1390 |
1 files changed, 736 insertions, 654 deletions
diff --git a/boost/container/list.hpp b/boost/container/list.hpp index c3e3562988..33cc6ee0f8 100644 --- a/boost/container/list.hpp +++ b/boost/container/list.hpp @@ -1,16 +1,16 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/container for documentation. // -#ifndef BOOST_CONTAINER_LIST_HPP_ -#define BOOST_CONTAINER_LIST_HPP_ +#ifndef BOOST_CONTAINER_LIST_HPP +#define BOOST_CONTAINER_LIST_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -18,13 +18,16 @@ #include <boost/container/detail/workaround.hpp> #include <boost/container/container_fwd.hpp> #include <boost/container/detail/version_type.hpp> -#include <boost/move/move.hpp> -#include <boost/move/move_helpers.hpp> +#include <boost/container/detail/iterators.hpp> +#include <boost/container/detail/mpl.hpp> +#include <boost/container/throw_exception.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/move/iterator.hpp> +#include <boost/move/detail/move_helpers.hpp> +#include <boost/move/traits.hpp> #include <boost/intrusive/pointer_traits.hpp> #include <boost/container/detail/utilities.hpp> #include <boost/container/detail/algorithms.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/container/detail/mpl.hpp> #include <boost/intrusive/list.hpp> #include <boost/assert.hpp> #include <boost/container/detail/node_alloc_holder.hpp> @@ -35,23 +38,20 @@ #include <boost/container/detail/preprocessor.hpp> #endif -#include <stdexcept> +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) +#include <initializer_list> +#endif + #include <iterator> #include <utility> #include <memory> #include <functional> #include <algorithm> -#include <stdexcept> -#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED namespace boost { namespace container { -#else -namespace boost { -namespace container { -#endif -/// @cond +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED namespace container_detail { template<class VoidPointer> @@ -69,14 +69,27 @@ struct list_node list_node(); public: + typedef T value_type; typedef typename list_hook<VoidPointer>::type hook_type; + T m_data; + + T &get_data() + { return this->m_data; } + + const T &get_data() const + { return this->m_data; } }; -template<class A> +template <class T, class VoidPointer> +struct iiterator_node_value_type< list_node<T,VoidPointer> > { + typedef T type; +}; + +template<class Allocator> struct intrusive_list_type { - typedef boost::container::allocator_traits<A> allocator_traits_type; + typedef boost::container::allocator_traits<Allocator> allocator_traits_type; typedef typename allocator_traits_type::value_type value_type; typedef typename boost::intrusive::pointer_traits <typename allocator_traits_type::pointer>::template @@ -95,7 +108,7 @@ struct intrusive_list_type }; } //namespace container_detail { -/// @endcond +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! A list is a doubly linked list. That is, it is a Sequence that supports both //! forward and backward traversal, and (amortized) constant time insertion and @@ -107,29 +120,31 @@ struct intrusive_list_type //! after a list operation than it did before), but the iterators themselves will //! not be invalidated or made to point to different elements unless that invalidation //! or mutation is explicit. +//! +//! \tparam T The type of object that is stored in the list +//! \tparam Allocator The allocator used for all internal memory management #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class T, class A = std::allocator<T> > +template <class T, class Allocator = std::allocator<T> > #else -template <class T, class A> +template <class T, class Allocator> #endif class list : protected container_detail::node_alloc_holder - <A, typename container_detail::intrusive_list_type<A>::type> + <Allocator, typename container_detail::intrusive_list_type<Allocator>::type> { - /// @cond + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED typedef typename - container_detail::intrusive_list_type<A>::type Icont; - typedef list <T, A> ThisType; - typedef container_detail::node_alloc_holder<A, Icont> AllocHolder; - typedef typename AllocHolder::NodePtr NodePtr; - typedef typename AllocHolder::NodeAlloc NodeAlloc; - typedef typename AllocHolder::ValAlloc ValAlloc; - typedef typename AllocHolder::Node Node; - typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer; - typedef typename AllocHolder::allocator_v1 allocator_v1; - typedef typename AllocHolder::allocator_v2 allocator_v2; - typedef typename AllocHolder::alloc_version alloc_version; - typedef boost::container::allocator_traits<A> allocator_traits_type; + container_detail::intrusive_list_type<Allocator>::type Icont; + typedef container_detail::node_alloc_holder<Allocator, Icont> AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer; + typedef typename AllocHolder::allocator_v1 allocator_v1; + typedef typename AllocHolder::allocator_v2 allocator_v2; + typedef typename AllocHolder::alloc_version alloc_version; + typedef boost::container::allocator_traits<Allocator> allocator_traits_type; class equal_to_value { @@ -159,141 +174,39 @@ class list bool operator()(const Node &a) const { return static_cast<const Pred&>(*this)(a.m_data); } }; - /// @endcond - public: - //! The type of object, T, stored in the list - typedef T value_type; - //! Pointer to T - typedef typename allocator_traits_type::pointer pointer; - //! Const pointer to T - typedef typename allocator_traits_type::const_pointer const_pointer; - //! Reference to T - typedef typename allocator_traits_type::reference reference; - //! Const reference to T - typedef typename allocator_traits_type::const_reference const_reference; - //! An unsigned integral type - typedef typename allocator_traits_type::size_type size_type; - //! A signed integral type - typedef typename allocator_traits_type::difference_type difference_type; - //! The allocator type - typedef A allocator_type; - //! Non-standard extension: the stored allocator type - typedef NodeAlloc stored_allocator_type; - - /// @cond - private: BOOST_COPYABLE_AND_MOVABLE(list) - typedef difference_type list_difference_type; - typedef pointer list_pointer; - typedef const_pointer list_const_pointer; - typedef reference list_reference; - typedef const_reference list_const_reference; - /// @endcond - - public: - //! Const iterator used to iterate through a list. - class const_iterator - /// @cond - : public std::iterator<std::bidirectional_iterator_tag, - value_type, list_difference_type, - list_const_pointer, list_const_reference> - { - - protected: - typename Icont::iterator m_it; - explicit const_iterator(typename Icont::iterator it) : m_it(it){} - void prot_incr() { ++m_it; } - void prot_decr() { --m_it; } - - private: - typename Icont::iterator get() - { return this->m_it; } - - public: - friend class list<T, A>; - typedef list_difference_type difference_type; - - //Constructors - const_iterator() - : m_it() - {} - - //Pointer like operators - const_reference operator*() const - { return m_it->m_data; } - - const_pointer operator->() const - { return const_pointer(&m_it->m_data); } - - //Increment / Decrement - const_iterator& operator++() - { prot_incr(); return *this; } - - const_iterator operator++(int) - { typename Icont::iterator tmp = m_it; ++*this; return const_iterator(tmp); } - - const_iterator& operator--() - { prot_decr(); return *this; } - - const_iterator operator--(int) - { typename Icont::iterator tmp = m_it; --*this; return const_iterator(tmp); } - - //Comparison operators - bool operator== (const const_iterator& r) const - { return m_it == r.m_it; } - - bool operator!= (const const_iterator& r) const - { return m_it != r.m_it; } - } - /// @endcond - ; - - //! Iterator used to iterate through a list - class iterator - /// @cond - : public const_iterator - { - - private: - explicit iterator(typename Icont::iterator it) - : const_iterator(it) - {} - - typename Icont::iterator get() - { return this->m_it; } - - public: - friend class list<T, A>; - typedef list_pointer pointer; - typedef list_reference reference; - - //Constructors - iterator(){} - //Pointer like operators - reference operator*() const { return this->m_it->m_data; } - pointer operator->() const { return pointer(&this->m_it->m_data); } + typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl; + typedef container_detail::iterator<typename Icont::iterator, true> const_iterator_impl; + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - //Increment / Decrement - iterator& operator++() - { this->prot_incr(); return *this; } - - iterator operator++(int) - { typename Icont::iterator tmp = this->m_it; ++*this; return iterator(tmp); } - - iterator& operator--() - { this->prot_decr(); return *this; } - - iterator operator--(int) - { iterator tmp = *this; --*this; return tmp; } - }; - /// @endcond - - //! Iterator used to iterate backwards through a list. - typedef std::reverse_iterator<iterator> reverse_iterator; - //! Const iterator used to iterate backwards through a list. - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + public: + ////////////////////////////////////////////// + // + // types + // + ////////////////////////////////////////////// + + typedef T value_type; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer; + typedef typename ::boost::container::allocator_traits<Allocator>::reference reference; + typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference; + typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type; + typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type; + typedef Allocator allocator_type; + typedef BOOST_CONTAINER_IMPDEF(NodeAlloc) stored_allocator_type; + typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; + typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<iterator>) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator; + + ////////////////////////////////////////////// + // + // construct/copy/destroy + // + ////////////////////////////////////////////// //! <b>Effects</b>: Default constructs a list. //! @@ -306,32 +219,32 @@ class list //! <b>Effects</b>: Constructs a list taking the allocator as parameter. //! - //! <b>Throws</b>: If allocator_type's copy constructor throws. + //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. - explicit list(const allocator_type &a) + explicit list(const allocator_type &a) BOOST_CONTAINER_NOEXCEPT : AllocHolder(a) {} //! <b>Effects</b>: Constructs a list that will use a copy of allocator a //! and inserts n copies of value. //! - //! <b>Throws</b>: If allocator_type's default constructor or copy constructor + //! <b>Throws</b>: If allocator_type's default constructor //! throws or T's default or copy constructor throws. //! //! <b>Complexity</b>: Linear to n. explicit list(size_type n) - : AllocHolder(A()) + : AllocHolder(Allocator()) { this->resize(n); } //! <b>Effects</b>: Constructs a list that will use a copy of allocator a //! and inserts n copies of value. //! - //! <b>Throws</b>: If allocator_type's default constructor or copy constructor + //! <b>Throws</b>: If allocator_type's default constructor //! throws or T's default or copy constructor throws. //! //! <b>Complexity</b>: Linear to n. - list(size_type n, const T& value, const A& a = A()) + list(size_type n, const T& value, const Allocator& a = Allocator()) : AllocHolder(a) { this->insert(this->cbegin(), n, value); } @@ -339,7 +252,7 @@ class list //! //! <b>Postcondition</b>: x == *this. //! - //! <b>Throws</b>: If allocator_type's default constructor or copy constructor throws. + //! <b>Throws</b>: If allocator_type's default constructor throws. //! //! <b>Complexity</b>: Linear to the elements x contains. list(const list& x) @@ -386,52 +299,205 @@ class list //! <b>Effects</b>: Constructs a list that will use a copy of allocator a //! and inserts a copy of the range [first, last) in the list. //! - //! <b>Throws</b>: If allocator_type's default constructor or copy constructor - //! throws or T's constructor taking an dereferenced InIt throws. + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's constructor taking a dereferenced InIt throws. //! //! <b>Complexity</b>: Linear to the range [first, last). template <class InpIt> - list(InpIt first, InpIt last, const A &a = A()) + list(InpIt first, InpIt last, const Allocator &a = Allocator()) : AllocHolder(a) { this->insert(this->cbegin(), first, last); } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! <b>Effects</b>: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [il.begin(), il.end()) in the list. + //! + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's constructor taking a dereferenced + //! std::initializer_list iterator throws. + //! + //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()). + list(std::initializer_list<value_type> il, const Allocator &a = Allocator()) + : AllocHolder(a) + { this->insert(this->cbegin(), il.begin(), il.end()); } +#endif + //! <b>Effects</b>: Destroys the list. All stored values are destroyed //! and used memory is deallocated. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements. - ~list() + ~list() BOOST_CONTAINER_NOEXCEPT {} //AllocHolder clears the list + //! <b>Effects</b>: Makes *this contain the same elements as x. + //! + //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. + //! + //! <b>Complexity</b>: Linear to the number of elements in x. + list& operator=(BOOST_COPY_ASSIGN_REF(list) x) + { + if (&x != this){ + NodeAlloc &this_alloc = this->node_alloc(); + const NodeAlloc &x_alloc = x.node_alloc(); + container_detail::bool_<allocator_traits_type:: + propagate_on_container_copy_assignment::value> flag; + if(flag && this_alloc != x_alloc){ + this->clear(); + } + this->AllocHolder::copy_assign_alloc(x); + this->assign(x.begin(), x.end()); + } + return *this; + } + + //! <b>Effects</b>: Move assignment. All x's values are transferred to *this. + //! + //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had + //! before the function. + //! + //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment + //! is false and (allocation throws or value_type's move constructor throws) + //! + //! <b>Complexity</b>: Constant if allocator_traits_type:: + //! propagate_on_container_move_assignment is true or + //! this->get>allocator() == x.get_allocator(). Linear otherwise. + list& operator=(BOOST_RV_REF(list) x) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + { + BOOST_ASSERT(this != &x); + NodeAlloc &this_alloc = this->node_alloc(); + NodeAlloc &x_alloc = x.node_alloc(); + const bool propagate_alloc = allocator_traits_type:: + propagate_on_container_move_assignment::value; + const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; + //Resources can be transferred if both allocators are + //going to be equal after this function (either propagated or already equal) + if(propagate_alloc || allocators_equal){ + //Destroy + this->clear(); + //Move allocator if needed + this->AllocHolder::move_assign_alloc(x); + //Obtain resources + this->icont() = boost::move(x.icont()); + } + //Else do a one by one move + else{ + this->assign( boost::make_move_iterator(x.begin()) + , boost::make_move_iterator(x.end())); + } + return *this; + } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! <b>Effects</b>: Makes *this contain the same elements as il. + //! + //! <b>Postcondition</b>: this->size() == il.size(). *this contains a copy + //! of each of x's elements. + //! + //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. + //! + //! <b>Complexity</b>: Linear to the number of elements in x. + list& operator=(std::initializer_list<value_type> il) + { + assign(il.begin(), il.end()); + return *this; + } +#endif + + //! <b>Effects</b>: Assigns the n copies of val to *this. + //! + //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. + //! + //! <b>Complexity</b>: Linear to n. + void assign(size_type n, const T& val) + { + typedef constant_iterator<value_type, difference_type> cvalue_iterator; + return this->assign(cvalue_iterator(val, n), cvalue_iterator()); + } + + //! <b>Effects</b>: Assigns the the range [first, last) to *this. + //! + //! <b>Throws</b>: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! <b>Complexity</b>: Linear to n. + template <class InpIt> + void assign(InpIt first, InpIt last + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + , typename container_detail::enable_if_c + < !container_detail::is_convertible<InpIt, size_type>::value + >::type * = 0 + #endif + ) + { + iterator first1 = this->begin(); + const iterator last1 = this->end(); + for ( ; first1 != last1 && first != last; ++first1, ++first) + *first1 = *first; + if (first == last) + this->erase(first1, last1); + else{ + this->insert(last1, first, last); + } + } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this. + //! + //! <b>Throws</b>: If memory allocation throws or + //! T's constructor from dereferencing std::initializer_list iterator throws. + //! + //! <b>Complexity</b>: Linear to n. + void assign(std::initializer_list<value_type> il) + { assign(il.begin(), il.end()); } +#endif + //! <b>Effects</b>: Returns a copy of the internal allocator. //! //! <b>Throws</b>: If allocator's copy constructor throws. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return allocator_type(this->node_alloc()); } - const stored_allocator_type &get_stored_allocator() const - { return this->node_alloc(); } - - stored_allocator_type &get_stored_allocator() + //! <b>Effects</b>: Returns a reference to the internal allocator. + //! + //! <b>Throws</b>: Nothing + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension. + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return this->node_alloc(); } - //! <b>Effects</b>: Erases all the elements of the list. + //! <b>Effects</b>: Returns a reference to the internal allocator. //! - //! <b>Throws</b>: Nothing. + //! <b>Throws</b>: Nothing //! - //! <b>Complexity</b>: Linear to the number of elements in the list. - void clear() - { AllocHolder::clear(alloc_version()); } + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension. + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + { return this->node_alloc(); } + + ////////////////////////////////////////////// + // + // iterators + // + ////////////////////////////////////////////// //! <b>Effects</b>: Returns an iterator to the first element contained in the list. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().begin()); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list. @@ -439,7 +505,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return this->cbegin(); } //! <b>Effects</b>: Returns an iterator to the end of the list. @@ -447,7 +513,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().end()); } //! <b>Effects</b>: Returns a const_iterator to the end of the list. @@ -455,7 +521,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return this->cend(); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning @@ -464,7 +530,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return reverse_iterator(end()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -473,7 +539,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return this->crbegin(); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the end @@ -482,7 +548,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return reverse_iterator(begin()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -491,7 +557,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return this->crend(); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list. @@ -499,7 +565,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return const_iterator(this->non_const_icont().begin()); } //! <b>Effects</b>: Returns a const_iterator to the end of the list. @@ -507,7 +573,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return const_iterator(this->non_const_icont().end()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -516,7 +582,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return const_reverse_iterator(this->cend()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -525,15 +591,21 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT { return const_reverse_iterator(this->cbegin()); } + ////////////////////////////////////////////// + // + // capacity + // + ////////////////////////////////////////////// + //! <b>Effects</b>: Returns true if the list contains no elements. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return !this->size(); } //! <b>Effects</b>: Returns the number of the elements contained in the list. @@ -541,7 +613,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return this->icont().size(); } //! <b>Effects</b>: Returns the largest possible size of the list. @@ -549,64 +621,41 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return AllocHolder::max_size(); } - #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! <b>Effects</b>: Inserts a copy of x at the beginning of the list. - //! - //! <b>Throws</b>: If memory allocation throws or - //! T's copy constructor throws. - //! - //! <b>Complexity</b>: Amortized constant time. - void push_front(const T &x); - - //! <b>Effects</b>: Constructs a new element in the beginning of the list - //! and moves the resources of mx to this new element. - //! - //! <b>Throws</b>: If memory allocation throws. - //! - //! <b>Complexity</b>: Amortized constant time. - void push_front(T &&x); - #else - BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front) - #endif - - #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! <b>Effects</b>: Inserts a copy of x at the end of the list. - //! - //! <b>Throws</b>: If memory allocation throws or - //! T's copy constructor throws. - //! - //! <b>Complexity</b>: Amortized constant time. - void push_back(const T &x); - - //! <b>Effects</b>: Constructs a new element in the end of the list - //! and moves the resources of mx to this new element. + //! <b>Effects</b>: Inserts or erases elements at the end such that + //! the size becomes n. New elements are value initialized. //! - //! <b>Throws</b>: If memory allocation throws. + //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws. //! - //! <b>Complexity</b>: Amortized constant time. - void push_back(T &&x); - #else - BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) - #endif + //! <b>Complexity</b>: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + if(!priv_try_shrink(new_size)){ + typedef value_init_construct_iterator<value_type, difference_type> value_init_iterator; + this->insert(this->cend(), value_init_iterator(new_size - this->size()), value_init_iterator()); + } + } - //! <b>Effects</b>: Removes the first element from the list. + //! <b>Effects</b>: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. //! - //! <b>Throws</b>: Nothing. + //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws. //! - //! <b>Complexity</b>: Amortized constant time. - void pop_front() - { this->erase(this->cbegin()); } + //! <b>Complexity</b>: Linear to the difference between size() and new_size. + void resize(size_type new_size, const T& x) + { + if(!priv_try_shrink(new_size)){ + this->insert(this->cend(), new_size - this->size(), x); + } + } - //! <b>Effects</b>: Removes the last element from the list. - //! - //! <b>Throws</b>: Nothing. - //! - //! <b>Complexity</b>: Amortized constant time. - void pop_back() - { const_iterator tmp = this->cend(); this->erase(--tmp); } + ////////////////////////////////////////////// + // + // element access + // + ////////////////////////////////////////////// //! <b>Requires</b>: !empty() //! @@ -616,7 +665,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference front() + reference front() BOOST_CONTAINER_NOEXCEPT { return *this->begin(); } //! <b>Requires</b>: !empty() @@ -627,7 +676,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference front() const + const_reference front() const BOOST_CONTAINER_NOEXCEPT { return *this->begin(); } //! <b>Requires</b>: !empty() @@ -638,7 +687,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference back() + reference back() BOOST_CONTAINER_NOEXCEPT { return *(--this->end()); } //! <b>Requires</b>: !empty() @@ -649,176 +698,14 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference back() const + const_reference back() const BOOST_CONTAINER_NOEXCEPT { return *(--this->end()); } - //! <b>Effects</b>: Inserts or erases elements at the end such that - //! the size becomes n. New elements are copy constructed from x. - //! - //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws. - //! - //! <b>Complexity</b>: Linear to the difference between size() and new_size. - void resize(size_type new_size, const T& x) - { - const_iterator iend = this->cend(); - size_type len = this->size(); - - if(len > new_size){ - size_type to_erase = len - new_size; - while(to_erase--){ - --iend; - } - this->erase(iend, this->cend()); - } - else{ - this->priv_create_and_insert_nodes(iend, new_size - len, x); - } - } - - //! <b>Effects</b>: Inserts or erases elements at the end such that - //! the size becomes n. New elements are default constructed. - //! - //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws. - //! - //! <b>Complexity</b>: Linear to the difference between size() and new_size. - void resize(size_type new_size) - { - const_iterator iend = this->end(); - size_type len = this->size(); - - if(len > new_size){ - size_type to_erase = len - new_size; - const_iterator ifirst; - if(to_erase < len/2u){ - ifirst = iend; - while(to_erase--){ - --ifirst; - } - } - else{ - ifirst = this->begin(); - size_type to_skip = len - to_erase; - while(to_skip--){ - ++ifirst; - } - } - this->erase(ifirst, iend); - } - else{ - this->priv_create_and_insert_nodes(this->cend(), new_size - len); - } - } - - //! <b>Effects</b>: Swaps the contents of *this and x. - //! - //! <b>Throws</b>: Nothing. - //! - //! <b>Complexity</b>: Constant. - void swap(ThisType& x) - { AllocHolder::swap(x); } - - //! <b>Effects</b>: Makes *this contain the same elements as x. - //! - //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy - //! of each of x's elements. - //! - //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. - //! - //! <b>Complexity</b>: Linear to the number of elements in x. - ThisType& operator=(BOOST_COPY_ASSIGN_REF(ThisType) x) - { - if (&x != this){ - NodeAlloc &this_alloc = this->node_alloc(); - const NodeAlloc &x_alloc = x.node_alloc(); - container_detail::bool_<allocator_traits_type:: - propagate_on_container_copy_assignment::value> flag; - if(flag && this_alloc != x_alloc){ - this->clear(); - } - this->AllocHolder::copy_assign_alloc(x); - this->assign(x.begin(), x.end()); - } - return *this; - } - - //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this. - //! - //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had - //! before the function. - //! - //! <b>Throws</b>: If allocator_type's copy constructor throws. - //! - //! <b>Complexity</b>: Constant. - ThisType& operator=(BOOST_RV_REF(ThisType) x) - { - if (&x != this){ - NodeAlloc &this_alloc = this->node_alloc(); - NodeAlloc &x_alloc = x.node_alloc(); - //If allocators are equal we can just swap pointers - if(this_alloc == x_alloc){ - //Destroy and swap pointers - this->clear(); - this->icont() = boost::move(x.icont()); - //Move allocator if needed - this->AllocHolder::move_assign_alloc(x); - } - //If unequal allocators, then do a one by one move - else{ - typedef typename std::iterator_traits<iterator>::iterator_category ItCat; - this->assign( boost::make_move_iterator(x.begin()) - , boost::make_move_iterator(x.end())); - } - } - return *this; - } - - //! <b>Requires</b>: p must be a valid iterator of *this. - //! - //! <b>Effects</b>: Inserts n copies of x before p. - //! - //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. - //! - //! <b>Complexity</b>: Linear to n. - void insert(const_iterator p, size_type n, const T& x) - { this->priv_create_and_insert_nodes(p, n, x); } - - //! <b>Requires</b>: p must be a valid iterator of *this. - //! - //! <b>Effects</b>: Insert a copy of the [first, last) range before p. - //! - //! <b>Throws</b>: If memory allocation throws, T's constructor from a - //! dereferenced InpIt throws. - //! - //! <b>Complexity</b>: Linear to std::distance [first, last). - template <class InpIt> - void insert(const_iterator p, InpIt first, InpIt last) - { - const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value; - typedef container_detail::bool_<aux_boolean> Result; - this->priv_insert_dispatch(p, first, last, Result()); - } - - #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! <b>Requires</b>: position must be a valid iterator of *this. - //! - //! <b>Effects</b>: Insert a copy of x before position. - //! - //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws. - //! - //! <b>Complexity</b>: Amortized constant time. - iterator insert(const_iterator position, const T &x); - - //! <b>Requires</b>: position must be a valid iterator of *this. - //! - //! <b>Effects</b>: Insert a new element before position with mx's resources. - //! - //! <b>Throws</b>: If memory allocation throws. - //! - //! <b>Complexity</b>: Amortized constant time. - iterator insert(const_iterator position, T &&x); - #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator) - #endif + ////////////////////////////////////////////// + // + // modifiers + // + ////////////////////////////////////////////// #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -831,9 +718,7 @@ class list //! <b>Complexity</b>: Constant template <class... Args> void emplace_back(Args&&... args) - { - this->emplace(this->cend(), boost::forward<Args>(args)...); - } + { this->emplace(this->cend(), boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... in the beginning of the list. @@ -844,9 +729,7 @@ class list //! <b>Complexity</b>: Constant template <class... Args> void emplace_front(Args&&... args) - { - this->emplace(this->cbegin(), boost::forward<Args>(args)...); - } + { this->emplace(this->cbegin(), boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... before p. @@ -893,6 +776,172 @@ class list #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! <b>Effects</b>: Inserts a copy of x at the beginning of the list. + //! + //! <b>Throws</b>: If memory allocation throws or + //! T's copy constructor throws. + //! + //! <b>Complexity</b>: Amortized constant time. + void push_front(const T &x); + + //! <b>Effects</b>: Constructs a new element in the beginning of the list + //! and moves the resources of mx to this new element. + //! + //! <b>Throws</b>: If memory allocation throws. + //! + //! <b>Complexity</b>: Amortized constant time. + void push_front(T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front) + #endif + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! <b>Effects</b>: Inserts a copy of x at the end of the list. + //! + //! <b>Throws</b>: If memory allocation throws or + //! T's copy constructor throws. + //! + //! <b>Complexity</b>: Amortized constant time. + void push_back(const T &x); + + //! <b>Effects</b>: Constructs a new element in the end of the list + //! and moves the resources of mx to this new element. + //! + //! <b>Throws</b>: If memory allocation throws. + //! + //! <b>Complexity</b>: Amortized constant time. + void push_back(T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) + #endif + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! <b>Requires</b>: p must be a valid iterator of *this. + //! + //! <b>Effects</b>: Insert a copy of x before p. + //! + //! <b>Returns</b>: an iterator to the inserted element. + //! + //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws. + //! + //! <b>Complexity</b>: Amortized constant time. + iterator insert(const_iterator p, const T &x); + + //! <b>Requires</b>: p must be a valid iterator of *this. + //! + //! <b>Effects</b>: Insert a new element before p with mx's resources. + //! + //! <b>Returns</b>: an iterator to the inserted element. + //! + //! <b>Throws</b>: If memory allocation throws. + //! + //! <b>Complexity</b>: Amortized constant time. + iterator insert(const_iterator p, T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) + #endif + + //! <b>Requires</b>: p must be a valid iterator of *this. + //! + //! <b>Effects</b>: Inserts n copies of x before p. + //! + //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0. + //! + //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. + //! + //! <b>Complexity</b>: Linear to n. + iterator insert(const_iterator p, size_type n, const T& x) + { + typedef constant_iterator<value_type, difference_type> cvalue_iterator; + return this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); + } + + //! <b>Requires</b>: p must be a valid iterator of *this. + //! + //! <b>Effects</b>: Insert a copy of the [first, last) range before p. + //! + //! <b>Returns</b>: an iterator to the first inserted element or p if first == last. + //! + //! <b>Throws</b>: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! <b>Complexity</b>: Linear to std::distance [first, last). + template <class InpIt> + iterator insert(const_iterator p, InpIt first, InpIt last + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + , typename container_detail::enable_if_c + < !container_detail::is_convertible<InpIt, size_type>::value + && (container_detail::is_input_iterator<InpIt>::value + || container_detail::is_same<alloc_version, allocator_v1>::value + ) + >::type * = 0 + #endif + ) + { + const typename Icont::iterator ipos(p.get()); + iterator ret_it(ipos); + if(first != last){ + ret_it = iterator(this->icont().insert(ipos, *this->create_node_from_it(first))); + ++first; + } + for (; first != last; ++first){ + this->icont().insert(ipos, *this->create_node_from_it(first)); + } + return ret_it; + } + + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + template <class FwdIt> + iterator insert(const_iterator p, FwdIt first, FwdIt last + , typename container_detail::enable_if_c + < !container_detail::is_convertible<FwdIt, size_type>::value + && !(container_detail::is_input_iterator<FwdIt>::value + || container_detail::is_same<alloc_version, allocator_v1>::value + ) + >::type * = 0 + ) + { + //Optimized allocation and construction + insertion_functor func(this->icont(), p.get()); + iterator before_p(p.get()); + --before_p; + this->allocate_many_and_construct(first, std::distance(first, last), func); + return ++before_p; + } + #endif + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! <b>Requires</b>: p must be a valid iterator of *this. + //! + //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before p. + //! + //! <b>Returns</b>: an iterator to the first inserted element or p if if.begin() == il.end(). + //! + //! <b>Throws</b>: If memory allocation throws, T's constructor from a + //! dereferenced std::initializer_list iterator throws. + //! + //! <b>Complexity</b>: Linear to std::distance [il.begin(), il.end()). + iterator insert(const_iterator p, std::initializer_list<value_type> il) + { return insert(p, il.begin(), il.end()); } +#endif + + //! <b>Effects</b>: Removes the first element from the list. + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Amortized constant time. + void pop_front() BOOST_CONTAINER_NOEXCEPT + { this->erase(this->cbegin()); } + + //! <b>Effects</b>: Removes the last element from the list. + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Amortized constant time. + void pop_back() BOOST_CONTAINER_NOEXCEPT + { const_iterator tmp = this->cend(); this->erase(--tmp); } + //! <b>Requires</b>: p must be a valid iterator of *this. //! //! <b>Effects</b>: Erases the element at p p. @@ -900,7 +949,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Amortized constant time. - iterator erase(const_iterator p) + iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().erase_and_dispose(p.get(), Destroyer(this->node_alloc()))); } //! <b>Requires</b>: first and last must be valid iterator to elements in *this. @@ -910,129 +959,187 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the distance between first and last. - iterator erase(const_iterator first, const_iterator last) + iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } - //! <b>Effects</b>: Assigns the n copies of val to *this. + //! <b>Effects</b>: Swaps the contents of *this and x. //! - //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. + //! <b>Throws</b>: Nothing. //! - //! <b>Complexity</b>: Linear to n. - void assign(size_type n, const T& val) - { this->priv_fill_assign(n, val); } + //! <b>Complexity</b>: Constant. + void swap(list& x) + { AllocHolder::swap(x); } - //! <b>Effects</b>: Assigns the the range [first, last) to *this. + //! <b>Effects</b>: Erases all the elements of the list. //! - //! <b>Throws</b>: If memory allocation throws or - //! T's constructor from dereferencing InpIt throws. + //! <b>Throws</b>: Nothing. //! - //! <b>Complexity</b>: Linear to n. - template <class InpIt> - void assign(InpIt first, InpIt last) - { - const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value; - typedef container_detail::bool_<aux_boolean> Result; - this->priv_assign_dispatch(first, last, Result()); - } + //! <b>Complexity</b>: Linear to the number of elements in the list. + void clear() BOOST_CONTAINER_NOEXCEPT + { AllocHolder::clear(alloc_version()); } + + ////////////////////////////////////////////// + // + // slist operations + // + ////////////////////////////////////////////// //! <b>Requires</b>: p must point to an element contained - //! by the list. x != *this + //! by the list. x != *this. this' allocator and x's allocator shall compare equal //! //! <b>Effects</b>: Transfers all the elements of list x to this list, before the //! the element pointed by p. No destructors or copy constructors are called. //! - //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. //! //! <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. - void splice(const_iterator p, ThisType& x) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, list& x) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x); + BOOST_ASSERT(this != &x); + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont()); } //! <b>Requires</b>: p must point to an element contained + //! by the list. x != *this. this' allocator and x's allocator shall compare equal + //! + //! <b>Effects</b>: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! <b>Throws</b>: Nothing + //! + //! <b>Complexity</b>: Constant. + //! + //! <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. + void splice(const_iterator p, BOOST_RV_REF(list) x) BOOST_CONTAINER_NOEXCEPT + { this->splice(p, static_cast<list&>(x)); } + + //! <b>Requires</b>: p must point to an element contained //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal //! //! <b>Effects</b>: Transfers the value pointed by i, from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! If p == i or p == ++i, this function is a null operation. //! - //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. //! //! <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. - void splice(const_iterator p, ThisType &x, const_iterator i) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, list &x, const_iterator i) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x); + //BOOST_ASSERT(this != &x); + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont(), i.get()); } //! <b>Requires</b>: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. + //! + //! <b>Effects</b>: Transfers the value pointed by i, from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! If p == i or p == ++i, this function is a null operation. + //! + //! <b>Throws</b>: Nothing + //! + //! <b>Complexity</b>: Constant. + //! + //! <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. + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator i) BOOST_CONTAINER_NOEXCEPT + { this->splice(p, static_cast<list&>(x), i); } + + //! <b>Requires</b>: p must point to an element contained //! by this list. first and last must point to elements contained in list x. + //! this' allocator and x's allocator shall compare equal //! //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! - //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Linear to the number of elements transferred. //! //! <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. - void splice(const_iterator p, ThisType &x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, list &x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x); + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont(), first.get(), last.get()); } //! <b>Requires</b>: p must point to an element contained //! by this list. first and last must point to elements contained in list x. - //! n == std::distance(first, last) + //! this' allocator and x's allocator shall compare equal. //! //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! - //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! <b>Throws</b>: Nothing + //! + //! <b>Complexity</b>: Linear to the number of elements transferred. + //! + //! <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. + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + { this->splice(p, static_cast<list&>(x), first, last); } + + //! <b>Requires</b>: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! n == std::distance(first, last). this' allocator and x's allocator shall compare equal + //! + //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! + //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. //! //! <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. - void splice(const_iterator p, ThisType &x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT + //! + //! <b>Note</b>: Non-standard extension + void splice(const_iterator p, list &x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x); + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n); } - //! <b>Effects</b>: Reverses the order of elements in the list. + //! <b>Requires</b>: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! n == std::distance(first, last). this' allocator and x's allocator shall compare equal //! - //! <b>Throws</b>: Nothing. + //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. //! - //! <b>Complexity</b>: This function is linear time. + //! <b>Throws</b>: Nothing //! - //! <b>Note</b>: Iterators and references are not invalidated - void reverse() - { this->icont().reverse(); } + //! <b>Complexity</b>: Constant. + //! + //! <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. + //! + //! <b>Note</b>: Non-standard extension + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT + { this->splice(p, static_cast<list&>(x), first, last, n); } //! <b>Effects</b>: Removes all the elements that compare equal to value. //! - //! <b>Throws</b>: Nothing. + //! <b>Throws</b>: If comparison throws. //! //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality. //! //! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. void remove(const T& value) - { remove_if(equal_to_value(value)); } + { this->remove_if(equal_to_value(value)); } //! <b>Effects</b>: Removes all the elements for which a specified //! predicate is satisfied. @@ -1053,9 +1160,9 @@ class list //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent //! elements that are equal from the list. //! - //! <b>Throws</b>: Nothing. + //! <b>Throws</b>: If comparison throws. //! - //! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()). + //! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons). //! //! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. @@ -1067,7 +1174,7 @@ class list //! //! <b>Throws</b>: If pred throws. //! - //! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons). + //! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()). //! //! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. @@ -1085,13 +1192,27 @@ class list //! that is, if an element from *this is equivalent to one from x, then the element //! from *this will precede the one from x. //! - //! <b>Throws</b>: Nothing. + //! <b>Throws</b>: If comparison throws. //! //! <b>Complexity</b>: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. - void merge(list<T, A>& x) + void merge(list &x) { this->merge(x, value_less()); } + //! <b>Requires</b>: The lists x and *this must be distinct. + //! + //! <b>Effects</b>: This function removes all of x's elements and inserts them + //! in order into *this according to std::less<value_type>. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! <b>Throws</b>: If comparison throws. + //! + //! <b>Complexity</b>: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(BOOST_RV_REF(list) x) + { this->merge(static_cast<list&>(x)); } + //! <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 //! The lists x and *this must be distinct. @@ -1100,31 +1221,45 @@ class list //! in order into *this. The merge is stable; that is, if an element from *this is //! equivalent to one from x, then the element from *this will precede the one from x. //! - //! <b>Throws</b>: Nothing. + //! <b>Throws</b>: If comp throws. //! //! <b>Complexity</b>: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. //! //! <b>Note</b>: Iterators and references to *this are not invalidated. template <class StrictWeakOrdering> - void merge(list &x, StrictWeakOrdering comp) + void merge(list &x, const StrictWeakOrdering &comp) { - if((NodeAlloc&)*this == (NodeAlloc&)x){ - this->icont().merge(x.icont(), - ValueCompareToNodeCompare<StrictWeakOrdering>(comp)); - } - else{ - throw std::runtime_error("list::merge called with unequal allocators"); - } + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().merge(x.icont(), + ValueCompareToNodeCompare<StrictWeakOrdering>(comp)); } + //! <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 + //! The lists x and *this must be distinct. + //! + //! <b>Effects</b>: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! <b>Throws</b>: If comp throws. + //! + //! <b>Complexity</b>: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! <b>Note</b>: Iterators and references to *this are not invalidated. + template <class StrictWeakOrdering> + void merge(BOOST_RV_REF(list) x, StrictWeakOrdering comp) + { this->merge(static_cast<list&>(x), comp); } + //! <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. //! - //! <b>Throws</b>: Nothing. + //! <b>Throws</b>: If comparison throws. //! //! <b>Notes</b>: Iterators and references are not invalidated. - //! + //! //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N //! is the list's size. void sort() @@ -1133,7 +1268,7 @@ class list //! <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. //! - //! <b>Throws</b>: Nothing. + //! <b>Throws</b>: If comp throws. //! //! <b>Notes</b>: Iterators and references are not invalidated. //! @@ -1148,9 +1283,103 @@ class list this->icont().sort(ValueCompareToNodeCompare<StrictWeakOrdering>(comp)); } - /// @cond + //! <b>Effects</b>: Reverses the order of elements in the list. + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: This function is linear time. + //! + //! <b>Note</b>: Iterators and references are not invalidated + void reverse() BOOST_CONTAINER_NOEXCEPT + { this->icont().reverse(); } + + //! <b>Effects</b>: Returns true if x and y are equal + //! + //! <b>Complexity</b>: Linear to the number of elements in the container. + friend bool operator==(const list& x, const list& y) + { + if(x.size() != y.size()){ + return false; + } + typedef typename list::const_iterator const_iterator; + const_iterator end1 = x.end(); + + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; + } + + //! <b>Effects</b>: Returns true if x and y are unequal + //! + //! <b>Complexity</b>: Linear to the number of elements in the container. + friend bool operator!=(const list& x, const list& y) + { return !(x == y); } + + //! <b>Effects</b>: Returns true if x is less than y + //! + //! <b>Complexity</b>: Linear to the number of elements in the container. + friend bool operator<(const list& x, const list& y) + { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + //! <b>Effects</b>: Returns true if x is greater than y + //! + //! <b>Complexity</b>: Linear to the number of elements in the container. + friend bool operator>(const list& x, const list& y) + { return y < x; } + + //! <b>Effects</b>: Returns true if x is equal or less than y + //! + //! <b>Complexity</b>: Linear to the number of elements in the container. + friend bool operator<=(const list& x, const list& y) + { return !(y < x); } + + //! <b>Effects</b>: Returns true if x is equal or greater than y + //! + //! <b>Complexity</b>: Linear to the number of elements in the container. + friend bool operator>=(const list& x, const list& y) + { return !(x < y); } + + //! <b>Effects</b>: x.swap(y) + //! + //! <b>Complexity</b>: Constant. + friend void swap(list& x, list& y) + { x.swap(y); } + + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: + bool priv_try_shrink(size_type new_size) + { + const size_type len = this->size(); + if(len > new_size){ + const const_iterator iend = this->cend(); + size_type to_erase = len - new_size; + const_iterator ifirst; + if(to_erase < len/2u){ + ifirst = iend; + while(to_erase--){ + --ifirst; + } + } + else{ + ifirst = this->cbegin(); + size_type to_skip = len - to_erase; + while(to_skip--){ + ++ifirst; + } + } + this->erase(ifirst, iend); + return true; + } + else{ + return false; + } + } + iterator priv_insert(const_iterator p, const T &x) { NodePtr tmp = AllocHolder::create_node(x); @@ -1163,50 +1392,26 @@ class list return iterator(this->icont().insert(p.get(), *tmp)); } - void priv_push_back (const T &x) + void priv_push_back (const T &x) { this->insert(this->cend(), x); } void priv_push_back (BOOST_RV_REF(T) x) { this->insert(this->cend(), boost::move(x)); } - void priv_push_front (const T &x) + void priv_push_front (const T &x) { this->insert(this->cbegin(), x); } void priv_push_front (BOOST_RV_REF(T) x) { this->insert(this->cbegin(), boost::move(x)); } - //Iterator range version - template<class InpIterator> - void priv_create_and_insert_nodes - (const_iterator pos, InpIterator beg, InpIterator end) - { - typedef typename std::iterator_traits<InpIterator>::iterator_category ItCat; - priv_create_and_insert_nodes(pos, beg, end, alloc_version(), ItCat()); - } - - template<class InpIterator> - void priv_create_and_insert_nodes - (const_iterator pos, InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag) - { - for (; beg != end; ++beg){ - this->icont().insert(pos.get(), *this->create_node_from_it(beg)); - } - } - - template<class InpIterator> - void priv_create_and_insert_nodes - (const_iterator pos, InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag) - { //Just forward to the default one - priv_create_and_insert_nodes(pos, beg, end, allocator_v1(), std::input_iterator_tag()); - } - class insertion_functor; friend class insertion_functor; class insertion_functor { Icont &icont_; - typename Icont::const_iterator pos_; + typedef typename Icont::const_iterator iconst_iterator; + const iconst_iterator pos_; public: insertion_functor(Icont &icont, typename Icont::const_iterator pos) @@ -1214,77 +1419,10 @@ class list {} void operator()(Node &n) - { this->icont_.insert(pos_, n); } - }; - - - template<class FwdIterator> - void priv_create_and_insert_nodes - (const_iterator pos, FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag) - { - if(beg != end){ - //Optimized allocation and construction - this->allocate_many_and_construct - (beg, std::distance(beg, end), insertion_functor(this->icont(), pos.get())); + { + this->icont_.insert(pos_, n); } - } - - //Default constructed version - void priv_create_and_insert_nodes(const_iterator pos, size_type n) - { - typedef default_construct_iterator<value_type, difference_type> default_iterator; - this->priv_create_and_insert_nodes(pos, default_iterator(n), default_iterator()); - } - - //Copy constructed version - void priv_create_and_insert_nodes(const_iterator pos, size_type n, const T& x) - { - typedef constant_iterator<value_type, difference_type> cvalue_iterator; - this->priv_create_and_insert_nodes(pos, cvalue_iterator(x, n), cvalue_iterator()); - } - - //Dispatch to detect iterator range or integer overloads - template <class InputIter> - void priv_insert_dispatch(const_iterator p, - InputIter first, InputIter last, - container_detail::false_) - { this->priv_create_and_insert_nodes(p, first, last); } - - template<class Integer> - void priv_insert_dispatch(const_iterator p, Integer n, Integer x, container_detail::true_) - { this->insert(p, (size_type)n, x); } - - void priv_fill_assign(size_type n, const T& val) - { - iterator i = this->begin(), iend = this->end(); - - for ( ; i != iend && n > 0; ++i, --n) - *i = val; - if (n > 0){ - this->priv_create_and_insert_nodes(this->cend(), n, val); - } - else{ - this->erase(i, cend()); - } - } - - template <class Integer> - void priv_assign_dispatch(Integer n, Integer val, container_detail::true_) - { this->priv_fill_assign((size_type) n, (T) val); } - - template <class InputIter> - void priv_assign_dispatch(InputIter first2, InputIter last2, container_detail::false_) - { - iterator first1 = this->begin(); - iterator last1 = this->end(); - for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) - *first1 = *first2; - if (first2 == last2) - this->erase(first1, last1); - else{ - this->priv_create_and_insert_nodes(last1, first2, last2); - } - } + }; //Functors for member algorithm defaults struct value_less @@ -1298,83 +1436,27 @@ class list bool operator()(const value_type &a, const value_type &b) const { return a == b; } }; - /// @endcond + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -template <class T, class A> -inline bool operator==(const list<T,A>& x, const list<T,A>& y) -{ - if(x.size() != y.size()){ - return false; - } - typedef typename list<T,A>::const_iterator const_iterator; - const_iterator end1 = x.end(); - - const_iterator i1 = x.begin(); - const_iterator i2 = y.begin(); - while (i1 != end1 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1; -} - -template <class T, class A> -inline bool operator<(const list<T,A>& x, - const list<T,A>& y) -{ - return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); -} - -template <class T, class A> -inline bool operator!=(const list<T,A>& x, const list<T,A>& y) -{ - return !(x == y); -} - -template <class T, class A> -inline bool operator>(const list<T,A>& x, const list<T,A>& y) -{ - return y < x; -} - -template <class T, class A> -inline bool operator<=(const list<T,A>& x, const list<T,A>& y) -{ - return !(y < x); -} - -template <class T, class A> -inline bool operator>=(const list<T,A>& x, const list<T,A>& y) -{ - return !(x < y); -} - -template <class T, class A> -inline void swap(list<T, A>& x, list<T, A>& y) -{ - x.swap(y); -} - -/// @cond +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED } //namespace container { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class T, class A> -struct has_trivial_destructor_after_move<boost::container::list<T, A> > -{ - static const bool value = has_trivial_destructor<A>::value; -}; -*/ +template <class T, class Allocator> +struct has_trivial_destructor_after_move<boost::container::list<T, Allocator> > + : public ::boost::has_trivial_destructor_after_move<Allocator> +{}; + namespace container { -/// @endcond +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }} #include <boost/container/detail/config_end.hpp> -#endif // BOOST_CONTAINER_LIST_HPP_ +#endif // BOOST_CONTAINER_LIST_HPP |