- Added nth and index_of.

- Used BOOST_MOVE_BASE
This commit is contained in:
Ion Gaztañaga
2014-11-01 20:03:25 +01:00
parent 6d034733bd
commit 6f1f162cb3
21 changed files with 615 additions and 106 deletions

View File

@@ -1079,6 +1079,11 @@ use [*Boost.Container]? There are several reasons for that:
[section:release_notes Release Notes] [section:release_notes Release Notes]
[section:release_notes_boost_1_58_00 Boost 1.58 Release]
* Added `nth` and `index_of` functions to containers with random-access iterators (except `basic_string`).
[endsect]
[section:release_notes_boost_1_57_00 Boost 1.57 Release] [section:release_notes_boost_1_57_00 Boost 1.57 Release]
* Added support for `initializer_list`. Contributed by Robert Matusewicz. * Added support for `initializer_list`. Contributed by Robert Matusewicz.
* Fixed double destruction bugs in vector and backward expansion capable allocators. * Fixed double destruction bugs in vector and backward expansion capable allocators.

View File

@@ -639,13 +639,13 @@ class deque : protected deque_base<Allocator>
} }
} }
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this. //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
//! //!
//! <b>Throws</b>: If allocator_type's copy constructor throws. //! <b>Throws</b>: If allocator_type's copy constructor throws.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
deque(BOOST_RV_REF(deque) x) deque(BOOST_RV_REF(deque) x)
: Base(boost::move(static_cast<Base&>(x))) : Base(BOOST_MOVE_BASE(Base, x))
{ this->swap_members(x); } { this->swap_members(x); }
//! <b>Effects</b>: Copy constructs a vector using the specified allocator. //! <b>Effects</b>: Copy constructs a vector using the specified allocator.
@@ -667,23 +667,23 @@ class deque : protected deque_base<Allocator>
} }
//! <b>Effects</b>: Move constructor using the specified allocator. //! <b>Effects</b>: Move constructor using the specified allocator.
//! Moves mx's resources to *this if a == allocator_type(). //! Moves x's resources to *this if a == allocator_type().
//! Otherwise copies values from x to *this. //! Otherwise copies values from x to *this.
//! //!
//! <b>Throws</b>: If allocation or T's copy constructor throws. //! <b>Throws</b>: If allocation or T's copy constructor throws.
//! //!
//! <b>Complexity</b>: Constant if a == mx.get_allocator(), linear otherwise. //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
deque(BOOST_RV_REF(deque) mx, const allocator_type &a) deque(BOOST_RV_REF(deque) x, const allocator_type &a)
: Base(a) : Base(a)
{ {
if(mx.alloc() == a){ if(x.alloc() == a){
this->swap_members(mx); this->swap_members(x);
} }
else{ else{
if(mx.size()){ if(x.size()){
this->priv_initialize_map(mx.size()); this->priv_initialize_map(x.size());
boost::container::uninitialized_copy_alloc boost::container::uninitialized_copy_alloc
(this->alloc(), mx.begin(), mx.end(), this->members_.m_start); (this->alloc(), x.begin(), x.end(), this->members_.m_start);
} }
} }
} }
@@ -1158,6 +1158,67 @@ class deque : protected deque_base<Allocator>
const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return this->members_.m_start[difference_type(n)]; } { return this->members_.m_start[difference_type(n)]; }
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
iterator nth(size_type n) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(this->size() >= n);
return iterator(this->begin()+n);
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns a const_iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
const_iterator nth(size_type n) const BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(this->size() >= n);
return const_iterator(this->cbegin()+n);
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
size_type index_of(iterator p) BOOST_CONTAINER_NOEXCEPT
{ return this->priv_index_of(p); }
//! <b>Requires</b>: begin() <= p <= end().
//!
//! <b>Effects</b>: Returns the index of the element pointed by p
//! and size() if p == end().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
size_type index_of(const_iterator p) const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_index_of(p); }
//! <b>Requires</b>: size() > n. //! <b>Requires</b>: size() > n.
//! //!
//! <b>Effects</b>: Returns a reference to the nth element //! <b>Effects</b>: Returns a reference to the nth element
@@ -1333,7 +1394,7 @@ class deque : protected deque_base<Allocator>
void push_front(const T &x); void push_front(const T &x);
//! <b>Effects</b>: Constructs a new element in the front of the deque //! <b>Effects</b>: Constructs a new element in the front of the deque
//! and moves the resources of mx to this new element. //! and moves the resources of x to this new element.
//! //!
//! <b>Throws</b>: If memory allocation throws. //! <b>Throws</b>: If memory allocation throws.
//! //!
@@ -1353,7 +1414,7 @@ class deque : protected deque_base<Allocator>
void push_back(const T &x); void push_back(const T &x);
//! <b>Effects</b>: Constructs a new element in the end of the deque //! <b>Effects</b>: Constructs a new element in the end of the deque
//! and moves the resources of mx to this new element. //! and moves the resources of x to this new element.
//! //!
//! <b>Throws</b>: If memory allocation throws. //! <b>Throws</b>: If memory allocation throws.
//! //!
@@ -1379,7 +1440,7 @@ class deque : protected deque_base<Allocator>
//! <b>Requires</b>: p must be a valid iterator of *this. //! <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>Effects</b>: Insert a new element before p with x's resources.
//! //!
//! <b>Returns</b>: an iterator to the inserted element. //! <b>Returns</b>: an iterator to the inserted element.
//! //!
@@ -1648,6 +1709,13 @@ class deque : protected deque_base<Allocator>
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
size_type priv_index_of(const_iterator p) const
{
BOOST_ASSERT(this->cbegin() <= p);
BOOST_ASSERT(p <= this->cend());
return static_cast<size_type>(p - this->cbegin());
}
void priv_erase_last_n(size_type n) void priv_erase_last_n(size_type n)
{ {
if(n == this->size()) { if(n == this->size()) {

View File

@@ -265,8 +265,8 @@ class flat_tree
flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x) flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x)
{ m_data = x.m_data; return *this; } { m_data = x.m_data; return *this; }
flat_tree& operator=(BOOST_RV_REF(flat_tree) mx) flat_tree& operator=(BOOST_RV_REF(flat_tree) x)
{ m_data = boost::move(mx.m_data); return *this; } { m_data = boost::move(x.m_data); return *this; }
public: public:
// accessors: // accessors:
@@ -632,6 +632,18 @@ class flat_tree
void shrink_to_fit() void shrink_to_fit()
{ this->m_data.m_vect.shrink_to_fit(); } { this->m_data.m_vect.shrink_to_fit(); }
iterator nth(size_type n) BOOST_CONTAINER_NOEXCEPT
{ return this->m_data.m_vect.nth(n); }
const_iterator nth(size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return this->m_data.m_vect.nth(n); }
size_type index_of(iterator p) BOOST_CONTAINER_NOEXCEPT
{ return this->m_data.m_vect.index_of(p); }
size_type index_of(const_iterator p) const BOOST_CONTAINER_NOEXCEPT
{ return this->m_data.m_vect.index_of(p); }
// set operations: // set operations:
iterator find(const key_type& k) iterator find(const key_type& k)
{ {

View File

@@ -851,9 +851,9 @@ class tree
template<class MovableConvertible> template<class MovableConvertible>
iterator insert_unique_commit iterator insert_unique_commit
(BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data) (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data)
{ {
NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(mv)); NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(v));
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
iterator ret(this->icont().insert_unique_commit(*tmp, data)); iterator ret(this->icont().insert_unique_commit(*tmp, data));
destroy_deallocator.release(); destroy_deallocator.release();
@@ -872,13 +872,13 @@ class tree
} }
template<class MovableConvertible> template<class MovableConvertible>
std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) mv) std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) v)
{ {
insert_commit_data data; insert_commit_data data;
std::pair<iterator,bool> ret = std::pair<iterator,bool> ret =
this->insert_unique_check(KeyOfValue()(mv), data); this->insert_unique_check(KeyOfValue()(v), data);
if(ret.second){ if(ret.second){
ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data); ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
} }
return ret; return ret;
} }
@@ -886,9 +886,9 @@ class tree
private: private:
template<class MovableConvertible> template<class MovableConvertible>
void push_back_impl(BOOST_FWD_REF(MovableConvertible) mv) void push_back_impl(BOOST_FWD_REF(MovableConvertible) v)
{ {
NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
//push_back has no-throw guarantee so avoid any deallocator/destroyer //push_back has no-throw guarantee so avoid any deallocator/destroyer
this->icont().push_back(*tmp); this->icont().push_back(*tmp);
} }
@@ -1010,14 +1010,14 @@ class tree
} }
template<class MovableConvertible> template<class MovableConvertible>
iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
{ {
insert_commit_data data; insert_commit_data data;
std::pair<iterator,bool> ret = std::pair<iterator,bool> ret =
this->insert_unique_check(hint, KeyOfValue()(mv), data); this->insert_unique_check(hint, KeyOfValue()(v), data);
if(!ret.second) if(!ret.second)
return ret.first; return ret.first;
return this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data); return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
} }
template <class InputIterator> template <class InputIterator>
@@ -1037,9 +1037,9 @@ class tree
} }
template<class MovableConvertible> template<class MovableConvertible>
iterator insert_equal(BOOST_FWD_REF(MovableConvertible) mv) iterator insert_equal(BOOST_FWD_REF(MovableConvertible) v)
{ {
NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
destroy_deallocator.release(); destroy_deallocator.release();
@@ -1056,9 +1056,9 @@ class tree
} }
template<class MovableConvertible> template<class MovableConvertible>
iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
{ {
NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
iterator ret(this->icont().insert_equal(hint.get(), *tmp)); iterator ret(this->icont().insert_equal(hint.get(), *tmp));
destroy_deallocator.release(); destroy_deallocator.release();

View File

@@ -115,6 +115,7 @@ class flat_map
typedef typename impl_tree_t::value_type impl_value_type; typedef typename impl_tree_t::value_type impl_value_type;
typedef typename impl_tree_t::const_iterator impl_const_iterator; typedef typename impl_tree_t::const_iterator impl_const_iterator;
typedef typename impl_tree_t::iterator impl_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type; typedef typename impl_tree_t::allocator_type impl_allocator_type;
typedef container_detail::flat_tree_value_compare typedef container_detail::flat_tree_value_compare
< Compare < Compare
@@ -556,6 +557,22 @@ class flat_map
BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript) BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
#endif #endif
//! @copydoc ::boost::container::flat_set::nth(size_type)
iterator nth(size_type n) BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::nth(size_type) const
const_iterator nth(size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::index_of(iterator)
size_type index_of(iterator p) BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.index_of(container_detail::force_copy<impl_iterator>(p)); }
//! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
size_type index_of(const_iterator p) const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.index_of(container_detail::force_copy<impl_const_iterator>(p)); }
//! Returns: Allocator reference to the element whose key is equivalent to x. //! Returns: Allocator reference to the element whose key is equivalent to x.
//! //!
//! Throws: An exception object of type out_of_range if no such element is present. //! Throws: An exception object of type out_of_range if no such element is present.
@@ -1085,6 +1102,7 @@ class flat_multimap
typedef typename impl_tree_t::value_type impl_value_type; typedef typename impl_tree_t::value_type impl_value_type;
typedef typename impl_tree_t::const_iterator impl_const_iterator; typedef typename impl_tree_t::const_iterator impl_const_iterator;
typedef typename impl_tree_t::iterator impl_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type; typedef typename impl_tree_t::allocator_type impl_allocator_type;
typedef container_detail::flat_tree_value_compare typedef container_detail::flat_tree_value_compare
< Compare < Compare
@@ -1493,11 +1511,21 @@ class flat_multimap
void shrink_to_fit() void shrink_to_fit()
{ m_flat_tree.shrink_to_fit(); } { m_flat_tree.shrink_to_fit(); }
////////////////////////////////////////////// //! @copydoc ::boost::container::flat_set::nth(size_type)
// iterator nth(size_type n) BOOST_CONTAINER_NOEXCEPT
// modifiers { return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }
//
////////////////////////////////////////////// //! @copydoc ::boost::container::flat_set::nth(size_type) const
const_iterator nth(size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::index_of(iterator)
size_type index_of(iterator p) BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.index_of(container_detail::force_copy<impl_iterator>(p)); }
//! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
size_type index_of(const_iterator p) const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.index_of(container_detail::force_copy<impl_const_iterator>(p)); }
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)

