Implemented "insert_or_assign" for map-like containers.

This commit is contained in:
Ion Gaztañaga
2016-08-18 20:29:04 +02:00
parent fb1be6fa75
commit 2d6f781a2f
11 changed files with 589 additions and 208 deletions

View File

@@ -1230,6 +1230,7 @@ use [*Boost.Container]? There are several reasons for that:
* [@https://svn.boost.org/trac/boost/ticket/12319 Trac #12319: ['"flat_set` should be nothrow move constructible"]]. * [@https://svn.boost.org/trac/boost/ticket/12319 Trac #12319: ['"flat_set` should be nothrow move constructible"]].
* Revised noexcept expressions of default and move constructors in all containers. * Revised noexcept expressions of default and move constructors in all containers.
* Implemented `insert_or_assign` for [classref boost::container::map map] and [classref boost::container::flat_map flat_map].
[endsect] [endsect]

View File

@@ -23,16 +23,19 @@
#include <boost/container/allocator_traits.hpp> #include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/iterators.hpp> #include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/value_init.hpp>
namespace boost { namespace boost {
namespace container { namespace container {
//In place construction
template<class Allocator, class T, class InpIt> template<class Allocator, class T, class InpIt>
inline void construct_in_place(Allocator &a, T* dest, InpIt source) BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T* dest, InpIt source)
{ boost::container::allocator_traits<Allocator>::construct(a, dest, *source); } { boost::container::allocator_traits<Allocator>::construct(a, dest, *source); }
template<class Allocator, class T, class U, class D> template<class Allocator, class T, class U, class D>
inline void construct_in_place(Allocator &a, T *dest, value_init_construct_iterator<U, D>) BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, value_init_construct_iterator<U, D>)
{ {
boost::container::allocator_traits<Allocator>::construct(a, dest); boost::container::allocator_traits<Allocator>::construct(a, dest);
} }
@@ -41,7 +44,7 @@ template <class T, class Difference>
class default_init_construct_iterator; class default_init_construct_iterator;
template<class Allocator, class T, class U, class D> template<class Allocator, class T, class U, class D>
inline void construct_in_place(Allocator &a, T *dest, default_init_construct_iterator<U, D>) BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, default_init_construct_iterator<U, D>)
{ {
boost::container::allocator_traits<Allocator>::construct(a, dest, default_init); boost::container::allocator_traits<Allocator>::construct(a, dest, default_init);
} }
@@ -50,13 +53,44 @@ template <class T, class EmplaceFunctor, class Difference>
class emplace_iterator; class emplace_iterator;
template<class Allocator, class T, class U, class EF, class D> template<class Allocator, class T, class U, class EF, class D>
inline void construct_in_place(Allocator &a, T *dest, emplace_iterator<U, EF, D> ei) BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, emplace_iterator<U, EF, D> ei)
{ {
ei.construct_in_place(a, dest); ei.construct_in_place(a, dest);
} }
//Assignment
template<class DstIt, class InpIt>
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, InpIt source)
{ *dest = *source; }
template<class DstIt, class U, class D>
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, value_init_construct_iterator<U, D>)
{
container_detail::value_init<U> val;
*dest = boost::move(val.get());
}
template <class DstIt, class Difference>
class default_init_construct_iterator;
template<class DstIt, class U, class D>
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, default_init_construct_iterator<U, D>)
{
U u;
*dest = boost::move(u);
}
template <class T, class EmplaceFunctor, class Difference>
class emplace_iterator;
template<class DstIt, class U, class EF, class D>
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, emplace_iterator<U, EF, D> ei)
{
ei.assign_in_place(dest);
}
} //namespace container { } //namespace container {
} //namespace boost { } //namespace boost {
#endif //#ifndef BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP #endif //#ifndef BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP

View File

