summaryrefslogtreecommitdiff
path: root/boost/container/list.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container/list.hpp')
-rw-r--r--boost/container/list.hpp1390
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