View File

@@ -187,13 +187,13 @@ class flat_set
: base_t(static_cast<const base_t&>(x)) : base_t(static_cast<const base_t&>(x))
{} {}
//! <b>Effects</b>: Move constructs thecontainer. Constructs *this using mx's resources. //! <b>Effects</b>: Move constructs thecontainer. Constructs *this using x's resources.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
//! //!
//! <b>Postcondition</b>: mx is emptied. //! <b>Postcondition</b>: x is emptied.
flat_set(BOOST_RV_REF(flat_set) mx) flat_set(BOOST_RV_REF(flat_set) x)
: base_t(boost::move(static_cast<base_t&>(mx))) : base_t(BOOST_MOVE_BASE(base_t, x))
{} {}
//! <b>Effects</b>: Copy constructs a container using the specified allocator. //! <b>Effects</b>: Copy constructs a container using the specified allocator.
@@ -204,11 +204,11 @@ class flat_set
{} {}
//! <b>Effects</b>: Move constructs a container using the specified allocator. //! <b>Effects</b>: Move constructs a container using the specified allocator.
//! Constructs *this using mx's resources. //! Constructs *this using x's resources.
//! //!
//! <b>Complexity</b>: Constant if a == mx.get_allocator(), linear otherwise //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise
flat_set(BOOST_RV_REF(flat_set) mx, const allocator_type &a) flat_set(BOOST_RV_REF(flat_set) x, const allocator_type &a)
: base_t(boost::move(static_cast<base_t&>(mx)), a) : base_t(BOOST_MOVE_BASE(base_t, x), a)
{} {}
//! <b>Effects</b>: Makes *this a copy of x. //! <b>Effects</b>: Makes *this a copy of x.
@@ -225,7 +225,7 @@ class flat_set
//! this->get>allocator() == x.get_allocator(). Linear otherwise. //! this->get>allocator() == x.get_allocator(). Linear otherwise.
flat_set& operator=(BOOST_RV_REF(flat_set) x) flat_set& operator=(BOOST_RV_REF(flat_set) x)
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
{ return static_cast<flat_set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } { return static_cast<flat_set&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: Copy all elements from il to *this. //! <b>Effects</b>: Copy all elements from il to *this.
@@ -646,6 +646,57 @@ class flat_set
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
const_iterator find(const key_type& x) const; const_iterator find(const key_type& x) const;
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
iterator nth(size_type n) BOOST_CONTAINER_NOEXCEPT;
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns a const_iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
const_iterator nth(size_type n) const BOOST_CONTAINER_NOEXCEPT;
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
size_type index_of(iterator p) BOOST_CONTAINER_NOEXCEPT;
//! <b>Requires</b>: begin() <= p <= end().
//!
//! <b>Effects</b>: Returns the index of the element pointed by p
//! and size() if p == end().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
size_type index_of(const_iterator p) const BOOST_CONTAINER_NOEXCEPT;
#endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Returns</b>: The number of elements with key equivalent to x. //! <b>Returns</b>: The number of elements with key equivalent to x.
@@ -876,8 +927,8 @@ class flat_multiset
{} {}
//! @copydoc ::boost::container::flat_set(flat_set &&) //! @copydoc ::boost::container::flat_set(flat_set &&)
flat_multiset(BOOST_RV_REF(flat_multiset) mx) flat_multiset(BOOST_RV_REF(flat_multiset) x)
: base_t(boost::move(static_cast<base_t&>(mx))) : base_t(boost::move(static_cast<base_t&>(x)))
{} {}
//! @copydoc ::boost::container::flat_set(const flat_set &, const allocator_type &) //! @copydoc ::boost::container::flat_set(const flat_set &, const allocator_type &)
@@ -886,8 +937,8 @@ class flat_multiset
{} {}
//! @copydoc ::boost::container::flat_set(flat_set &&, const allocator_type &) //! @copydoc ::boost::container::flat_set(flat_set &&, const allocator_type &)
flat_multiset(BOOST_RV_REF(flat_multiset) mx, const allocator_type &a) flat_multiset(BOOST_RV_REF(flat_multiset) x, const allocator_type &a)
: base_t(boost::move(static_cast<base_t&>(mx)), a) : base_t(BOOST_MOVE_BASE(base_t, x), a)
{} {}
//! @copydoc ::boost::container::flat_set::operator=(const flat_set &) //! @copydoc ::boost::container::flat_set::operator=(const flat_set &)
@@ -895,9 +946,9 @@ class flat_multiset
{ return static_cast<flat_multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); } { return static_cast<flat_multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! @copydoc ::boost::container::flat_set::operator=(flat_set &&) //! @copydoc ::boost::container::flat_set::operator=(flat_set &&)
flat_multiset& operator=(BOOST_RV_REF(flat_multiset) mx) flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x)
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
{ return static_cast<flat_multiset&>(this->base_t::operator=(boost::move(static_cast<base_t&>(mx)))); } { return static_cast<flat_multiset&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @copydoc ::boost::container::flat_set::operator=(std::initializer_list<value_type>) //! @copydoc ::boost::container::flat_set::operator=(std::initializer_list<value_type>)
@@ -1157,6 +1208,18 @@ class flat_multiset
//! @copydoc ::boost::container::flat_set::find(const key_type& ) const //! @copydoc ::boost::container::flat_set::find(const key_type& ) const
const_iterator find(const key_type& x) const; const_iterator find(const key_type& x) const;
//! @copydoc ::boost::container::flat_set::nth(size_type)
iterator nth(size_type n) BOOST_CONTAINER_NOEXCEPT;
//! @copydoc ::boost::container::flat_set::nth(size_type) const
const_iterator nth(size_type n) const BOOST_CONTAINER_NOEXCEPT;
//! @copydoc ::boost::container::flat_set::index_of(iterator)
size_type index_of(iterator p) BOOST_CONTAINER_NOEXCEPT;
//! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
size_type index_of(const_iterator p) const BOOST_CONTAINER_NOEXCEPT;
//! @copydoc ::boost::container::flat_set::count(const key_type& ) const //! @copydoc ::boost::container::flat_set::count(const key_type& ) const
size_type count(const key_type& x) const; size_type count(const key_type& x) const;

View File

@@ -259,13 +259,13 @@ class list
: AllocHolder(x) : AllocHolder(x)
{ this->insert(this->cbegin(), x.begin(), x.end()); } { this->insert(this->cbegin(), x.begin(), x.end()); }
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this. //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
//! //!
//! <b>Throws</b>: If allocator_type's copy constructor throws. //! <b>Throws</b>: If allocator_type's copy constructor throws.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
list(BOOST_RV_REF(list) x) list(BOOST_RV_REF(list) x)
: AllocHolder(boost::move(static_cast<AllocHolder&>(x))) : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x))
{} {}
//! <b>Effects</b>: Copy constructs a list using the specified allocator. //! <b>Effects</b>: Copy constructs a list using the specified allocator.
@@ -280,7 +280,7 @@ class list
{ this->insert(this->cbegin(), x.begin(), x.end()); } { this->insert(this->cbegin(), x.begin(), x.end()); }
//! <b>Effects</b>: Move constructor sing the specified allocator. //! <b>Effects</b>: Move constructor sing the specified allocator.
//! Moves mx's resources to *this. //! Moves x's resources to *this.
//! //!
//! <b>Throws</b>: If allocation or value_type's copy constructor throws. //! <b>Throws</b>: If allocation or value_type's copy constructor throws.
//! //!
@@ -786,7 +786,7 @@ class list
void push_front(const T &x); void push_front(const T &x);
//! <b>Effects</b>: Constructs a new element in the beginning of the list //! <b>Effects</b>: Constructs a new element in the beginning of the list
//! and moves the resources of mx to this new element. //! and moves the resources of x to this new element.
//! //!
//! <b>Throws</b>: If memory allocation throws. //! <b>Throws</b>: If memory allocation throws.
//! //!
@@ -806,7 +806,7 @@ class list
void push_back(const T &x); void push_back(const T &x);
//! <b>Effects</b>: Constructs a new element in the end of the list //! <b>Effects</b>: Constructs a new element in the end of the list
//! and moves the resources of mx to this new element. //! and moves the resources of x to this new element.
//! //!
//! <b>Throws</b>: If memory allocation throws. //! <b>Throws</b>: If memory allocation throws.
//! //!
@@ -830,7 +830,7 @@ class list
//! <b>Requires</b>: p must be a valid iterator of *this. //! <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>Effects</b>: Insert a new element before p with x's resources.
//! //!
//! <b>Returns</b>: an iterator to the inserted element. //! <b>Returns</b>: an iterator to the inserted element.
//! //!