@@ -25,6 +25,8 @@
#include <boost/container/detail/iterator_to_raw_pointer.hpp> #include <boost/container/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/mpl.hpp> #include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/construct_in_place.hpp>
// move // move
#include <boost/move/adl_move_swap.hpp> #include <boost/move/adl_move_swap.hpp>
#include <boost/move/iterator.hpp> #include <boost/move/iterator.hpp>
@@ -515,7 +517,7 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F
F back = r; F back = r;
BOOST_TRY{ BOOST_TRY{
while (n--) { while (n--) {
allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); boost::container::construct_in_place(a, container_detail::iterator_to_raw_pointer(r), f);
++f; ++r; ++f; ++r;
} }
} }
@@ -757,7 +759,7 @@ inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I
copy_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) copy_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
{ {
while (n--) { while (n--) {
*r = *f; boost::container::assign_in_place(r, f);
++f; ++r; ++f; ++r;
} }
return f; return f;

View File

@@ -38,6 +38,7 @@
#include <boost/intrusive/pointer_traits.hpp> #include <boost/intrusive/pointer_traits.hpp>
#endif #endif
#include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/move/make_unique.hpp> #include <boost/move/make_unique.hpp>
#include <boost/move/adl_move_swap.hpp> #include <boost/move/adl_move_swap.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -201,36 +202,36 @@ class flat_tree
typedef allocator_traits<stored_allocator_type> stored_allocator_traits; typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
public: public:
flat_tree() BOOST_CONTAINER_FORCEINLINE flat_tree()
: m_data() : m_data()
{ } { }
explicit flat_tree(const Compare& comp) BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const Compare& comp)
: m_data(comp) : m_data(comp)
{ } { }
flat_tree(const Compare& comp, const allocator_type& a) BOOST_CONTAINER_FORCEINLINE flat_tree(const Compare& comp, const allocator_type& a)
: m_data(comp, a) : m_data(comp, a)
{ } { }
explicit flat_tree(const allocator_type& a) BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const allocator_type& a)
: m_data(a) : m_data(a)
{ } { }
flat_tree(const flat_tree& x) BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x)
: m_data(x.m_data) : m_data(x.m_data)
{ } { }
flat_tree(BOOST_RV_REF(flat_tree) x) BOOST_CONTAINER_FORCEINLINE flat_tree(BOOST_RV_REF(flat_tree) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: m_data(boost::move(x.m_data)) : m_data(boost::move(x.m_data))
{ } { }
flat_tree(const flat_tree& x, const allocator_type &a) BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x, const allocator_type &a)
: m_data(x.m_data, a) : m_data(x.m_data, a)
{ } { }
flat_tree(BOOST_RV_REF(flat_tree) x, const allocator_type &a) BOOST_CONTAINER_FORCEINLINE flat_tree(BOOST_RV_REF(flat_tree) x, const allocator_type &a)
: m_data(boost::move(x.m_data), a) : m_data(boost::move(x.m_data), a)
{ } { }
@@ -277,13 +278,13 @@ class flat_tree
} }
} }
~flat_tree() BOOST_CONTAINER_FORCEINLINE ~flat_tree()
{} {}
flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x) BOOST_CONTAINER_FORCEINLINE 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) x) BOOST_CONTAINER_FORCEINLINE flat_tree& operator=(BOOST_RV_REF(flat_tree) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) && allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
@@ -295,69 +296,75 @@ class flat_tree
BOOST_CONTAINER_FORCEINLINE value_compare &priv_value_comp() BOOST_CONTAINER_FORCEINLINE value_compare &priv_value_comp()
{ return static_cast<value_compare &>(this->m_data); } { return static_cast<value_compare &>(this->m_data); }
BOOST_CONTAINER_FORCEINLINE const key_compare &priv_key_comp() const
{ return this->priv_value_comp().get_comp(); }
BOOST_CONTAINER_FORCEINLINE key_compare &priv_key_comp()
{ return this->priv_value_comp().get_comp(); }
public: public:
// accessors: // accessors:
Compare key_comp() const BOOST_CONTAINER_FORCEINLINE Compare key_comp() const
{ return this->m_data.get_comp(); } { return this->m_data.get_comp(); }
value_compare value_comp() const BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
{ return this->m_data; } { return this->m_data; }
allocator_type get_allocator() const BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
{ return this->m_data.m_vect.get_allocator(); } { return this->m_data.m_vect.get_allocator(); }
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const
{ return this->m_data.m_vect.get_stored_allocator(); } { return this->m_data.m_vect.get_stored_allocator(); }
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator()
{ return this->m_data.m_vect.get_stored_allocator(); } { return this->m_data.m_vect.get_stored_allocator(); }
iterator begin() BOOST_CONTAINER_FORCEINLINE iterator begin()
{ return this->m_data.m_vect.begin(); } { return this->m_data.m_vect.begin(); }
const_iterator begin() const BOOST_CONTAINER_FORCEINLINE const_iterator begin() const
{ return this->cbegin(); } { return this->cbegin(); }
const_iterator cbegin() const BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const
{ return this->m_data.m_vect.begin(); } { return this->m_data.m_vect.begin(); }
iterator end() BOOST_CONTAINER_FORCEINLINE iterator end()
{ return this->m_data.m_vect.end(); } { return this->m_data.m_vect.end(); }
const_iterator end() const BOOST_CONTAINER_FORCEINLINE const_iterator end() const
{ return this->cend(); } { return this->cend(); }
const_iterator cend() const BOOST_CONTAINER_FORCEINLINE const_iterator cend() const
{ return this->m_data.m_vect.end(); } { return this->m_data.m_vect.end(); }
reverse_iterator rbegin() BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin()
{ return reverse_iterator(this->end()); } { return reverse_iterator(this->end()); }
const_reverse_iterator rbegin() const BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const
{ return this->crbegin(); } { return this->crbegin(); }
const_reverse_iterator crbegin() const BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const
{ return const_reverse_iterator(this->cend()); } { return const_reverse_iterator(this->cend()); }
reverse_iterator rend() BOOST_CONTAINER_FORCEINLINE reverse_iterator rend()
{ return reverse_iterator(this->begin()); } { return reverse_iterator(this->begin()); }
const_reverse_iterator rend() const BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const
{ return this->crend(); } { return this->crend(); }
const_reverse_iterator crend() const BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const
{ return const_reverse_iterator(this->cbegin()); } { return const_reverse_iterator(this->cbegin()); }
bool empty() const BOOST_CONTAINER_FORCEINLINE bool empty() const
{ return this->m_data.m_vect.empty(); } { return this->m_data.m_vect.empty(); }
size_type size() const BOOST_CONTAINER_FORCEINLINE size_type size() const
{ return this->m_data.m_vect.size(); } { return this->m_data.m_vect.size(); }
size_type max_size() const BOOST_CONTAINER_FORCEINLINE size_type max_size() const
{ return this->m_data.m_vect.max_size(); } { return this->m_data.m_vect.max_size(); }
void swap(flat_tree& other) BOOST_CONTAINER_FORCEINLINE void swap(flat_tree& other)
BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
&& boost::container::container_detail::is_nothrow_swappable<Compare>::value ) && boost::container::container_detail::is_nothrow_swappable<Compare>::value )
{ this->m_data.swap(other.m_data); } { this->m_data.swap(other.m_data); }
@@ -368,7 +375,7 @@ class flat_tree
{ {
std::pair<iterator,bool> ret; std::pair<iterator,bool> ret;
insert_commit_data data; insert_commit_data data;
ret.second = this->priv_insert_unique_prepare(val, data); ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
ret.first = ret.second ? this->priv_insert_commit(data, val) ret.first = ret.second ? this->priv_insert_commit(data, val)
: iterator(vector_iterator_get_ptr(data.position)); : iterator(vector_iterator_get_ptr(data.position));
return ret; return ret;
@@ -378,7 +385,7 @@ class flat_tree
{ {
std::pair<iterator,bool> ret; std::pair<iterator,bool> ret;
insert_commit_data data; insert_commit_data data;
ret.second = this->priv_insert_unique_prepare(val, data); ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val)) ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
: iterator(vector_iterator_get_ptr(data.position)); : iterator(vector_iterator_get_ptr(data.position));
return ret; return ret;
@@ -403,7 +410,7 @@ class flat_tree
BOOST_ASSERT(this->priv_in_range_or_end(hint)); BOOST_ASSERT(this->priv_in_range_or_end(hint));
std::pair<iterator,bool> ret; std::pair<iterator,bool> ret;
insert_commit_data data; insert_commit_data data;
return this->priv_insert_unique_prepare(hint, val, data) return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
? this->priv_insert_commit(data, val) ? this->priv_insert_commit(data, val)
: iterator(vector_iterator_get_ptr(data.position)); : iterator(vector_iterator_get_ptr(data.position));
} }
@@ -413,7 +420,7 @@ class flat_tree
BOOST_ASSERT(this->priv_in_range_or_end(hint)); BOOST_ASSERT(this->priv_in_range_or_end(hint));
std::pair<iterator,bool> ret; std::pair<iterator,bool> ret;
insert_commit_data data; insert_commit_data data;
return this->priv_insert_unique_prepare(hint, val, data) return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
? this->priv_insert_commit(data, boost::move(val)) ? this->priv_insert_commit(data, boost::move(val))
: iterator(vector_iterator_get_ptr(data.position)); : iterator(vector_iterator_get_ptr(data.position));
} }
@@ -634,7 +641,29 @@ class flat_tree
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
iterator erase(const_iterator position) template<class KeyType, class M>
std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
{
const key_type& k = key;
std::pair<iterator,bool> ret;
insert_commit_data data;
ret.second = hint == const_iterator()
? this->priv_insert_unique_prepare(k, data)
: this->priv_insert_unique_prepare(hint, k, data);
if(!ret.second){
ret.first = this->nth(data.position - this->cbegin());
ret.first->second = boost::forward<M>(obj);
}
else{
typedef typename emplace_functor_type<KeyType, M>::type func_t;
typedef emplace_iterator<value_type, func_t, difference_type> it_t;
func_t func(boost::forward<KeyType>(key), boost::forward<M>(obj));
ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());
}
return ret;
}
BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator position)
{ return this->m_data.m_vect.erase(position); } { return this->m_data.m_vect.erase(position); }
size_type erase(const key_type& k) size_type erase(const key_type& k)
@@ -647,10 +676,10 @@ class flat_tree
return ret; return ret;
} }
iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
{ return this->m_data.m_vect.erase(first, last); } { return this->m_data.m_vect.erase(first, last); }
void clear() BOOST_CONTAINER_FORCEINLINE void clear()
{ this->m_data.m_vect.clear(); } { this->m_data.m_vect.clear(); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created //! <b>Effects</b>: Tries to deallocate the excess of memory created
@@ -659,19 +688,19 @@ class flat_tree
//! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws. //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
//! //!
//! <b>Complexity</b>: Linear to size(). //! <b>Complexity</b>: Linear to size().
void shrink_to_fit() BOOST_CONTAINER_FORCEINLINE 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_NOEXCEPT_OR_NOTHROW BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_data.m_vect.nth(n); } { return this->m_data.m_vect.nth(n); }
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_data.m_vect.nth(n); } { return this->m_data.m_vect.nth(n); }
size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_data.m_vect.index_of(p); } { return this->m_data.m_vect.index_of(p); }
size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_data.m_vect.index_of(p); } { return this->m_data.m_vect.index_of(p); }
// set operations: // set operations:
@@ -704,64 +733,64 @@ class flat_tree
return n; return n;
} }
iterator lower_bound(const key_type& k) BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k)
{ return this->priv_lower_bound(this->begin(), this->end(), k); } { return this->priv_lower_bound(this->begin(), this->end(), k); }
const_iterator lower_bound(const key_type& k) const BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const
{ return this->priv_lower_bound(this->cbegin(), this->cend(), k); } { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
iterator upper_bound(const key_type& k) BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k)
{ return this->priv_upper_bound(this->begin(), this->end(), k); } { return this->priv_upper_bound(this->begin(), this->end(), k); }
const_iterator upper_bound(const key_type& k) const BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const
{ return this->priv_upper_bound(this->cbegin(), this->cend(), k); } { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
std::pair<iterator,iterator> equal_range(const key_type& k) BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& k)
{ return this->priv_equal_range(this->begin(), this->end(), k); } { return this->priv_equal_range(this->begin(), this->end(), k); }
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
{ return this->priv_equal_range(this->cbegin(), this->cend(), k); } { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
std::pair<iterator, iterator> lower_bound_range(const key_type& k) BOOST_CONTAINER_FORCEINLINE std::pair<iterator, iterator> lower_bound_range(const key_type& k)
{ return this->priv_lower_bound_range(this->begin(), this->end(), k); } { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
{ return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); } { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
size_type capacity() const BOOST_CONTAINER_FORCEINLINE size_type capacity() const
{ return this->m_data.m_vect.capacity(); } { return this->m_data.m_vect.capacity(); }
void reserve(size_type cnt) BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
{ this->m_data.m_vect.reserve(cnt); } { this->m_data.m_vect.reserve(cnt); }
friend bool operator==(const flat_tree& x, const flat_tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_tree& x, const flat_tree& y)
{ {
return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());
} }
friend bool operator<(const flat_tree& x, const flat_tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_tree& x, const flat_tree& y)
{ {
return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
} }
friend bool operator!=(const flat_tree& x, const flat_tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_tree& x, const flat_tree& y)
{ return !(x == y); } { return !(x == y); }
friend bool operator>(const flat_tree& x, const flat_tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_tree& x, const flat_tree& y)
{ return y < x; } { return y < x; }
friend bool operator<=(const flat_tree& x, const flat_tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_tree& x, const flat_tree& y)
{ return !(y < x); } { return !(y < x); }
friend bool operator>=(const flat_tree& x, const flat_tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_tree& x, const flat_tree& y)
{ return !(x < y); } { return !(x < y); }
friend void swap(flat_tree& x, flat_tree& y) BOOST_CONTAINER_FORCEINLINE friend void swap(flat_tree& x, flat_tree& y)
{ x.swap(y); } { x.swap(y); }
private: private:
bool priv_in_range_or_end(const_iterator pos) const BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const
{ {
return (this->begin() <= pos) && (pos <= this->end()); return (this->begin() <= pos) && (pos <= this->end());
} }
@@ -802,34 +831,34 @@ class flat_tree
} }
bool priv_insert_unique_prepare bool priv_insert_unique_prepare
(const_iterator b, const_iterator e, const value_type& val, insert_commit_data &commit_data) (const_iterator b, const_iterator e, const key_type& k, insert_commit_data &commit_data)
{ {
const value_compare &val_cmp = this->m_data; const key_compare &key_cmp = this->priv_key_comp();
commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val)); commit_data.position = this->priv_lower_bound(b, e, k);
return commit_data.position == e || val_cmp(val, *commit_data.position); return commit_data.position == e || key_cmp(k, KeyOfValue()(*commit_data.position));
} }
bool priv_insert_unique_prepare BOOST_CONTAINER_FORCEINLINE bool priv_insert_unique_prepare
(const value_type& val, insert_commit_data &commit_data) (const key_type& k, insert_commit_data &commit_data)
{ return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), val, commit_data); } { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), k, commit_data); }
bool priv_insert_unique_prepare bool priv_insert_unique_prepare
(const_iterator pos, const value_type& val, insert_commit_data &commit_data) (const_iterator pos, const key_type& k, insert_commit_data &commit_data)
{ {
//N1780. Props to Howard Hinnant! //N1780. Props to Howard Hinnant!
//To insert val at pos: //To insert k at pos:
//if pos == end || val <= *pos //if pos == end || k <= *pos
// if pos == begin || val >= *(pos-1) // if pos == begin || k >= *(pos-1)
// insert val before pos // insert k before pos
// else // else
// insert val before upper_bound(val) // insert k before upper_bound(k)
//else if pos+1 == end || val <= *(pos+1) //else if pos+1 == end || k <= *(pos+1)
// insert val after pos // insert k after pos
//else //else
// insert val before lower_bound(val) // insert k before lower_bound(k)
const value_compare &val_cmp = this->m_data; const key_compare &key_cmp = this->priv_key_comp();
const const_iterator cend_it = this->cend(); const const_iterator cend_it = this->cend();
if(pos == cend_it || val_cmp(val, *pos)){ //Check if val should go before end if(pos == cend_it || key_cmp(k, KeyOfValue()(*pos))){ //Check if k should go before end
const const_iterator cbeg = this->cbegin(); const const_iterator cbeg = this->cbegin();
commit_data.position = pos; commit_data.position = pos;
if(pos == cbeg){ //If container is empty then insert it in the beginning if(pos == cbeg){ //If container is empty then insert it in the beginning
@@ -837,27 +866,27 @@ class flat_tree
} }
const_iterator prev(pos); const_iterator prev(pos);
--prev; --prev;
if(val_cmp(*prev, val)){ //If previous element was less, then it should go between prev and pos if(key_cmp(KeyOfValue()(*prev), k)){ //If previous element was less, then it should go between prev and pos
return true; return true;
} }
else if(!val_cmp(val, *prev)){ //If previous was equal then insertion should fail else if(!key_cmp(k, KeyOfValue()(*prev))){ //If previous was equal then insertion should fail
commit_data.position = prev; commit_data.position = prev;
return false; return false;
} }
else{ //Previous was bigger so insertion hint was pointless, dispatch to hintless insertion else{ //Previous was bigger so insertion hint was pointless, dispatch to hintless insertion
//but reduce the search between beg and prev as prev is bigger than val //but reduce the search between beg and prev as prev is bigger than k
return this->priv_insert_unique_prepare(cbeg, prev, val, commit_data); return this->priv_insert_unique_prepare(cbeg, prev, k, commit_data);
} }
} }
else{ else{
//The hint is before the insertion position, so insert it //The hint is before the insertion position, so insert it
//in the remaining range [pos, end) //in the remaining range [pos, end)
return this->priv_insert_unique_prepare(pos, cend_it, val, commit_data); return this->priv_insert_unique_prepare(pos, cend_it, k, commit_data);
} }
} }
template<class Convertible> template<class Convertible>
iterator priv_insert_commit BOOST_CONTAINER_FORCEINLINE iterator priv_insert_commit
(insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible) (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
{ {
return this->m_data.m_vect.insert return this->m_data.m_vect.insert

View File

@@ -560,17 +560,23 @@ class emplace_iterator
BOOST_CONTAINER_FORCEINLINE this_type operator-(difference_type off) const BOOST_CONTAINER_FORCEINLINE this_type operator-(difference_type off) const
{ return *this + (-off); } { return *this + (-off); }
private:
//This pseudo-iterator's dereference operations have no sense since value is not //This pseudo-iterator's dereference operations have no sense since value is not
//constructed until ::boost::container::construct_in_place is called. //constructed until ::boost::container::construct_in_place is called.
//So comment them to catch bad uses //So comment them to catch bad uses
//const T& operator*() const; const T& operator*() const;
//const T& operator[](difference_type) const; const T& operator[](difference_type) const;
//const T* operator->() const; const T* operator->() const;
public:
template<class Allocator> template<class Allocator>
void construct_in_place(Allocator &a, T* ptr) void construct_in_place(Allocator &a, T* ptr)
{ (*m_pe)(a, ptr); } { (*m_pe)(a, ptr); }
template<class DestIt>
void assign_in_place(DestIt dest)
{ (*m_pe)(dest); }
private: private:
difference_type m_num; difference_type m_num;
EmplaceFunctor * m_pe; EmplaceFunctor * m_pe;
@@ -612,9 +618,14 @@ struct emplace_functor
{} {}
template<class Allocator, class T> template<class Allocator, class T>
void operator()(Allocator &a, T *ptr) BOOST_CONTAINER_FORCEINLINE void operator()(Allocator &a, T *ptr)
{ emplace_functor::inplace_impl(a, ptr, index_tuple_t()); } { emplace_functor::inplace_impl(a, ptr, index_tuple_t()); }
template<class DestIt>
BOOST_CONTAINER_FORCEINLINE void operator()(DestIt dest)
{ emplace_functor::inplace_impl(dest, index_tuple_t()); }
private:
template<class Allocator, class T, int ...IdxPack> template<class Allocator, class T, int ...IdxPack>
BOOST_CONTAINER_FORCEINLINE void inplace_impl(Allocator &a, T* ptr, const container_detail::index_tuple<IdxPack...>&) BOOST_CONTAINER_FORCEINLINE void inplace_impl(Allocator &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
{ {
@@ -622,11 +633,29 @@ struct emplace_functor
(a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...); (a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
} }
template<class DestIt, int ...IdxPack>
BOOST_CONTAINER_FORCEINLINE void inplace_impl(DestIt dest, const container_detail::index_tuple<IdxPack...>&)
{
typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;
value_type && tmp= value_type(::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
*dest = ::boost::move(tmp);
}
container_detail::tuple<Args&...> args_; container_detail::tuple<Args&...> args_;
}; };
template<class ...Args>
struct emplace_functor_type
{
typedef emplace_functor<Args...> type;
};
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
//Partial specializations cannot match argument list for primary template, so add an extra argument
template <BOOST_MOVE_CLASSDFLT9, class Dummy = void>
struct emplace_functor_type;
#define BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE(N) \ #define BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
struct emplace_functor##N\ struct emplace_functor##N\
@@ -638,10 +667,26 @@ struct emplace_functor##N\
void operator()(Allocator &a, T *ptr)\ void operator()(Allocator &a, T *ptr)\
{ allocator_traits<Allocator>::construct(a, ptr BOOST_MOVE_I##N BOOST_MOVE_MFWD##N); }\ { allocator_traits<Allocator>::construct(a, ptr BOOST_MOVE_I##N BOOST_MOVE_MFWD##N); }\
\ \
template<class DestIt>\
void operator()(DestIt dest)\
{\
typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;\
value_type tmp(BOOST_MOVE_MFWD##N);\
*dest = ::boost::move(const_cast<value_type &>(tmp));\
}\
\
BOOST_MOVE_MREF##N\ BOOST_MOVE_MREF##N\
};\ };\
\
template <BOOST_MOVE_CLASS##N>\
struct emplace_functor_type<BOOST_MOVE_TARG##N>\
{\
typedef emplace_functor##N BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N type;\
};\
// //
BOOST_MOVE_ITERATE_0TO9(BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE) BOOST_MOVE_ITERATE_0TO9(BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE)
#undef BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE #undef BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE
#endif #endif

View File

@@ -199,11 +199,11 @@ class insert_equal_end_hint_functor
Icont &icont_; Icont &icont_;
public: public:
insert_equal_end_hint_functor(Icont &icont) BOOST_CONTAINER_FORCEINLINE insert_equal_end_hint_functor(Icont &icont)
: icont_(icont) : icont_(icont)
{} {}
void operator()(Node &n) BOOST_CONTAINER_FORCEINLINE void operator()(Node &n)
{ this->icont_.insert_equal(this->icont_.cend(), n); } { this->icont_.insert_equal(this->icont_.cend(), n); }
}; };
@@ -213,11 +213,11 @@ class push_back_functor
Icont &icont_; Icont &icont_;
public: public:
push_back_functor(Icont &icont) BOOST_CONTAINER_FORCEINLINE push_back_functor(Icont &icont)
: icont_(icont) : icont_(icont)
{} {}
void operator()(Node &n) BOOST_CONTAINER_FORCEINLINE void operator()(Node &n)
{ this->icont_.push_back(n); } { this->icont_.push_back(n); }
}; };
@@ -328,14 +328,14 @@ template< boost::container::tree_type_enum tree_type_value
struct intrusive_tree_proxy struct intrusive_tree_proxy
{ {
template<class Icont> template<class Icont>
static void rebalance(Icont &) {} BOOST_CONTAINER_FORCEINLINE static void rebalance(Icont &) {}
}; };
template<boost::container::tree_type_enum tree_type_value> template<boost::container::tree_type_enum tree_type_value>
struct intrusive_tree_proxy<tree_type_value, true> struct intrusive_tree_proxy<tree_type_value, true>
{ {
template<class Icont> template<class Icont>
static void rebalance(Icont &c) BOOST_CONTAINER_FORCEINLINE static void rebalance(Icont &c)
{ c.rebalance(); } { c.rebalance(); }
}; };
@@ -359,10 +359,10 @@ class RecyclingCloner
: m_holder(holder), m_icont(itree) : m_holder(holder), m_icont(itree)
{} {}
static void do_assign(node_ptr_type &p, const node_type &other, bool_<true>) BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_type &other, bool_<true>)
{ p->do_move_assign(const_cast<node_type &>(other).m_data); } { p->do_move_assign(const_cast<node_type &>(other).m_data); }
static void do_assign(node_ptr_type &p, const node_type &other, bool_<false>) BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_type &other, bool_<false>)
{ p->do_assign(other.m_data); } { p->do_assign(other.m_data); }
node_ptr_type operator()(const node_type &other) const node_ptr_type operator()(const node_type &other) const
@@ -398,7 +398,7 @@ template<class KeyValueCompare, class Node>
struct key_node_compare struct key_node_compare
: private KeyValueCompare : private KeyValueCompare
{ {
explicit key_node_compare(const KeyValueCompare &comp) BOOST_CONTAINER_FORCEINLINE explicit key_node_compare(const KeyValueCompare &comp)
: KeyValueCompare(comp) : KeyValueCompare(comp)
{} {}
@@ -409,20 +409,20 @@ struct key_node_compare
}; };
template<class T> template<class T>
typename enable_if_c<is_node<T>::value, const typename KeyValueCompare::value_type &>::type BOOST_CONTAINER_FORCEINLINE typename enable_if_c<is_node<T>::value, const typename KeyValueCompare::value_type &>::type
key_forward(const T &node) const key_forward(const T &node) const
{ return node.get_data(); } { return node.get_data(); }
template<class T> template<class T>
#if defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN) #if defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
const T &key_forward(const T &key, typename enable_if_c<!is_node<T>::value>::type* =0) const BOOST_CONTAINER_FORCEINLINE const T &key_forward(const T &key, typename enable_if_c<!is_node<T>::value>::type* =0) const
#else #else
typename enable_if_c<!is_node<T>::value, const T &>::type key_forward(const T &key) const BOOST_CONTAINER_FORCEINLINE typename enable_if_c<!is_node<T>::value, const T &>::type key_forward(const T &key) const
#endif #endif
{ return key; } { return key; }
template<class KeyType, class KeyType2> template<class KeyType, class KeyType2>
bool operator()(const KeyType &key1, const KeyType2 &key2) const BOOST_CONTAINER_FORCEINLINE bool operator()(const KeyType &key1, const KeyType2 &key2) const
{ return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); } { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
}; };
@@ -496,15 +496,15 @@ class tree
typedef boost::container::reverse_iterator<iterator> reverse_iterator; typedef boost::container::reverse_iterator<iterator> reverse_iterator;
typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator; typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
tree() BOOST_CONTAINER_FORCEINLINE tree()
: AllocHolder() : AllocHolder()
{} {}
explicit tree(const key_compare& comp, const allocator_type& a = allocator_type()) BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp, const allocator_type& a = allocator_type())
: AllocHolder(ValComp(comp), a) : AllocHolder(ValComp(comp), a)
{} {}
explicit tree(const allocator_type& a) BOOST_CONTAINER_FORCEINLINE explicit tree(const allocator_type& a)
: AllocHolder(a) : AllocHolder(a)
{} {}
@@ -604,19 +604,19 @@ class tree
, container_detail::push_back_functor<Node, Icont>(this->icont())); , container_detail::push_back_functor<Node, Icont>(this->icont()));
} }
tree(const tree& x) BOOST_CONTAINER_FORCEINLINE tree(const tree& x)
: AllocHolder(x.value_comp(), x) : AllocHolder(x.value_comp(), x)
{ {
this->icont().clone_from this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
} }
tree(BOOST_RV_REF(tree) x) BOOST_CONTAINER_FORCEINLINE tree(BOOST_RV_REF(tree) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: AllocHolder(BOOST_MOVE_BASE(AllocHolder, x), x.value_comp()) : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x), x.value_comp())
{} {}
tree(const tree& x, const allocator_type &a) BOOST_CONTAINER_FORCEINLINE tree(const tree& x, const allocator_type &a)
: AllocHolder(x.value_comp(), a) : AllocHolder(x.value_comp(), a)
{ {
this->icont().clone_from this->icont().clone_from
@@ -635,7 +635,7 @@ class tree
} }
} }
~tree() BOOST_CONTAINER_FORCEINLINE ~tree()
{} //AllocHolder clears the tree {} //AllocHolder clears the tree
tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x) tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
@@ -714,43 +714,43 @@ class tree
public: public:
// accessors: // accessors:
value_compare value_comp() const BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
{ return this->icont().value_comp().predicate(); } { return this->icont().value_comp().predicate(); }
key_compare key_comp() const BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const
{ return this->icont().value_comp().predicate().key_comp(); } { return this->icont().value_comp().predicate().key_comp(); }
allocator_type get_allocator() const BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
{ return allocator_type(this->node_alloc()); } { return allocator_type(this->node_alloc()); }
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const
{ return this->node_alloc(); } { return this->node_alloc(); }
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator()
{ return this->node_alloc(); } { return this->node_alloc(); }
iterator begin() BOOST_CONTAINER_FORCEINLINE iterator begin()
{ return iterator(this->icont().begin()); } { return iterator(this->icont().begin()); }
const_iterator begin() const BOOST_CONTAINER_FORCEINLINE const_iterator begin() const
{ return this->cbegin(); } { return this->cbegin(); }
iterator end() BOOST_CONTAINER_FORCEINLINE iterator end()
{ return iterator(this->icont().end()); } { return iterator(this->icont().end()); }
const_iterator end() const BOOST_CONTAINER_FORCEINLINE const_iterator end() const
{ return this->cend(); } { return this->cend(); }
reverse_iterator rbegin() BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin()
{ return reverse_iterator(end()); } { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const
{ return this->crbegin(); } { return this->crbegin(); }
reverse_iterator rend() BOOST_CONTAINER_FORCEINLINE reverse_iterator rend()
{ return reverse_iterator(begin()); } { return reverse_iterator(begin()); }
const_reverse_iterator rend() const BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const
{ return this->crend(); } { return this->crend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -758,7 +758,7 @@ class tree
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_iterator cbegin() const BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const
{ return const_iterator(this->non_const_icont().begin()); } { return const_iterator(this->non_const_icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container. //! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -766,7 +766,7 @@ class tree
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_iterator cend() const BOOST_CONTAINER_FORCEINLINE const_iterator cend() const
{ return const_iterator(this->non_const_icont().end()); } { return const_iterator(this->non_const_icont().end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -775,7 +775,7 @@ class tree
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const
{ return const_reverse_iterator(cend()); } { return const_reverse_iterator(cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -784,19 +784,19 @@ class tree
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const
{ return const_reverse_iterator(cbegin()); } { return const_reverse_iterator(cbegin()); }
bool empty() const BOOST_CONTAINER_FORCEINLINE bool empty() const
{ return !this->size(); } { return !this->size(); }
size_type size() const BOOST_CONTAINER_FORCEINLINE size_type size() const
{ return this->icont().size(); } { return this->icont().size(); }
size_type max_size() const BOOST_CONTAINER_FORCEINLINE size_type max_size() const
{ return AllocHolder::max_size(); } { return AllocHolder::max_size(); }
void swap(ThisType& x) BOOST_CONTAINER_FORCEINLINE void swap(ThisType& x)
BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
&& boost::container::container_detail::is_nothrow_swappable<Compare>::value ) && boost::container::container_detail::is_nothrow_swappable<Compare>::value )
{ AllocHolder::swap(x); } { AllocHolder::swap(x); }
@@ -868,6 +868,28 @@ class tree
private: private:
template<class KeyConvertible>
iterator priv_insert_unique_key_commit
(BOOST_FWD_REF(KeyConvertible) key, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node_from_key(boost::forward<KeyConvertible>(key));
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
iterator ret(this->icont().insert_unique_commit(*tmp, data));
destroy_deallocator.release();
return ret;
}
template<class KeyConvertible, class M>
iiterator priv_insert_or_assign_commit
(BOOST_FWD_REF(KeyConvertible) key, BOOST_FWD_REF(M) obj, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(boost::forward<KeyConvertible>(key), boost::forward<M>(obj));
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
iiterator ret(this->icont().insert_unique_commit(*tmp, data));
destroy_deallocator.release();
return ret;
}
bool priv_is_linked(const_iterator const position) const bool priv_is_linked(const_iterator const position) const
{ {
iiterator const cur(position.get()); iiterator const cur(position.get());
@@ -921,11 +943,11 @@ class tree
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args> template <class... Args>
std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args) BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
{ return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); } { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); }
template <class... Args> template <class... Args>
iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args) BOOST_CONTAINER_FORCEINLINE iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
{ return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); } { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); }
template <class... Args> template <class... Args>
@@ -1054,19 +1076,25 @@ class tree
std::pair<iiterator, bool> ret = std::pair<iiterator, bool> ret =
this->icont().insert_unique_check(k, KeyNodeCompare(value_comp()), data); this->icont().insert_unique_check(k, KeyNodeCompare(value_comp()), data);
return ret.second return ret.second
? this->insert_unique_key_commit(boost::forward<KeyConvertible>(key), data) ? this->priv_insert_unique_key_commit(boost::forward<KeyConvertible>(key), data)
: iterator(ret.first); : iterator(ret.first);
} }
template<class KeyConvertible> template<class KeyType, class M>
iterator insert_unique_key_commit std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
(BOOST_FWD_REF(KeyConvertible) key, insert_commit_data &data)
{ {
NodePtr tmp = AllocHolder::create_node_from_key(boost::forward<KeyConvertible>(key)); insert_commit_data data;
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); const key_type & k = key; //Support emulated rvalue references
iterator ret(this->icont().insert_unique_commit(*tmp, data)); std::pair<iiterator, bool> ret =
destroy_deallocator.release(); hint == const_iterator() ? this->icont().insert_unique_check(k, KeyNodeCompare(value_comp()), data)
return ret; : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(value_comp()), data);
if(ret.second){
ret.first = this->priv_insert_or_assign_commit(boost::forward<KeyType>(key), boost::forward<M>(obj), data);
}
else{
ret.first->get_data().second = boost::forward<M>(obj);
}
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
} }
iterator erase(const_iterator position) iterator erase(const_iterator position)
@@ -1075,7 +1103,7 @@ class tree
return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc()))); return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc())));
} }
size_type erase(const key_type& k) BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& k)
{ return AllocHolder::erase_key(k, KeyNodeCompare(value_comp()), alloc_version()); } { return AllocHolder::erase_key(k, KeyNodeCompare(value_comp()), alloc_version()); }
iterator erase(const_iterator first, const_iterator last) iterator erase(const_iterator first, const_iterator last)
@@ -1085,30 +1113,30 @@ class tree
return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version()));
} }
void clear() BOOST_CONTAINER_FORCEINLINE void clear()
{ AllocHolder::clear(alloc_version()); } { AllocHolder::clear(alloc_version()); }
// search operations. Const and non-const overloads even if no iterator is returned // search operations. Const and non-const overloads even if no iterator is returned
// so splay implementations can to their rebalancing when searching in non-const versions // so splay implementations can to their rebalancing when searching in non-const versions
iterator find(const key_type& k) BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& k)
{ return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); } { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); }
const_iterator find(const key_type& k) const BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& k) const
{ return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); } { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); }
size_type count(const key_type& k) const BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& k) const
{ return size_type(this->icont().count(k, KeyNodeCompare(value_comp()))); } { return size_type(this->icont().count(k, KeyNodeCompare(value_comp()))); }
iterator lower_bound(const key_type& k) BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k)
{ return iterator(this->icont().lower_bound(k, KeyNodeCompare(value_comp()))); } { return iterator(this->icont().lower_bound(k, KeyNodeCompare(value_comp()))); }
const_iterator lower_bound(const key_type& k) const BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const
{ return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(value_comp()))); } { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(value_comp()))); }
iterator upper_bound(const key_type& k) BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k)
{ return iterator(this->icont().upper_bound(k, KeyNodeCompare(value_comp()))); } { return iterator(this->icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
const_iterator upper_bound(const key_type& k) const BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const
{ return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); } { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
std::pair<iterator,iterator> equal_range(const key_type& k) std::pair<iterator,iterator> equal_range(const key_type& k)
@@ -1141,28 +1169,28 @@ class tree
(const_iterator(ret.first), const_iterator(ret.second)); (const_iterator(ret.first), const_iterator(ret.second));
} }
void rebalance() BOOST_CONTAINER_FORCEINLINE void rebalance()
{ intrusive_tree_proxy_t::rebalance(this->icont()); } { intrusive_tree_proxy_t::rebalance(this->icont()); }
friend bool operator==(const tree& x, const tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator==(const tree& x, const tree& y)
{ return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
friend bool operator<(const tree& x, const tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator<(const tree& x, const tree& y)
{ return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
friend bool operator!=(const tree& x, const tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const tree& x, const tree& y)
{ return !(x == y); } { return !(x == y); }
friend bool operator>(const tree& x, const tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator>(const tree& x, const tree& y)
{ return y < x; } { return y < x; }
friend bool operator<=(const tree& x, const tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const tree& x, const tree& y)
{ return !(y < x); } { return !(y < x); }
friend bool operator>=(const tree& x, const tree& y) BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const tree& x, const tree& y)
{ return !(x < y); } { return !(x < y); }
friend void swap(tree& x, tree& y) BOOST_CONTAINER_FORCEINLINE friend void swap(tree& x, tree& y)
{ x.swap(y); } { x.swap(y); }
}; };

View File

@@ -37,6 +37,8 @@ struct value_init
operator T &() { return m_t; } operator T &() { return m_t; }
T &get() { return m_t; }
T m_t; T m_t;
}; };