View File

@@ -223,7 +223,7 @@ class map
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
map(BOOST_RV_REF(map) x) map(BOOST_RV_REF(map) x)
: base_t(boost::move(static_cast<base_t&>(x))) : base_t(BOOST_MOVE_BASE(base_t, x))
{ {
//Allocator type must be std::pair<CONST Key, T> //Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
@@ -246,7 +246,7 @@ class map
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
map(BOOST_RV_REF(map) x, const allocator_type &a) map(BOOST_RV_REF(map) x, const allocator_type &a)
: base_t(boost::move(static_cast<base_t&>(x)), a) : base_t(BOOST_MOVE_BASE(base_t, x), a)
{ {
//Allocator type must be std::pair<CONST Key, T> //Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
@@ -268,7 +268,7 @@ class map
//! this->get>allocator() == x.get_allocator(). Linear otherwise. //! this->get>allocator() == x.get_allocator(). Linear otherwise.
map& operator=(BOOST_RV_REF(map) x) map& operator=(BOOST_RV_REF(map) x)
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
{ return static_cast<map&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } { return static_cast<map&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: Assign content of il to *this. //! <b>Effects</b>: Assign content of il to *this.
@@ -1021,7 +1021,7 @@ class multimap
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
multimap(BOOST_RV_REF(multimap) x) multimap(BOOST_RV_REF(multimap) x)
: base_t(boost::move(static_cast<base_t&>(x))) : base_t(BOOST_MOVE_BASE(base_t, x))
{ {
//Allocator type must be std::pair<CONST Key, T> //Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
@@ -1043,7 +1043,7 @@ class multimap
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
multimap(BOOST_RV_REF(multimap) x, const allocator_type &a) multimap(BOOST_RV_REF(multimap) x, const allocator_type &a)
: base_t(boost::move(static_cast<base_t&>(x)), a) : base_t(BOOST_MOVE_BASE(base_t, x), a)
{ {
//Allocator type must be std::pair<CONST Key, T> //Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
@@ -1059,7 +1059,7 @@ class multimap
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
multimap& operator=(BOOST_RV_REF(multimap) x) multimap& operator=(BOOST_RV_REF(multimap) x)
{ return static_cast<multimap&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } { return static_cast<multimap&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: Assign content of il to *this. //! <b>Effects</b>: Assign content of il to *this.

View File

@@ -188,7 +188,7 @@ class set
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
set(BOOST_RV_REF(set) x) set(BOOST_RV_REF(set) x)
: base_t(boost::move(static_cast<base_t&>(x))) : base_t(BOOST_MOVE_BASE(base_t, x))
{} {}
//! <b>Effects</b>: Copy constructs a set using the specified allocator. //! <b>Effects</b>: Copy constructs a set using the specified allocator.
@@ -203,7 +203,7 @@ class set
//! //!
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
set(BOOST_RV_REF(set) x, const allocator_type &a) set(BOOST_RV_REF(set) x, const allocator_type &a)
: base_t(boost::move(static_cast<base_t&>(x)), a) : base_t(BOOST_MOVE_BASE(base_t, x), a)
{} {}
//! <b>Effects</b>: Makes *this a copy of x. //! <b>Effects</b>: Makes *this a copy of x.
@@ -222,7 +222,7 @@ class set
//! this->get>allocator() == x.get_allocator(). Linear otherwise. //! this->get>allocator() == x.get_allocator(). Linear otherwise.
set& operator=(BOOST_RV_REF(set) x) set& operator=(BOOST_RV_REF(set) x)
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
{ return static_cast<set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } { return static_cast<set&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
set& operator=(std::initializer_list<value_type> il) set& operator=(std::initializer_list<value_type> il)
@@ -812,7 +812,7 @@ class multiset
//! @copydoc ::boost::container::set(set &&) //! @copydoc ::boost::container::set(set &&)
multiset(BOOST_RV_REF(multiset) x) multiset(BOOST_RV_REF(multiset) x)
: base_t(boost::move(static_cast<base_t&>(x))) : base_t(BOOST_MOVE_BASE(base_t, x))
{} {}
//! @copydoc ::boost::container::set(const set &, const allocator_type &) //! @copydoc ::boost::container::set(const set &, const allocator_type &)
@@ -822,7 +822,7 @@ class multiset
//! @copydoc ::boost::container::set(set &&, const allocator_type &) //! @copydoc ::boost::container::set(set &&, const allocator_type &)
multiset(BOOST_RV_REF(multiset) x, const allocator_type &a) multiset(BOOST_RV_REF(multiset) x, const allocator_type &a)
: base_t(boost::move(static_cast<base_t&>(x)), a) : base_t(BOOST_MOVE_BASE(base_t, x), a)
{} {}
//! @copydoc ::boost::container::set::operator=(const set &) //! @copydoc ::boost::container::set::operator=(const set &)
@@ -831,7 +831,7 @@ class multiset
//! @copydoc ::boost::container::set::operator=(set &&) //! @copydoc ::boost::container::set::operator=(set &&)
multiset& operator=(BOOST_RV_REF(multiset) x) multiset& operator=(BOOST_RV_REF(multiset) x)
{ return static_cast<multiset&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } { return static_cast<multiset&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @copydoc ::boost::container::set::operator=(std::initializer_list<value_type>) //! @copydoc ::boost::container::set::operator=(std::initializer_list<value_type>)

View File

@@ -307,13 +307,13 @@ class slist
: AllocHolder(x) : AllocHolder(x)
{ this->insert_after(this->cbefore_begin(), x.begin(), x.end()); } { this->insert_after(this->cbefore_begin(), x.begin(), x.end()); }
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this. //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
//! //!
//! <b>Throws</b>: If allocator_type's copy constructor throws. //! <b>Throws</b>: If allocator_type's copy constructor throws.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
slist(BOOST_RV_REF(slist) x) slist(BOOST_RV_REF(slist) x)
: AllocHolder(boost::move(static_cast<AllocHolder&>(x))) : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x))
{} {}
//! <b>Effects</b>: Copy constructs a list using the specified allocator. //! <b>Effects</b>: Copy constructs a list using the specified allocator.
@@ -774,7 +774,7 @@ class slist
void push_front(const T &x); void push_front(const T &x);
//! <b>Effects</b>: Constructs a new element in the beginning of the list //! <b>Effects</b>: Constructs a new element in the beginning of the list
//! and moves the resources of mx to this new element. //! and moves the resources of x to this new element.
//! //!
//! <b>Throws</b>: If memory allocation throws. //! <b>Throws</b>: If memory allocation throws.
//! //!
@@ -1337,7 +1337,7 @@ class slist
//! <b>Requires</b>: p must be a valid iterator of *this. //! <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>Effects</b>: Insert a new element before p with x's resources.
//! //!
//! <b>Returns</b>: an iterator to the inserted element. //! <b>Returns</b>: an iterator to the inserted element.
//! //!

View File

@@ -652,7 +652,7 @@ class stable_vector
} }
#endif #endif
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this. //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
//! //!
//! <b>Throws</b>: If allocator_type's copy constructor throws. //! <b>Throws</b>: If allocator_type's copy constructor throws.
//! //!
@@ -678,7 +678,7 @@ class stable_vector
} }
//! <b>Effects</b>: Move constructor using the specified allocator. //! <b>Effects</b>: Move constructor using the specified allocator.
//! Moves mx's resources to *this. //! Moves x's resources to *this.
//! //!
//! <b>Throws</b>: If allocator_type's copy constructor throws. //! <b>Throws</b>: If allocator_type's copy constructor throws.
//! //!
@@ -736,7 +736,7 @@ class stable_vector
return *this; return *this;
} }
//! <b>Effects</b>: Move assignment. All mx's values are transferred to *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 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
//! before the function. //! before the function.
@@ -1217,6 +1217,67 @@ class stable_vector
return static_cast<const_node_reference>(*this->index[n]).value; return static_cast<const_node_reference>(*this->index[n]).value;
} }
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
iterator nth(size_type n) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(this->size() >= n);
return (this->index.empty()) ? this->end() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns a const_iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
const_iterator nth(size_type n) const BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(this->size() >= n);
return (this->index.empty()) ? this->cend() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
size_type index_of(iterator p) BOOST_CONTAINER_NOEXCEPT
{ return this->priv_index_of(p.node_pointer()); }
//! <b>Requires</b>: begin() <= p <= end().
//!
//! <b>Effects</b>: Returns the index of the element pointed by p
//! and size() if p == end().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
size_type index_of(const_iterator p) const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_index_of(p.node_pointer()); }
//! <b>Requires</b>: size() > n. //! <b>Requires</b>: size() > n.
//! //!
//! <b>Effects</b>: Returns a reference to the nth element //! <b>Effects</b>: Returns a reference to the nth element
@@ -1339,7 +1400,7 @@ class stable_vector
void push_back(const T &x); void push_back(const T &x);
//! <b>Effects</b>: Constructs a new element in the end of the stable_vector //! <b>Effects</b>: Constructs a new element in the end of the stable_vector
//! and moves the resources of mx to this new element. //! and moves the resources of x to this new element.
//! //!
//! <b>Throws</b>: If memory allocation throws. //! <b>Throws</b>: If memory allocation throws.
//! //!
@@ -1364,7 +1425,7 @@ class stable_vector
//! <b>Requires</b>: p must be a valid iterator of *this. //! <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>Effects</b>: Insert a new element before p with x's resources.
//! //!
//! <b>Returns</b>: an iterator to the inserted element. //! <b>Returns</b>: an iterator to the inserted element.
//! //!
@@ -1603,6 +1664,14 @@ class stable_vector
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
size_type priv_index_of(node_ptr p) const
{
//Check range
BOOST_ASSERT(this->index.empty() || (this->index.data() <= p->up));
BOOST_ASSERT(this->index.empty() || p->up <= (this->index.data() + this->index.size()));
return this->index.empty() ? 0 : p->up - this->index.data();
}
class insert_rollback class insert_rollback
{ {
public: public:

View File

@@ -16,7 +16,7 @@
#endif #endif
#include <boost/container/detail/config_begin.hpp> #include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/vector.hpp> #include <boost/container/vector.hpp>
#include <boost/aligned_storage.hpp> #include <boost/aligned_storage.hpp>
@@ -265,7 +265,7 @@ public:
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
static_vector(BOOST_RV_REF(static_vector) other) static_vector(BOOST_RV_REF(static_vector) other)
: base_t(boost::move(static_cast<base_t&>(other))) : base_t(BOOST_MOVE_BASE(base_t, other))
{} {}
//! @pre <tt>other.size() <= capacity()</tt> //! @pre <tt>other.size() <= capacity()</tt>
@@ -282,7 +282,7 @@ public:
//! Linear O(N). //! Linear O(N).
template <std::size_t C> template <std::size_t C>
static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other) static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
: base_t(boost::move(static_cast<typename static_vector<value_type, C>::base_t&>(other))) : base_t(BOOST_MOVE_BASE(typename static_vector<value_type BOOST_CONTAINER_I C>::base_t, other))
{} {}
//! @brief Copy assigns Values stored in the other static_vector to this one. //! @brief Copy assigns Values stored in the other static_vector to this one.
@@ -310,9 +310,7 @@ public:
//! @par Complexity //! @par Complexity
//! Linear O(N). //! Linear O(N).
static_vector & operator=(std::initializer_list<value_type> il) static_vector & operator=(std::initializer_list<value_type> il)
{ { return static_cast<static_vector&>(base_t::operator=(il)); }
return static_cast<static_vector&>(base_t::operator=(il));
}
#endif #endif
//! @pre <tt>other.size() <= capacity()</tt> //! @pre <tt>other.size() <= capacity()</tt>
@@ -345,7 +343,7 @@ public:
//! Linear O(N). //! Linear O(N).
static_vector & operator=(BOOST_RV_REF(static_vector) other) static_vector & operator=(BOOST_RV_REF(static_vector) other)
{ {
return static_cast<static_vector&>(base_t::operator=(boost::move(static_cast<base_t&>(other)))); return static_cast<static_vector&>(base_t::operator=(BOOST_MOVE_BASE(base_t, other)));
} }
//! @pre <tt>other.size() <= capacity()</tt> //! @pre <tt>other.size() <= capacity()</tt>
@@ -364,7 +362,7 @@ public:
static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other) static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
{ {
return static_cast<static_vector&>(base_t::operator= return static_cast<static_vector&>(base_t::operator=
(boost::move(static_cast<typename static_vector<value_type, C>::base_t&>(other)))); (BOOST_MOVE_BASE(typename static_vector<value_type BOOST_CONTAINER_I C>::base_t, other)));
} }
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -769,6 +767,66 @@ public:
//! Constant O(1). //! Constant O(1).
const_reference operator[](size_type i) const; const_reference operator[](size_type i) const;
//! @pre <tt>i =< size()</tt>
//!
//! @brief Returns a iterator to the i-th element.
//!
//! @param i The element's index.
//!
//! @return a iterator to the i-th element.
//!
//! @par Throws
//! Nothing by default.
//!
//! @par Complexity
//! Constant O(1).
iterator nth(size_type i);
//! @pre <tt>i =< size()</tt>
//!
//! @brief Returns a const_iterator to the i-th element.
//!
//! @param i The element's index.
//!
//! @return a const_iterator to the i-th element.
//!
//! @par Throws
//! Nothing by default.
//!
//! @par Complexity
//! Constant O(1).
const_iterator nth(size_type i) const;
//! @pre <tt>begin() <= p <= end()</tt>
//!
//! @brief Returns the index of the element pointed by p.
//!
//! @param i The element's index.
//!
//! @return The index of the element pointed by p.
//!
//! @par Throws
//! Nothing by default.
//!
//! @par Complexity
//! Constant O(1).
size_type index_of(iterator p);
//! @pre <tt>begin() <= p <= end()</tt>
//!
//! @brief Returns the index of the element pointed by p.
//!
//! @param i The index of the element pointed by p.
//!
//! @return a const_iterator to the i-th element.
//!
//! @par Throws
//! Nothing by default.
//!
//! @par Complexity
//! Constant O(1).
size_type index_of(const_iterator p) const;
//! @pre \c !empty() //! @pre \c !empty()
//! //!
//! @brief Returns reference to the first element. //! @brief Returns reference to the first element.

View File

@@ -2552,29 +2552,29 @@ template <class CharT, class Traits, class Allocator> inline
template <class CharT, class Traits, class Allocator> inline template <class CharT, class Traits, class Allocator> inline
basic_string<CharT, Traits, Allocator> operator+ basic_string<CharT, Traits, Allocator> operator+
( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END mx ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
, BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END my) , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
{ {
mx += my; x += y;
return boost::move(mx); return boost::move(x);
} }
template <class CharT, class Traits, class Allocator> inline template <class CharT, class Traits, class Allocator> inline
basic_string<CharT, Traits, Allocator> operator+ basic_string<CharT, Traits, Allocator> operator+
( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END mx ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
, const basic_string<CharT,Traits,Allocator>& y) , const basic_string<CharT,Traits,Allocator>& y)
{ {
mx += y; x += y;
return boost::move(mx); return boost::move(x);
} }
template <class CharT, class Traits, class Allocator> inline template <class CharT, class Traits, class Allocator> inline
basic_string<CharT, Traits, Allocator> operator+ basic_string<CharT, Traits, Allocator> operator+
(const basic_string<CharT,Traits,Allocator>& x (const basic_string<CharT,Traits,Allocator>& x
,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END my) ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
{ {
my.insert(my.begin(), x.begin(), x.end()); y.insert(y.begin(), x.begin(), x.end());
return boost::move(my); return boost::move(y);
} }
template <class CharT, class Traits, class Allocator> inline template <class CharT, class Traits, class Allocator> inline

View File

@@ -310,7 +310,7 @@ struct vector_alloc_holder
} }
vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_CONTAINER_NOEXCEPT vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_CONTAINER_NOEXCEPT
: Allocator(boost::move(static_cast<Allocator&>(holder))) : Allocator(BOOST_MOVE_BASE(Allocator, holder))
, m_start(holder.m_start) , m_start(holder.m_start)
, m_size(holder.m_size) , m_size(holder.m_size)
, m_capacity(holder.m_capacity) , m_capacity(holder.m_capacity)
@@ -439,7 +439,7 @@ struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsign
} }
vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
: Allocator(boost::move(static_cast<Allocator&>(holder))) : Allocator(BOOST_MOVE_BASE(Allocator, holder))
, m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
{ {
::boost::container::uninitialized_move_alloc_n ::boost::container::uninitialized_move_alloc_n
@@ -1300,7 +1300,10 @@ class vector
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
reference back() BOOST_CONTAINER_NOEXCEPT reference back() BOOST_CONTAINER_NOEXCEPT
{ return this->m_holder.start()[this->m_holder.m_size - 1]; } {
BOOST_ASSERT(this->m_holder.m_size > 0);
return this->m_holder.start()[this->m_holder.m_size - 1];
}
//! <b>Requires</b>: !empty() //! <b>Requires</b>: !empty()
//! //!
@@ -1311,7 +1314,10 @@ class vector
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reference back() const BOOST_CONTAINER_NOEXCEPT const_reference back() const BOOST_CONTAINER_NOEXCEPT
{ return this->m_holder.start()[this->m_holder.m_size - 1]; } {
BOOST_ASSERT(this->m_holder.m_size > 0);
return this->m_holder.start()[this->m_holder.m_size - 1];
}
//! <b>Requires</b>: size() > n. //! <b>Requires</b>: size() > n.
//! //!
@@ -1322,7 +1328,10 @@ class vector
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
{ return this->m_holder.start()[n]; } {
BOOST_ASSERT(this->m_holder.m_size > n);
return this->m_holder.start()[n];
}
//! <b>Requires</b>: size() > n. //! <b>Requires</b>: size() > n.
//! //!
@@ -1333,7 +1342,70 @@ class vector
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return this->m_holder.start()[n]; } {
return this->m_holder.start()[n];
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
iterator nth(size_type n) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(this->m_holder.m_size >= n);
return iterator(this->m_holder.start()+n);
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns a const_iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
const_iterator nth(size_type n) const BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(this->m_holder.m_size >= n);
return const_iterator(this->m_holder.start()+n);
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
size_type index_of(iterator p) BOOST_CONTAINER_NOEXCEPT
{ return this->priv_index_of(vector_iterator_get_ptr(p)); }
//! <b>Requires</b>: begin() <= p <= end().
//!
//! <b>Effects</b>: Returns the index of the element pointed by p
//! and size() if p == end().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
size_type index_of(const_iterator p) const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_index_of(vector_iterator_get_ptr(p)); }
//! <b>Requires</b>: size() > n. //! <b>Requires</b>: size() > n.
//! //!
@@ -1901,6 +1973,13 @@ class vector
private: private:
size_type priv_index_of(pointer p) const
{
BOOST_ASSERT(this->m_holder.start() <= p);
BOOST_ASSERT(p <= (this->m_holder.start()+size()));
return static_cast<size_type>(p - this->m_holder.start());
}
template<class OtherAllocator> template<class OtherAllocator>
void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
, typename container_detail::enable_if_c , typename container_detail::enable_if_c

View File

@@ -197,6 +197,9 @@
<File <File
RelativePath="..\..\..\..\boost\container\detail\config_end.hpp"> RelativePath="..\..\..\..\boost\container\detail\config_end.hpp">
</File> </File>
<File
RelativePath="..\..\test\container_common_tests.hpp">
</File>
<File <File
RelativePath="..\..\..\..\boost\container\detail\destroyers.hpp"> RelativePath="..\..\..\..\boost\container\detail\destroyers.hpp">
</File> </File>

View File

@@ -101,6 +101,7 @@ bool CheckEqualPairContainers(const MyBoostCont &boostcont, const MyStdCont &std
} }
return true; return true;
} }
} //namespace test{ } //namespace test{
} //namespace container { } //namespace container {
} //namespace boost{ } //namespace boost{

View File

@@ -0,0 +1,86 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014. 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_TEST_CONTAINER_COMMON_TESTS_HPP
#define BOOST_CONTAINER_TEST_CONTAINER_COMMON_TESTS_HPP
#include <boost/container/detail/config_begin.hpp>
namespace boost{
namespace container {
namespace test{
template<class Container>
const Container &as_const(Container &c)
{ return c; }
//nth, index_of
template<class Container>
bool test_nth_index_of(Container &c)
{
typename Container::iterator it;
typename Container::const_iterator cit;
typename Container::size_type sz, csz;
//index 0
it = c.nth(0);
sz = c.index_of(it);
cit = as_const(c).nth(0);
csz = as_const(c).index_of(cit);
if(it != c.begin())
return false;
if(cit != c.cbegin())
return false;
if(sz != 0)
return false;
if(csz != 0)
return false;
//index size()/2
const typename Container::size_type sz_div_2 = c.size()/2;
it = c.nth(sz_div_2);
sz = c.index_of(it);
cit = as_const(c).nth(sz_div_2);
csz = as_const(c).index_of(cit);
if(it != (c.begin()+sz_div_2))
return false;
if(cit != (c.cbegin()+sz_div_2))
return false;
if(sz != sz_div_2)
return false;
if(csz != sz_div_2)
return false;
//index size()
it = c.nth(c.size());
sz = c.index_of(it);
cit = as_const(c).nth(c.size());
csz = as_const(c).index_of(cit);
if(it != c.end())
return false;
if(cit != c.cend())
return false;
if(sz != c.size())
return false;
if(csz != c.size())
return false;
return true;
}
} //namespace test{
} //namespace container {
} //namespace boost{
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_TEST_CONTAINER_COMMON_TESTS_HPP