View File

@@ -56,11 +56,11 @@ namespace container {
namespace container_detail{ namespace container_detail{
template<class D, class S> template<class D, class S>
static D &force(const S &s) BOOST_CONTAINER_FORCEINLINE static D &force(const S &s)
{ return *const_cast<D*>((reinterpret_cast<const D*>(&s))); } { return *const_cast<D*>((reinterpret_cast<const D*>(&s))); }
template<class D, class S> template<class D, class S>
static D force_copy(S s) BOOST_CONTAINER_FORCEINLINE static D force_copy(S s)
{ {
D *vp = reinterpret_cast<D *>(&s); D *vp = reinterpret_cast<D *>(&s);
return D(*vp); return D(*vp);
@@ -604,6 +604,98 @@ 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
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
//! as if by insert, constructing it from value_type(k, forward<M>(obj)).
//!
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
//! references obtained to that element before it was extracted become valid.
//!
//! Returns: The bool component is true if the insertion took place and false if the assignment
//! took place. The iterator component is pointing at the element that was inserted or updated.
//!
//! Complexity: Logarithmic in the size of the container.
template <class M>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
{
return container_detail::force_copy< std::pair<iterator, bool> >
(this->m_flat_tree.insert_or_assign
( container_detail::force_copy<impl_const_iterator>(const_iterator())
, k, ::boost::forward<M>(obj))
);
}
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
//! as if by insert, constructing it from value_type(k, move(obj)).
//!
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
//! references obtained to that element before it was extracted become valid.
//!
//! Returns: The bool component is true if the insertion took place and false if the assignment
//! took place. The iterator component is pointing at the element that was inserted or updated.
//!
//! Complexity: Logarithmic in the size of the container.
template <class M>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
{
return container_detail::force_copy< std::pair<iterator, bool> >
(this->m_flat_tree.insert_or_assign
( container_detail::force_copy<impl_const_iterator>(const_iterator())
, ::boost::move(k), ::boost::forward<M>(obj))
);
}
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
//! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
//! to the container as close as possible to the position just before hint.
//!
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
//! references obtained to that element before it was extracted become valid.
//!
//! Returns: The bool component is true if the insertion took place and false if the assignment
//! took place. The iterator component is pointing at the element that was inserted or updated.
//!
//! Complexity: Logarithmic in the size of the container in general, but amortized constant if
//! the new element is inserted just before hint.
template <class M>
BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
{
return container_detail::force_copy< std::pair<iterator, bool> >
(this->m_flat_tree.insert_or_assign
( container_detail::force_copy<impl_const_iterator>(hint)
, k, ::boost::forward<M>(obj))
);
}
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
//! as if by insert, constructing it from value_type(k, move(obj)) and the new element
//! to the container as close as possible to the position just before hint.
//!
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
//! references obtained to that element before it was extracted become valid.
//!
//! Returns: The bool component is true if the insertion took place and false if the assignment
//! took place. The iterator component is pointing at the element that was inserted or updated.
//!
//! Complexity: Logarithmic in the size of the container in general, but amortized constant if
//! the new element is inserted just before hint.
template <class M>
BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
{
return container_detail::force_copy< std::pair<iterator, bool> >
(this->m_flat_tree.insert_or_assign
( container_detail::force_copy<impl_const_iterator>(hint)
, ::boost::move(k), ::boost::forward<M>(obj))
);
}
//! @copydoc ::boost::container::flat_set::nth(size_type) //! @copydoc ::boost::container::flat_set::nth(size_type)
iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); } { return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }

View File

@@ -132,6 +132,7 @@ class map
//! <b>Effects</b>: Default constructs an empty map. //! <b>Effects</b>: Default constructs an empty map.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value) container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t() : base_t()
@@ -144,6 +145,7 @@ class map
//! and allocator. //! and allocator.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
explicit map(const Compare& comp, const allocator_type& a = allocator_type()) explicit map(const Compare& comp, const allocator_type& a = allocator_type())
: base_t(comp, a) : base_t(comp, a)
{ {
@@ -154,6 +156,7 @@ class map
//! <b>Effects</b>: Constructs an empty map using the specified allocator. //! <b>Effects</b>: Constructs an empty map using the specified allocator.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
explicit map(const allocator_type& a) explicit map(const allocator_type& a)
: base_t(a) : base_t(a)
{ {
@@ -167,6 +170,7 @@ class map
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first. //! comp and otherwise N logN, where N is last - first.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
map(InputIterator first, InputIterator last, const Compare& comp = Compare(), map(InputIterator first, InputIterator last, const Compare& comp = Compare(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_t(true, first, last, comp, a) : base_t(true, first, last, comp, a)
@@ -181,6 +185,7 @@ class map
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first. //! comp and otherwise N logN, where N is last - first.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
map(InputIterator first, InputIterator last, const allocator_type& a) map(InputIterator first, InputIterator last, const allocator_type& a)
: base_t(true, first, last, Compare(), a) : base_t(true, first, last, Compare(), a)
{ {
@@ -199,6 +204,7 @@ class map
//! //!
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
map( ordered_unique_range_t, InputIterator first, InputIterator last map( ordered_unique_range_t, InputIterator first, InputIterator last
, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) , const Compare& comp = Compare(), const allocator_type& a = allocator_type())
: base_t(ordered_range, first, last, comp, a) : base_t(ordered_range, first, last, comp, a)
@@ -213,6 +219,7 @@ class map
//! //!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is il.first() - il.end(). //! comp and otherwise N logN, where N is il.first() - il.end().
BOOST_CONTAINER_FORCEINLINE
map(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) map(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
: base_t(true, il.begin(), il.end(), comp, a) : base_t(true, il.begin(), il.end(), comp, a)
{ {
@@ -225,6 +232,7 @@ class map
//! //!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is il.first() - il.end(). //! comp and otherwise N logN, where N is il.first() - il.end().
BOOST_CONTAINER_FORCEINLINE
map(std::initializer_list<value_type> il, const allocator_type& a) map(std::initializer_list<value_type> il, const allocator_type& a)
: base_t(true, il.begin(), il.end(), Compare(), a) : base_t(true, il.begin(), il.end(), Compare(), a)
{ {
@@ -242,6 +250,7 @@ class map
//! <b>Complexity</b>: Linear in N. //! <b>Complexity</b>: Linear in N.
//! //!
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE
map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_t(ordered_range, il.begin(), il.end(), comp, a) : base_t(ordered_range, il.begin(), il.end(), comp, a)
@@ -254,6 +263,7 @@ class map
//! <b>Effects</b>: Copy constructs a map. //! <b>Effects</b>: Copy constructs a map.
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE
map(const map& x) map(const map& x)
: base_t(static_cast<const base_t&>(x)) : base_t(static_cast<const base_t&>(x))
{ {
@@ -266,6 +276,7 @@ class map
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
BOOST_CONTAINER_FORCEINLINE
map(BOOST_RV_REF(map) x) map(BOOST_RV_REF(map) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(BOOST_MOVE_BASE(base_t, x)) : base_t(BOOST_MOVE_BASE(base_t, x))
@@ -277,6 +288,7 @@ class map
//! <b>Effects</b>: Copy constructs a map using the specified allocator. //! <b>Effects</b>: Copy constructs a map using the specified allocator.
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE
map(const map& x, const allocator_type &a) map(const map& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a) : base_t(static_cast<const base_t&>(x), a)
{ {
@@ -290,6 +302,7 @@ class map
//! <b>Complexity</b>: Constant if x == x.get_allocator(), linear otherwise. //! <b>Complexity</b>: Constant if x == x.get_allocator(), linear otherwise.
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
BOOST_CONTAINER_FORCEINLINE
map(BOOST_RV_REF(map) x, const allocator_type &a) map(BOOST_RV_REF(map) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a) : base_t(BOOST_MOVE_BASE(base_t, x), a)
{ {
@@ -300,6 +313,7 @@ class map
//! <b>Effects</b>: Makes *this a copy of x. //! <b>Effects</b>: Makes *this a copy of x.
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE
map& operator=(BOOST_COPY_ASSIGN_REF(map) x) map& operator=(BOOST_COPY_ASSIGN_REF(map) x)
{ return static_cast<map&>(this->base_t::operator=(static_cast<const base_t&>(x))); } { return static_cast<map&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
@@ -311,6 +325,7 @@ class map
//! <b>Complexity</b>: Constant if allocator_traits_type:: //! <b>Complexity</b>: Constant if allocator_traits_type::
//! propagate_on_container_move_assignment is true or //! propagate_on_container_move_assignment is true or
//! this->get>allocator() == x.get_allocator(). Linear otherwise. //! this->get>allocator() == x.get_allocator(). Linear otherwise.
BOOST_CONTAINER_FORCEINLINE
map& operator=(BOOST_RV_REF(map) x) map& operator=(BOOST_RV_REF(map) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) && allocator_traits_type::is_always_equal::value) &&
@@ -320,6 +335,7 @@ class map
#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.
//! //!
BOOST_CONTAINER_FORCEINLINE
map& operator=(std::initializer_list<value_type> il) map& operator=(std::initializer_list<value_type> il)
{ {
this->clear(); this->clear();
@@ -485,12 +501,80 @@ class map
mapped_type& operator[](key_type &&k); mapped_type& operator[](key_type &&k);
#elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN) #elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
//in compilers like GCC 3.4, we can't catch temporaries //in compilers like GCC 3.4, we can't catch temporaries
mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); } BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); } BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
#else #else
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
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
//! as if by insert, constructing it from value_type(k, forward<M>(obj)).
//!
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
//! references obtained to that element before it was extracted become valid.
//!
//! Returns: The bool component is true if the insertion took place and false if the assignment
//! took place. The iterator component is pointing at the element that was inserted or updated.
//!
//! Complexity: Logarithmic in the size of the container.
template <class M>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
{ return this->base_t::insert_or_assign(const_iterator(), k, ::boost::forward<M>(obj)); }
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
//! as if by insert, constructing it from value_type(k, move(obj)).
//!
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
//! references obtained to that element before it was extracted become valid.
//!
//! Returns: The bool component is true if the insertion took place and false if the assignment
//! took place. The iterator component is pointing at the element that was inserted or updated.
//!
//! Complexity: Logarithmic in the size of the container.
template <class M>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
{ return this->base_t::insert_or_assign(const_iterator(), ::boost::move(k), ::boost::forward<M>(obj)); }
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
//! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
//! to the container as close as possible to the position just before hint.
//!
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
//! references obtained to that element before it was extracted become valid.
//!
//! Returns: The bool component is true if the insertion took place and false if the assignment
//! took place. The iterator component is pointing at the element that was inserted or updated.
//!
//! Complexity: Logarithmic in the size of the container in general, but amortized constant if
//! the new element is inserted just before hint.
template <class M>
BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
{ return this->base_t::insert_or_assign(hint, k, ::boost::forward<M>(obj)); }
//! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
//! as if by insert, constructing it from value_type(k, move(obj)) and the new element
//! to the container as close as possible to the position just before hint.
//!
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
//! references obtained to that element before it was extracted become valid.
//!
//! Returns: The bool component is true if the insertion took place and false if the assignment
//! took place. The iterator component is pointing at the element that was inserted or updated.
//!
//! Complexity: Logarithmic in the size of the container in general, but amortized constant if
//! the new element is inserted just before hint.
template <class M>
BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
{ return this->base_t::insert_or_assign(hint, ::boost::move(k), ::boost::forward<M>(obj)); }
//! Returns: A reference to the element whose key is equivalent to x. //! Returns: A 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.
//! Complexity: logarithmic. //! Complexity: logarithmic.
@@ -529,7 +613,7 @@ class map
//! points to the element with key equivalent to the key of x. //! points to the element with key equivalent to the key of x.
//! //!
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(const value_type& x) BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const value_type& x)
{ return this->base_t::insert_unique(x); } { return this->base_t::insert_unique(x); }
//! <b>Effects</b>: Inserts a new value_type created from the pair if and only if //! <b>Effects</b>: Inserts a new value_type created from the pair if and only if
@@ -540,7 +624,7 @@ class map
//! points to the element with key equivalent to the key of x. //! points to the element with key equivalent to the key of x.
//! //!
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(const nonconst_value_type& x) BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const nonconst_value_type& x)
{ return this->base_t::insert_unique(x); } { return this->base_t::insert_unique(x); }
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
@@ -551,7 +635,7 @@ class map
//! points to the element with key equivalent to the key of x. //! points to the element with key equivalent to the key of x.
//! //!
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_value_type) x) BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_value_type) x)
{ return this->base_t::insert_unique(boost::move(x)); } { return this->base_t::insert_unique(boost::move(x)); }
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
@@ -562,7 +646,7 @@ class map
//! points to the element with key equivalent to the key of x. //! points to the element with key equivalent to the key of x.
//! //!
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x) BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
{ return this->base_t::insert_unique(boost::move(x)); } { return this->base_t::insert_unique(boost::move(x)); }
//! <b>Effects</b>: Move constructs a new value from x if and only if there is //! <b>Effects</b>: Move constructs a new value from x if and only if there is
@@ -573,7 +657,7 @@ class map
//! points to the element with key equivalent to the key of x. //! points to the element with key equivalent to the key of x.
//! //!
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x) BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
{ return this->base_t::insert_unique(boost::move(x)); } { return this->base_t::insert_unique(boost::move(x)); }
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
@@ -585,7 +669,7 @@ class map
//! //!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
iterator insert(const_iterator p, const value_type& x) BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
{ return this->base_t::insert_unique(p, x); } { return this->base_t::insert_unique(p, x); }
//! <b>Effects</b>: Move constructs a new value from x if and only if there is //! <b>Effects</b>: Move constructs a new value from x if and only if there is
@@ -637,7 +721,7 @@ class map
//! //!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last) //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator> template <class InputIterator>
void insert(InputIterator first, InputIterator last) BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_unique(first, last); } { this->base_t::insert_unique(first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -645,7 +729,7 @@ class map
//! if there is no element with key equivalent to the key of that element. //! if there is no element with key equivalent to the key of that element.
//! //!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end()) //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
void insert(std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_unique(il.begin(), il.end()); } { this->base_t::insert_unique(il.begin(), il.end()); }
#endif #endif
@@ -663,7 +747,7 @@ class map
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
template <class... Args> template <class... Args>
std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args) BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_unique(boost::forward<Args>(args)...); } { return this->base_t::emplace_unique(boost::forward<Args>(args)...); }
//! <b>Effects</b>: Inserts an object of type T constructed with //! <b>Effects</b>: Inserts an object of type T constructed with
@@ -677,18 +761,18 @@ class map
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
template <class... Args> template <class... Args>
iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); } { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_MAP_EMPLACE_CODE(N) \ #define BOOST_CONTAINER_MAP_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\ { return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\
\ \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ { return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
// //
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MAP_EMPLACE_CODE) BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MAP_EMPLACE_CODE)
@@ -766,7 +850,7 @@ class map
//! <b>Returns</b>: The number of elements with key equivalent to x. //! <b>Returns</b>: The number of elements with key equivalent to x.
//! //!
//! <b>Complexity</b>: log(size())+count(k) //! <b>Complexity</b>: log(size())+count(k)
size_type count(const key_type& x) const BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
{ return static_cast<size_type>(this->find(x) != this->cend()); } { return static_cast<size_type>(this->find(x) != this->cend()); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -850,11 +934,10 @@ class map
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
template<class KeyConvertible> template<class KeyConvertible>
mapped_type& priv_subscript(BOOST_FWD_REF(KeyConvertible) k) BOOST_CONTAINER_FORCEINLINE mapped_type& priv_subscript(BOOST_FWD_REF(KeyConvertible) k)
{ {
return this->insert_from_key(boost::forward<KeyConvertible>(k))->second; return this->insert_from_key(boost::forward<KeyConvertible>(k))->second;
} }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}; };
@@ -959,6 +1042,7 @@ class multimap
//! <b>Effects</b>: Default constructs an empty multimap. //! <b>Effects</b>: Default constructs an empty multimap.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
multimap() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && multimap() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value) container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t() : base_t()
@@ -970,6 +1054,7 @@ class multimap
//! <b>Effects</b>: Constructs an empty multimap using the specified allocator. //! <b>Effects</b>: Constructs an empty multimap using the specified allocator.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
explicit multimap(const Compare& comp, const allocator_type& a = allocator_type()) explicit multimap(const Compare& comp, const allocator_type& a = allocator_type())
: base_t(comp, a) : base_t(comp, a)
{ {
@@ -981,6 +1066,7 @@ class multimap
//! object and allocator. //! object and allocator.
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
explicit multimap(const allocator_type& a) explicit multimap(const allocator_type& a)
: base_t(a) : base_t(a)
{ {
@@ -994,6 +1080,7 @@ class multimap
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first. //! comp and otherwise N logN, where N is last - first.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
multimap(InputIterator first, InputIterator last, multimap(InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Compare& comp = Compare(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
@@ -1009,7 +1096,7 @@ class multimap
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first. //! comp and otherwise N logN, where N is last - first.
template <class InputIterator> template <class InputIterator>
multimap(InputIterator first, InputIterator last, const allocator_type& a) BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last, const allocator_type& a)
: base_t(false, first, last, Compare(), a) : base_t(false, first, last, Compare(), a)
{ {
//A type must be std::pair<CONST Key, T> //A type must be std::pair<CONST Key, T>
@@ -1026,7 +1113,7 @@ class multimap
//! //!
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
template <class InputIterator> template <class InputIterator>
multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(), BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_t(ordered_range, first, last, comp, a) : base_t(ordered_range, first, last, comp, a)
{} {}
@@ -1037,6 +1124,7 @@ class multimap
//! //!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is il.first() - il.end(). //! comp and otherwise N logN, where N is il.first() - il.end().
BOOST_CONTAINER_FORCEINLINE
multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(), multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_t(false, il.begin(), il.end(), comp, a) : base_t(false, il.begin(), il.end(), comp, a)
@@ -1050,6 +1138,7 @@ class multimap
//! //!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is il.first() - il.end(). //! comp and otherwise N logN, where N is il.first() - il.end().
BOOST_CONTAINER_FORCEINLINE
multimap(std::initializer_list<value_type> il, const allocator_type& a) multimap(std::initializer_list<value_type> il, const allocator_type& a)
: base_t(false, il.begin(), il.end(), Compare(), a) : base_t(false, il.begin(), il.end(), Compare(), a)
{ {
@@ -1066,6 +1155,7 @@ class multimap
//! <b>Complexity</b>: Linear in N. //! <b>Complexity</b>: Linear in N.
//! //!
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE
multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_t(ordered_range, il.begin(), il.end(), comp, a) : base_t(ordered_range, il.begin(), il.end(), comp, a)
@@ -1078,7 +1168,7 @@ class multimap
//! <b>Effects</b>: Copy constructs a multimap. //! <b>Effects</b>: Copy constructs a multimap.
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
multimap(const multimap& x) BOOST_CONTAINER_FORCEINLINE multimap(const multimap& x)
: base_t(static_cast<const base_t&>(x)) : base_t(static_cast<const base_t&>(x))
{ {
//A type must be std::pair<CONST Key, T> //A type must be std::pair<CONST Key, T>
@@ -1090,7 +1180,7 @@ class multimap
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
multimap(BOOST_RV_REF(multimap) x) BOOST_CONTAINER_FORCEINLINE multimap(BOOST_RV_REF(multimap) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(BOOST_MOVE_BASE(base_t, x)) : base_t(BOOST_MOVE_BASE(base_t, x))
{ {
@@ -1101,7 +1191,7 @@ class multimap
//! <b>Effects</b>: Copy constructs a multimap. //! <b>Effects</b>: Copy constructs a multimap.
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
multimap(const multimap& x, const allocator_type &a) BOOST_CONTAINER_FORCEINLINE multimap(const multimap& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a) : base_t(static_cast<const base_t&>(x), a)
{ {
//A type must be std::pair<CONST Key, T> //A type must be std::pair<CONST Key, T>
@@ -1113,7 +1203,7 @@ class multimap
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
//! //!
//! <b>Postcondition</b>: x is emptied. //! <b>Postcondition</b>: x is emptied.
multimap(BOOST_RV_REF(multimap) x, const allocator_type &a) BOOST_CONTAINER_FORCEINLINE multimap(BOOST_RV_REF(multimap) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a) : base_t(BOOST_MOVE_BASE(base_t, x), a)
{ {
//A type must be std::pair<CONST Key, T> //A type must be std::pair<CONST Key, T>
@@ -1123,13 +1213,13 @@ class multimap
//! <b>Effects</b>: Makes *this a copy of x. //! <b>Effects</b>: Makes *this a copy of x.
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
multimap& operator=(BOOST_COPY_ASSIGN_REF(multimap) x) BOOST_CONTAINER_FORCEINLINE multimap& operator=(BOOST_COPY_ASSIGN_REF(multimap) x)
{ return static_cast<multimap&>(this->base_t::operator=(static_cast<const base_t&>(x))); } { return static_cast<multimap&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! <b>Effects</b>: this->swap(x.get()). //! <b>Effects</b>: this->swap(x.get()).
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
multimap& operator=(BOOST_RV_REF(multimap) x) BOOST_CONTAINER_FORCEINLINE multimap& operator=(BOOST_RV_REF(multimap) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) && allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
@@ -1138,7 +1228,7 @@ class multimap
#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.
//! //!
multimap& operator=(std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE multimap& operator=(std::initializer_list<value_type> il)
{ {
this->clear(); this->clear();
insert(il.begin(), il.end()); insert(il.begin(), il.end());
@@ -1216,7 +1306,7 @@ class multimap
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
template <class... Args> template <class... Args>
iterator emplace(BOOST_FWD_REF(Args)... args) BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_equal(boost::forward<Args>(args)...); } { return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
//! <b>Effects</b>: Inserts an object of type T constructed with //! <b>Effects</b>: Inserts an object of type T constructed with
@@ -1229,18 +1319,18 @@ class multimap
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
template <class... Args> template <class... Args>
iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); } { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE(N) \ #define BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
iterator emplace(BOOST_MOVE_UREF##N)\ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\ { return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\
\ \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ { return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
// //
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE) BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE)
@@ -1252,21 +1342,21 @@ class multimap
//! newly inserted element. //! newly inserted element.
//! //!
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
iterator insert(const value_type& x) BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x)
{ return this->base_t::insert_equal(x); } { return this->base_t::insert_equal(x); }
//! <b>Effects</b>: Inserts a new value constructed from x and returns //! <b>Effects</b>: Inserts a new value constructed from x and returns
//! the iterator pointing to the newly inserted element. //! the iterator pointing to the newly inserted element.
//! //!
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
iterator insert(const nonconst_value_type& x) BOOST_CONTAINER_FORCEINLINE iterator insert(const nonconst_value_type& x)
{ return this->base_t::insert_equal(x); } { return this->base_t::insert_equal(x); }
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
//! the iterator pointing to the newly inserted element. //! the iterator pointing to the newly inserted element.
//! //!
//! <b>Complexity</b>: Logarithmic. //! <b>Complexity</b>: Logarithmic.
iterator insert(BOOST_RV_REF(nonconst_value_type) x) BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(nonconst_value_type) x)
{ return this->base_t::insert_equal(boost::move(x)); } { return this->base_t::insert_equal(boost::move(x)); }
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
@@ -1284,7 +1374,7 @@ class multimap
//! //!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
iterator insert(const_iterator p, const value_type& x) BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
{ return this->base_t::insert_equal(p, x); } { return this->base_t::insert_equal(p, x); }
//! <b>Effects</b>: Inserts a new value constructed from x in the container. //! <b>Effects</b>: Inserts a new value constructed from x in the container.
@@ -1295,7 +1385,7 @@ class multimap
//! //!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
iterator insert(const_iterator p, const nonconst_value_type& x) BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const nonconst_value_type& x)
{ return this->base_t::insert_equal_convertible(p, x); } { return this->base_t::insert_equal_convertible(p, x); }
//! <b>Effects</b>: Inserts a new value move constructed from x in the container. //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
@@ -1306,7 +1396,7 @@ class multimap
//! //!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x) BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
{ return this->base_t::insert_equal_convertible(p, boost::move(x)); } { return this->base_t::insert_equal_convertible(p, boost::move(x)); }
//! <b>Effects</b>: Inserts a new value move constructed from x in the container. //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
@@ -1317,7 +1407,7 @@ class multimap
//! //!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p. //! is inserted right before p.
iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
{ return this->base_t::insert_equal_convertible(p, boost::move(x)); } { return this->base_t::insert_equal_convertible(p, boost::move(x)); }
//! <b>Requires</b>: first, last are not iterators into *this. //! <b>Requires</b>: first, last are not iterators into *this.
@@ -1326,14 +1416,14 @@ class multimap
//! //!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last) //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator> template <class InputIterator>
void insert(InputIterator first, InputIterator last) BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_equal(first, last); } { this->base_t::insert_equal(first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end(). //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end().
//! //!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end()) //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
void insert(std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_equal(il.begin(), il.end()); } { this->base_t::insert_equal(il.begin(), il.end()); }
#endif #endif

View File

@@ -250,7 +250,6 @@ int main ()
std::pair<const pair_t,pair_t> p; std::pair<const pair_t,pair_t> p;
s.insert(p); s.insert(p);
s.emplace(p); s.emplace(p);
return 0;
} }
//////////////////////////////////// ////////////////////////////////////

View File

@@ -667,6 +667,65 @@ int map_test()
} }
} }
{ //operator[] test
boostmap.clear();
boostmultimap.clear();
stdmap.clear();
stdmultimap.clear();
IntPairType aux_vect[max];
for(int i = 0; i < max; ++i){
IntType i1(i);
IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
}
for(int i = 0; i < max; ++i){
boostmap[boost::move(aux_vect[i].first)] = boost::move(aux_vect[i].second);
stdmap[i] = i;
}
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
}
{ //insert_or_assign test
boostmap.clear();
boostmultimap.clear();
stdmap.clear();
stdmultimap.clear();
IntPairType aux_vect[max];
for(int i = 0; i < max; ++i){
IntType i1(i);
IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
}
IntPairType aux_vect2[max];
for(int i = 0; i < max; ++i){
IntType i1(i);
IntType i2(max-i);
new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
}
for(int i = 0; i < max; ++i){
boostmap.insert_or_assign(boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
stdmap[i] = i;
}
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
for(int i = 0; i < max; ++i){
boostmap.insert_or_assign(boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
stdmap[i] = max-i;
}
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
}
if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap> if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>
(container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){ (container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){
return 1; return 1;