View File

@@ -55,8 +55,7 @@ template<class VectorWithExpandBwdAllocator>
bool test_insert_with_expand_bwd() bool test_insert_with_expand_bwd()
{ {
typedef typename VectorWithExpandBwdAllocator::value_type value_type; typedef typename VectorWithExpandBwdAllocator::value_type value_type;
typedef typename boost::remove_volatile<value_type>::type non_volatile_value_type; typedef std::vector<value_type> Vect;
typedef std::vector<non_volatile_value_type> Vect;
const unsigned int MemorySize = 1000; const unsigned int MemorySize = 1000;
//Distance old and new buffer //Distance old and new buffer
@@ -84,7 +83,7 @@ bool test_insert_with_expand_bwd()
boost::movelib::unique_ptr<char[]> memptr = boost::movelib::unique_ptr<char[]> memptr =
boost::movelib::make_unique_definit<char[]>(MemorySize*sizeof(value_type)); boost::movelib::make_unique_definit<char[]>(MemorySize*sizeof(value_type));
value_type *memory = (value_type*)memptr.get(); value_type *memory = (value_type*)memptr.get();
std::vector<non_volatile_value_type> initial_data; std::vector<value_type> initial_data;
initial_data.resize(InitialSize[iteration]); initial_data.resize(InitialSize[iteration]);
for(unsigned int i = 0; i < InitialSize[iteration]; ++i){ for(unsigned int i = 0; i < InitialSize[iteration]; ++i){
initial_data[i] = i; initial_data[i] = i;
@@ -133,7 +132,6 @@ template<class VectorWithExpandBwdAllocator>
bool test_assign_with_expand_bwd() bool test_assign_with_expand_bwd()
{ {
typedef typename VectorWithExpandBwdAllocator::value_type value_type; typedef typename VectorWithExpandBwdAllocator::value_type value_type;
typedef typename boost::remove_volatile<value_type>::type non_volatile_value_type;
const unsigned int MemorySize = 200; const unsigned int MemorySize = 200;
const unsigned int Offset[] = { 50, 50, 50}; const unsigned int Offset[] = { 50, 50, 50};
@@ -147,14 +145,14 @@ bool test_assign_with_expand_bwd()
boost::movelib::make_unique_definit<char[]>(MemorySize*sizeof(value_type)); boost::movelib::make_unique_definit<char[]>(MemorySize*sizeof(value_type));
value_type *memory = (value_type*)memptr.get(); value_type *memory = (value_type*)memptr.get();
//Create initial data //Create initial data
std::vector<non_volatile_value_type> initial_data; std::vector<value_type> initial_data;
initial_data.resize(InitialSize[iteration]); initial_data.resize(InitialSize[iteration]);
for(unsigned int i = 0; i < InitialSize[iteration]; ++i){ for(unsigned int i = 0; i < InitialSize[iteration]; ++i){
initial_data[i] = i; initial_data[i] = i;
} }
//Create data to assign //Create data to assign
std::vector<non_volatile_value_type> data_to_insert; std::vector<value_type> data_to_insert;
data_to_insert.resize(InsertSize[iteration]); data_to_insert.resize(InsertSize[iteration]);
for(unsigned int i = 0; i < InsertSize[iteration]; ++i){ for(unsigned int i = 0; i < InsertSize[iteration]; ++i){
data_to_insert[i] = -i; data_to_insert[i] = -i;

View File

@@ -19,6 +19,7 @@
#include "movable_int.hpp" #include "movable_int.hpp"
#include "map_test.hpp" #include "map_test.hpp"
#include "propagate_allocator_test.hpp" #include "propagate_allocator_test.hpp"
#include "container_common_tests.hpp"
#include "emplace_test.hpp" #include "emplace_test.hpp"
#include <vector> #include <vector>
#include <boost/container/detail/flat_tree.hpp> #include <boost/container/detail/flat_tree.hpp>
@@ -445,6 +446,22 @@ int main()
test_move<flat_map<recursive_flat_map, recursive_flat_map> >(); test_move<flat_map<recursive_flat_map, recursive_flat_map> >();
test_move<flat_multimap<recursive_flat_multimap, recursive_flat_multimap> >(); test_move<flat_multimap<recursive_flat_multimap, recursive_flat_multimap> >();
} }
//Now test nth/index_of
{
flat_map<int, int> map;
flat_multimap<int, int> mmap;
map.insert(std::pair<int, int>(0, 0));
map.insert(std::pair<int, int>(1, 0));
map.insert(std::pair<int, int>(2, 0));
mmap.insert(std::pair<int, int>(0, 0));
mmap.insert(std::pair<int, int>(1, 0));
mmap.insert(std::pair<int, int>(2, 0));
if(!boost::container::test::test_nth_index_of(map))
return 1;
if(!boost::container::test::test_nth_index_of(mmap))
return 1;
}
//////////////////////////////////// ////////////////////////////////////
// Ordered insertion test // Ordered insertion test

View File

@@ -21,6 +21,7 @@
#include "set_test.hpp" #include "set_test.hpp"
#include "propagate_allocator_test.hpp" #include "propagate_allocator_test.hpp"
#include "emplace_test.hpp" #include "emplace_test.hpp"
#include "container_common_tests.hpp"
#include <vector> #include <vector>
#include <boost/container/detail/flat_tree.hpp> #include <boost/container/detail/flat_tree.hpp>
@@ -531,6 +532,22 @@ int main()
test_move<flat_set<recursive_flat_set> >(); test_move<flat_set<recursive_flat_set> >();
test_move<flat_multiset<recursive_flat_multiset> >(); test_move<flat_multiset<recursive_flat_multiset> >();
} }
//Now test nth/index_of
{
flat_set<int> set;
flat_multiset<int> mset;
set.insert(0);
set.insert(1);
set.insert(2);
mset.insert(0);
mset.insert(1);
mset.insert(2);
if(!boost::container::test::test_nth_index_of(set))
return 1;
if(!boost::container::test::test_nth_index_of(mset))
return 1;
}
//////////////////////////////////// ////////////////////////////////////
// Ordered insertion test // Ordered insertion test

View File

@@ -34,6 +34,7 @@
#include <boost/core/no_exceptions_support.hpp> #include <boost/core/no_exceptions_support.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include "insert_test.hpp" #include "insert_test.hpp"
#include "container_common_tests.hpp"
namespace boost{ namespace boost{
namespace container { namespace container {
@@ -294,6 +295,10 @@ int vector_test()
stdvector.assign(l.begin(), l.end()); stdvector.assign(l.begin(), l.end());
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
} }
boostvector.resize(100);
if(!test_nth_index_of(boostvector))
return 1;
/* deque has no reserve or capacity /* deque has no reserve or capacity
std::size_t cap = boostvector.capacity(); std::size_t cap = boostvector.capacity();
boostvector.reserve(cap*2); boostvector.reserve(cap*2);