summaryrefslogtreecommitdiff
path: root/boost/container/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container/detail')
-rw-r--r--boost/container/detail/addressof.hpp4
-rw-r--r--boost/container/detail/advanced_insert_int.hpp4
-rw-r--r--boost/container/detail/compare_functors.hpp8
-rw-r--r--boost/container/detail/construct_in_place.hpp44
-rw-r--r--boost/container/detail/copy_move_algo.hpp12
-rw-r--r--boost/container/detail/dispatch_uses_allocator.hpp136
-rw-r--r--boost/container/detail/flat_tree.hpp319
-rw-r--r--boost/container/detail/is_sorted.hpp57
-rw-r--r--boost/container/detail/iterators.hpp56
-rw-r--r--boost/container/detail/mpl.hpp15
-rw-r--r--boost/container/detail/node_alloc_holder.hpp13
-rw-r--r--boost/container/detail/pair.hpp197
-rw-r--r--boost/container/detail/tree.hpp430
-rw-r--r--boost/container/detail/value_init.hpp2
-rw-r--r--boost/container/detail/variadic_templates_tools.hpp23
-rw-r--r--boost/container/detail/workaround.hpp18
16 files changed, 1018 insertions, 320 deletions
diff --git a/boost/container/detail/addressof.hpp b/boost/container/detail/addressof.hpp
index cc582c439d..fedbdb91d1 100644
--- a/boost/container/detail/addressof.hpp
+++ b/boost/container/detail/addressof.hpp
@@ -25,12 +25,12 @@ namespace container {
namespace container_detail {
template <typename T>
-inline T* addressof(T& obj)
+BOOST_CONTAINER_FORCEINLINE T* addressof(T& obj)
{
return static_cast<T*>(
static_cast<void*>(
const_cast<char*>(
- &reinterpret_cast<const char&>(obj)
+ &reinterpret_cast<const volatile char&>(obj)
)));
}
diff --git a/boost/container/detail/advanced_insert_int.hpp b/boost/container/detail/advanced_insert_int.hpp
index 56df588706..278cd1b3f1 100644
--- a/boost/container/detail/advanced_insert_int.hpp
+++ b/boost/container/detail/advanced_insert_int.hpp
@@ -236,7 +236,7 @@ struct insert_nonmovable_emplace_proxy
{ this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
- template<int ...IdxPack>
+ template<std::size_t ...IdxPack>
void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(n == 1); (void)n;
@@ -266,7 +266,7 @@ struct insert_emplace_proxy
private:
- template<int ...IdxPack>
+ template<std::size_t ...IdxPack>
void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(n ==1); (void)n;
diff --git a/boost/container/detail/compare_functors.hpp b/boost/container/detail/compare_functors.hpp
index 4220d50996..28f9093b9a 100644
--- a/boost/container/detail/compare_functors.hpp
+++ b/boost/container/detail/compare_functors.hpp
@@ -53,16 +53,16 @@ struct value_to_node_compare
{}
bool operator()(const Node &a, const Node &b) const
- { return static_cast<const Pred&>(*this)(a.m_data, b.m_data); }
+ { return static_cast<const Pred&>(*this)(a.get_data(), b.get_data()); }
bool operator()(const Node &a) const
- { return static_cast<const Pred&>(*this)(a.m_data); }
+ { return static_cast<const Pred&>(*this)(a.get_data()); }
bool operator()(const Node &a, const Node &b)
- { return static_cast<Pred&>(*this)(a.m_data, b.m_data); }
+ { return static_cast<Pred&>(*this)(a.get_data(), b.get_data()); }
bool operator()(const Node &a)
- { return static_cast<Pred&>(*this)(a.m_data); }
+ { return static_cast<Pred&>(*this)(a.get_data()); }
predicate_type & predicate() { return static_cast<predicate_type&>(*this); }
const predicate_type & predicate() const { return static_cast<predicate_type&>(*this); }
diff --git a/boost/container/detail/construct_in_place.hpp b/boost/container/detail/construct_in_place.hpp
index 6cb339519c..9fecd24a8f 100644
--- a/boost/container/detail/construct_in_place.hpp
+++ b/boost/container/detail/construct_in_place.hpp
@@ -23,16 +23,19 @@
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/value_init.hpp>
namespace boost {
namespace container {
+//In place construction
+
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); }
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);
}
@@ -41,7 +44,7 @@ template <class T, class Difference>
class default_init_construct_iterator;
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);
}
@@ -50,13 +53,44 @@ template <class T, class EmplaceFunctor, class Difference>
class emplace_iterator;
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);
}
+//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 boost {
#endif //#ifndef BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP
-
diff --git a/boost/container/detail/copy_move_algo.hpp b/boost/container/detail/copy_move_algo.hpp
index f590a8aaf3..ead93c6035 100644
--- a/boost/container/detail/copy_move_algo.hpp
+++ b/boost/container/detail/copy_move_algo.hpp
@@ -7,8 +7,8 @@
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
-#define BOOST_CONTAINER_DETAIL_UTILITIES_HPP
+#ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
+#define BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
@@ -25,6 +25,8 @@
#include <boost/container/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/construct_in_place.hpp>
+
// move
#include <boost/move/adl_move_swap.hpp>
#include <boost/move/iterator.hpp>
@@ -515,7 +517,7 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F
F back = r;
BOOST_TRY{
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;
}
}
@@ -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)
{
while (n--) {
- *r = *f;
+ boost::container::assign_in_place(r, f);
++f; ++r;
}
return f;
@@ -1139,4 +1141,4 @@ void move_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_tr
} //namespace container {
} //namespace boost {
-#endif //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
+#endif //#ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
diff --git a/boost/container/detail/dispatch_uses_allocator.hpp b/boost/container/detail/dispatch_uses_allocator.hpp
index 3000f7cb27..fdf203cef8 100644
--- a/boost/container/detail/dispatch_uses_allocator.hpp
+++ b/boost/container/detail/dispatch_uses_allocator.hpp
@@ -222,7 +222,7 @@ template < typename ConstructAlloc
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
dispatch_uses_allocator
( ConstructAlloc & construct_alloc
- , ArgAlloc & arg_alloc
+ , BOOST_FWD_REF(ArgAlloc) arg_alloc
, Pair* p)
{
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first));
@@ -243,7 +243,7 @@ template < typename ConstructAlloc
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
dispatch_uses_allocator
( ConstructAlloc & construct_alloc
- , ArgAlloc & arg_alloc
+ , BOOST_FWD_REF(ArgAlloc) arg_alloc
, Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<U>(x));
@@ -263,7 +263,7 @@ template < typename ConstructAlloc
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if< container_detail::is_pair<Pair> >::type)
dispatch_uses_allocator
(ConstructAlloc & construct_alloc
- , ArgAlloc & arg_alloc
+ , BOOST_FWD_REF(ArgAlloc) arg_alloc
, Pair* p, Pair2& x)
{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, x.first, x.second); }
@@ -276,13 +276,135 @@ typename container_detail::enable_if_and
, container_detail::not_<boost::move_detail::is_reference<Pair2> > >::type //This is needed for MSVC10 and ambiguous overloads
dispatch_uses_allocator
(ConstructAlloc & construct_alloc
- , ArgAlloc & arg_alloc
+ , BOOST_FWD_REF(ArgAlloc) arg_alloc
, Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x)
{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); }
-//template <typename ConstructAlloc, typename ArgAlloc, class Pair, class Pair2>
-//void dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc
-// , pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
+
+//piecewise construction from boost::tuple
+#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
+template< typename ConstructAlloc, typename ArgAlloc, class Pair \
+ , template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
+ dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
+ , BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
+ , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
+{\
+ (void)p; (void)q;\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_TMPL_GET##N);\
+ BOOST_TRY{\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_TMPL_GETQ##M);\
+ }\
+ BOOST_CATCH(...) {\
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
+}\
+//
+BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
+#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
+
+//piecewise construction from Std Tuple
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template< typename ConstructAlloc, typename ArgAlloc, class Pair
+ , template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
+ void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair
+ , Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
+ {
+ (void)t1; (void)t2;
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(pair->first), ::boost::forward<Args1>(get<Indexes1>(t1))...);
+ BOOST_TRY{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(pair->second), ::boost::forward<Args2>(get<Indexes2>(t2))...);
+ }
+ BOOST_CATCH(...){
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ template< typename ConstructAlloc, typename ArgAlloc, class Pair
+ , template<class ...> class Tuple, class... Args1, class... Args2>
+ typename container_detail::enable_if< container_detail::is_pair<Pair> >::type
+ dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t
+ , Tuple<Args1...> t1, Tuple<Args2...> t2)
+ {
+ (dispatch_uses_allocator_index)( construct_alloc, arg_alloc, pair, t1, t2
+ , typename build_number_seq<sizeof...(Args1)>::type()
+ , typename build_number_seq<sizeof...(Args2)>::type());
+ }
+
+#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
+
+ //MSVC 2010 tuple implementation
+ #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
+ template< typename ConstructAlloc, typename ArgAlloc, class Pair\
+ , template<class, class, class, class, class, class, class, class, class, class> class StdTuple\
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
+ dispatch_uses_allocator(ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
+ , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
+ , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
+ {\
+ (void)p; (void)q;\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
+ BOOST_TRY{\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
+ }\
+ BOOST_CATCH(...) {\
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
+ }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
+ #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
+
+#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
+ #if _VARIADIC_MAX >= 9
+ #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
+ #else
+ #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
+ #endif
+
+ //MSVC 2012 tuple implementation
+ #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
+ template< typename ConstructAlloc, typename ArgAlloc, class Pair\
+ , template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
+ dispatch_uses_allocator\
+ ( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
+ , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
+ , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
+ {\
+ (void)p; (void)q;\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
+ BOOST_TRY{\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
+ }\
+ BOOST_CATCH(...) {\
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
+ }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
+ #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
+ #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
+
+#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
} //namespace container_detail
diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp
index 4c48c8b7d3..db73c410a9 100644
--- a/boost/container/detail/flat_tree.hpp
+++ b/boost/container/detail/flat_tree.hpp
@@ -32,11 +32,13 @@
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
#include <boost/container/detail/iterator.hpp>
+#include <boost/container/detail/is_sorted.hpp>
#include <boost/container/allocator_traits.hpp>
#ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
#include <boost/intrusive/pointer_traits.hpp>
#endif
#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/iterators.hpp>
#include <boost/move/make_unique.hpp>
#include <boost/move/adl_move_swap.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -44,6 +46,7 @@
#endif
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+#include <boost/move/iterator.hpp>
namespace boost {
namespace container {
@@ -98,7 +101,7 @@ struct get_flat_tree_iterators
typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
};
-template <class Key, class Value, class KeyOfValue,
+template <class Value, class KeyOfValue,
class Compare, class Allocator>
class flat_tree
{
@@ -183,7 +186,7 @@ class flat_tree
typedef typename vector_t::const_pointer const_pointer;
typedef typename vector_t::reference reference;
typedef typename vector_t::const_reference const_reference;
- typedef Key key_type;
+ typedef typename KeyOfValue::type key_type;
typedef Compare key_compare;
typedef typename vector_t::allocator_type allocator_type;
typedef typename vector_t::size_type size_type;
@@ -200,35 +203,36 @@ class flat_tree
typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
public:
- flat_tree()
+ BOOST_CONTAINER_FORCEINLINE flat_tree()
: m_data()
{ }
- explicit flat_tree(const Compare& comp)
+ BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const Compare& 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)
{ }
- explicit flat_tree(const allocator_type& a)
+ BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const allocator_type& a)
: m_data(a)
{ }
- flat_tree(const flat_tree& x)
+ BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x)
: 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)
: 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)
{ }
- 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)
{ }
@@ -237,7 +241,20 @@ class flat_tree
, const Compare& comp = Compare()
, const allocator_type& a = allocator_type())
: m_data(comp, a)
- { this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); }
+ {
+ this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last
+ , const Compare& comp = Compare()
+ , const allocator_type& a = allocator_type())
+ : m_data(comp, a)
+ {
+ this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp()));
+ }
template <class InputIterator>
flat_tree( bool unique_insertion
@@ -262,80 +279,93 @@ 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; }
- flat_tree& operator=(BOOST_RV_REF(flat_tree) x)
- BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
- && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value )
+ BOOST_CONTAINER_FORCEINLINE flat_tree& operator=(BOOST_RV_REF(flat_tree) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
{ m_data = boost::move(x.m_data); return *this; }
+ BOOST_CONTAINER_FORCEINLINE const value_compare &priv_value_comp() const
+ { return static_cast<const value_compare &>(this->m_data); }
+
+ BOOST_CONTAINER_FORCEINLINE value_compare &priv_value_comp()
+ { 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:
// accessors:
- Compare key_comp() const
+ BOOST_CONTAINER_FORCEINLINE Compare key_comp() const
{ return this->m_data.get_comp(); }
- value_compare value_comp() const
+ BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
{ 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(); }
- 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(); }
- stored_allocator_type &get_stored_allocator()
+ BOOST_CONTAINER_FORCEINLINE stored_allocator_type &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(); }
- const_iterator begin() const
+ BOOST_CONTAINER_FORCEINLINE const_iterator begin() const
{ return this->cbegin(); }
- const_iterator cbegin() const
+ BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const
{ return this->m_data.m_vect.begin(); }
- iterator end()
+ BOOST_CONTAINER_FORCEINLINE iterator end()
{ return this->m_data.m_vect.end(); }
- const_iterator end() const
+ BOOST_CONTAINER_FORCEINLINE const_iterator end() const
{ return this->cend(); }
- const_iterator cend() const
+ BOOST_CONTAINER_FORCEINLINE const_iterator cend() const
{ return this->m_data.m_vect.end(); }
- reverse_iterator rbegin()
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin()
{ return reverse_iterator(this->end()); }
- const_reverse_iterator rbegin() const
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const
{ return this->crbegin(); }
- const_reverse_iterator crbegin() const
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const
{ return const_reverse_iterator(this->cend()); }
- reverse_iterator rend()
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rend()
{ return reverse_iterator(this->begin()); }
- const_reverse_iterator rend() const
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const
{ return this->crend(); }
- const_reverse_iterator crend() const
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const
{ return const_reverse_iterator(this->cbegin()); }
- bool empty() const
+ BOOST_CONTAINER_FORCEINLINE bool empty() const
{ 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(); }
- size_type max_size() const
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const
{ 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::container::container_detail::is_nothrow_swappable<Compare>::value )
{ this->m_data.swap(other.m_data); }
@@ -346,7 +376,7 @@ class flat_tree
{
std::pair<iterator,bool> ret;
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)
: iterator(vector_iterator_get_ptr(data.position));
return ret;
@@ -356,7 +386,7 @@ class flat_tree
{
std::pair<iterator,bool> ret;
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))
: iterator(vector_iterator_get_ptr(data.position));
return ret;
@@ -381,7 +411,7 @@ class flat_tree
BOOST_ASSERT(this->priv_in_range_or_end(hint));
std::pair<iterator,bool> ret;
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)
: iterator(vector_iterator_get_ptr(data.position));
}
@@ -391,7 +421,7 @@ class flat_tree
BOOST_ASSERT(this->priv_in_range_or_end(hint));
std::pair<iterator,bool> ret;
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))
: iterator(vector_iterator_get_ptr(data.position));
}
@@ -481,7 +511,7 @@ class flat_tree
>::type * = 0
#endif
)
- { this->m_data.m_vect.merge(first, last); }
+ { this->m_data.m_vect.merge(first, last, static_cast<const value_compare &>(this->m_data)); }
template <class InIt>
void insert_unique(ordered_unique_range_t, InIt first, InIt last
@@ -510,7 +540,7 @@ class flat_tree
>::type * = 0
#endif
)
- { this->m_data.m_vect.merge_unique(first, last, value_compare()); }
+ { this->m_data.m_vect.merge_unique(first, last, static_cast<const value_compare &>(this->m_data)); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -560,6 +590,29 @@ class flat_tree
return this->insert_equal(hint, ::boost::move(val));
}
+ template <class KeyType, class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace
+ (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
+ {
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ const key_type & k = key;
+ 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());
+ }
+ else{
+ typedef typename emplace_functor_type<try_emplace_t, KeyType, Args...>::type func_t;
+ typedef emplace_iterator<value_type, func_t, difference_type> it_t;
+ func_t func(try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
+ ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());
+ }
+ return ret;
+ }
+
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE(N) \
@@ -606,13 +659,57 @@ class flat_tree
value_destructor<stored_allocator_type> d(a, val);\
return this->insert_equal(hint, ::boost::move(val));\
}\
+ template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\
+ try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ std::pair<iterator,bool> ret;\
+ insert_commit_data data;\
+ const key_type & k = key;\
+ 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());\
+ }\
+ else{\
+ typedef typename emplace_functor_type<try_emplace_t, KeyType BOOST_MOVE_I##N BOOST_MOVE_TARG##N>::type func_t;\
+ typedef emplace_iterator<value_type, func_t, difference_type> it_t;\
+ func_t func(try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());\
+ }\
+ return ret;\
+ }\
//
- BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE)
+ BOOST_MOVE_ITERATE_0TO7(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE)
#undef BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE
#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); }
size_type erase(const key_type& k)
@@ -625,10 +722,10 @@ class flat_tree
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); }
- void clear()
+ BOOST_CONTAINER_FORCEINLINE void clear()
{ this->m_data.m_vect.clear(); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created
@@ -637,19 +734,19 @@ class flat_tree
//! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
//!
//! <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(); }
- 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); }
- 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); }
- 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); }
- 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); }
// set operations:
@@ -682,64 +779,94 @@ class flat_tree
return n;
}
- iterator lower_bound(const key_type& k)
+ template<class C2>
+ void merge_unique(flat_tree<Value, KeyOfValue, C2, Allocator>& source)
+ {
+ this->insert( boost::make_move_iterator(source.begin())
+ , boost::make_move_iterator(source.end()));
+ }
+
+ template<class C2>
+ void merge_equal(flat_tree<Value, KeyOfValue, C2, Allocator>& source)
+ {
+ this->insert( boost::make_move_iterator(source.begin())
+ , boost::make_move_iterator(source.end()));
+ }
+
+ void merge_unique(flat_tree& source)
+ {
+ this->m_data.m_vect.merge_unique
+ ( boost::make_move_iterator(source.begin())
+ , boost::make_move_iterator(source.end())
+ , static_cast<const value_compare &>(this->m_data));
+ }
+
+ void merge_equal(flat_tree& source)
+ {
+ this->m_data.m_vect.merge
+ ( boost::make_move_iterator(source.begin())
+ , boost::make_move_iterator(source.end())
+ , static_cast<const value_compare &>(this->m_data));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& 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); }
- 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); }
- 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); }
- 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); }
- 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); }
- 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); }
- 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); }
- size_type capacity() const
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const
{ 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); }
- 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());
}
- 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());
}
- 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); }
- 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; }
- 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); }
- 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); }
- friend void swap(flat_tree& x, flat_tree& y)
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_tree& x, flat_tree& y)
{ x.swap(y); }
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());
}
@@ -780,34 +907,34 @@ class flat_tree
}
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;
- commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val));
- return commit_data.position == e || val_cmp(val, *commit_data.position);
+ const key_compare &key_cmp = this->priv_key_comp();
+ commit_data.position = this->priv_lower_bound(b, e, k);
+ return commit_data.position == e || key_cmp(k, KeyOfValue()(*commit_data.position));
}
- bool priv_insert_unique_prepare
- (const value_type& val, insert_commit_data &commit_data)
- { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), val, commit_data); }
+ BOOST_CONTAINER_FORCEINLINE bool priv_insert_unique_prepare
+ (const key_type& k, insert_commit_data &commit_data)
+ { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), k, commit_data); }
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!
- //To insert val at pos:
- //if pos == end || val <= *pos
- // if pos == begin || val >= *(pos-1)
- // insert val before pos
+ //To insert k at pos:
+ //if pos == end || k <= *pos
+ // if pos == begin || k >= *(pos-1)
+ // insert k before pos
// else
- // insert val before upper_bound(val)
- //else if pos+1 == end || val <= *(pos+1)
- // insert val after pos
+ // insert k before upper_bound(k)
+ //else if pos+1 == end || k <= *(pos+1)
+ // insert k after pos
//else
- // insert val before lower_bound(val)
- const value_compare &val_cmp = this->m_data;
+ // insert k before lower_bound(k)
+ const key_compare &key_cmp = this->priv_key_comp();
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();
commit_data.position = pos;
if(pos == cbeg){ //If container is empty then insert it in the beginning
@@ -815,27 +942,27 @@ class flat_tree
}
const_iterator prev(pos);
--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;
}
- 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;
return false;
}
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
- return this->priv_insert_unique_prepare(cbeg, prev, val, commit_data);
+ //but reduce the search between beg and prev as prev is bigger than k
+ return this->priv_insert_unique_prepare(cbeg, prev, k, commit_data);
}
}
else{
//The hint is before the insertion position, so insert it
//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>
- iterator priv_insert_commit
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert_commit
(insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
{
return this->m_data.m_vect.insert
@@ -966,9 +1093,9 @@ class flat_tree
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class Key, class T, class KeyOfValue,
+template <class T, class KeyOfValue,
class Compare, class Allocator>
-struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<Key, T, KeyOfValue, Compare, Allocator> >
+struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<T, KeyOfValue, Compare, Allocator> >
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
diff --git a/boost/container/detail/is_sorted.hpp b/boost/container/detail/is_sorted.hpp
new file mode 100644
index 0000000000..b8c223bb7b
--- /dev/null
+++ b/boost/container/detail/is_sorted.hpp
@@ -0,0 +1,57 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2016-2016. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
+#define BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+template <class ForwardIterator, class Pred>
+bool is_sorted (ForwardIterator first, ForwardIterator last, Pred pred)
+{
+ if(first != last){
+ ForwardIterator next = first;
+ while (++next != last){
+ if(pred(*next, *first))
+ return false;
+ ++first;
+ }
+ }
+ return true;
+}
+
+template <class ForwardIterator, class Pred>
+bool is_sorted_and_unique (ForwardIterator first, ForwardIterator last, Pred pred)
+{
+ if(first != last){
+ ForwardIterator next = first;
+ while (++next != last){
+ if(!pred(*first, *next))
+ return false;
+ ++first;
+ }
+ }
+ return true;
+}
+
+} //namespace container_detail {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
diff --git a/boost/container/detail/iterators.hpp b/boost/container/detail/iterators.hpp
index 32ff32f362..d3b353a461 100644
--- a/boost/container/detail/iterators.hpp
+++ b/boost/container/detail/iterators.hpp
@@ -26,6 +26,7 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/value_init.hpp>
#include <boost/static_assert.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/intrusive/detail/reverse_iterator.hpp>
@@ -560,17 +561,23 @@ class emplace_iterator
BOOST_CONTAINER_FORCEINLINE this_type operator-(difference_type off) const
{ return *this + (-off); }
+ private:
//This pseudo-iterator's dereference operations have no sense since value is not
//constructed until ::boost::container::construct_in_place is called.
//So comment them to catch bad uses
- //const T& operator*() const;
- //const T& operator[](difference_type) const;
- //const T* operator->() const;
+ const T& operator*() const;
+ const T& operator[](difference_type) const;
+ const T* operator->() const;
+ public:
template<class Allocator>
void construct_in_place(Allocator &a, T* ptr)
{ (*m_pe)(a, ptr); }
+ template<class DestIt>
+ void assign_in_place(DestIt dest)
+ { (*m_pe)(dest); }
+
private:
difference_type m_num;
EmplaceFunctor * m_pe;
@@ -612,21 +619,44 @@ struct emplace_functor
{}
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()); }
- template<class Allocator, class T, int ...IdxPack>
+ template<class DestIt>
+ BOOST_CONTAINER_FORCEINLINE void operator()(DestIt dest)
+ { emplace_functor::inplace_impl(dest, index_tuple_t()); }
+
+ private:
+ template<class Allocator, class T, std::size_t ...IdxPack>
BOOST_CONTAINER_FORCEINLINE void inplace_impl(Allocator &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
{
allocator_traits<Allocator>::construct
(a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
}
+ template<class DestIt, std::size_t ...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_;
};
+template<class ...Args>
+struct emplace_functor_type
+{
+ typedef emplace_functor<Args...> type;
+};
+
#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) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
struct emplace_functor##N\
@@ -638,10 +668,26 @@ struct emplace_functor##N\
void operator()(Allocator &a, T *ptr)\
{ 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;\
+ BOOST_MOVE_IF(N, value_type tmp(BOOST_MOVE_MFWD##N), container_detail::value_init<value_type> tmp) ;\
+ *dest = ::boost::move(const_cast<value_type &>(BOOST_MOVE_IF(N, tmp, tmp.get())));\
+ }\
+ \
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)
+
#undef BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE
#endif
diff --git a/boost/container/detail/mpl.hpp b/boost/container/detail/mpl.hpp
index e1684ea0b1..82fcc7036d 100644
--- a/boost/container/detail/mpl.hpp
+++ b/boost/container/detail/mpl.hpp
@@ -62,19 +62,18 @@ using boost::move_detail::disable_if_and;
using boost::move_detail::enable_if_or;
using boost::move_detail::disable_if_or;
-
-template <class Pair>
+template <class FirstType>
struct select1st
{
- typedef Pair argument_type;
- typedef typename Pair::first_type result_type;
+ typedef FirstType type;
- template<class OtherPair>
- const typename Pair::first_type& operator()(const OtherPair& x) const
+ template<class T>
+ const type& operator()(const T& x) const
{ return x.first; }
- const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
- { return x; }
+ template<class T>
+ type& operator()(T& x)
+ { return const_cast<type&>(x.first); }
};
} //namespace container_detail {
diff --git a/boost/container/detail/node_alloc_holder.hpp b/boost/container/detail/node_alloc_holder.hpp
index 1b7c4d76dc..7ef5d2883e 100644
--- a/boost/container/detail/node_alloc_holder.hpp
+++ b/boost/container/detail/node_alloc_holder.hpp
@@ -394,12 +394,6 @@ struct node_alloc_holder
ICont &non_const_icont() const
{ return const_cast<ICont&>(this->members_.m_icont); }
- ICont &icont()
- { return this->members_.m_icont; }
-
- const ICont &icont() const
- { return this->members_.m_icont; }
-
NodeAlloc &node_alloc()
{ return static_cast<NodeAlloc &>(this->members_); }
@@ -407,6 +401,13 @@ struct node_alloc_holder
{ return static_cast<const NodeAlloc &>(this->members_); }
members_holder members_;
+
+ public:
+ ICont &icont()
+ { return this->members_.m_icont; }
+
+ const ICont &icont() const
+ { return this->members_.m_icont; }
};
} //namespace container_detail {
diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp
index 134760e1e6..096f79561e 100644
--- a/boost/container/detail/pair.hpp
+++ b/boost/container/detail/pair.hpp
@@ -28,13 +28,62 @@
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/std_fwd.hpp>
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+# include <boost/container/detail/variadic_templates_tools.hpp>
+#endif
#include <boost/move/adl_move_swap.hpp> //swap
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
#include <boost/move/utility_core.hpp>
+#include<boost/move/detail/fwd_macros.hpp>
+
+namespace boost {
+namespace tuples {
+
+struct null_type;
+
+} //namespace tuples {
+} //namespace boost {
+
+#if defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
+//MSVC 2010 tuple marker
+namespace std { namespace tr1 { struct _Nil; }}
+#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
+//MSVC 2012 tuple marker
+namespace std { struct _Nil; }
+#endif
+
namespace boost {
namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ template <int Dummy = 0>
+ struct std_piecewise_construct_holder
+ {
+ static ::std::piecewise_construct_t *dummy;
+ };
+
+ template <int Dummy>
+ ::std::piecewise_construct_t *std_piecewise_construct_holder<Dummy>::dummy;
+
+typedef const std::piecewise_construct_t & piecewise_construct_t;
+
+struct try_emplace_t{};
+
+#else
+
+//! The piecewise_construct_t struct is an empty structure type used as a unique type to
+//! disambiguate used to disambiguate between different functions that take two tuple arguments.
+typedef unspecified piecewise_construct_t;
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A instance of type
+//! piecewise_construct_t
+static piecewise_construct_t piecewise_construct = BOOST_CONTAINER_DOC1ST(unspecified, *std_piecewise_construct_holder<>::dummy);
+
namespace container_detail {
template <class T1, class T2>
@@ -78,6 +127,9 @@ struct is_std_pair< std::pair<T1, T2> >
struct pair_nat;
+template<typename T, typename U, typename V>
+void get(T); //to enable ADL
+
template <class T1, class T2>
struct pair
{
@@ -147,11 +199,105 @@ struct pair
: first(::boost::move(p.first)), second(::boost::move(p.second))
{}
- //piecewise_construct missing
- //template <class U, class V> pair(pair<U, V>&& p);
- //template <class... Args1, class... Args2>
- // pair(piecewise_construct_t, tuple<Args1...> first_args,
- // tuple<Args2...> second_args);
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< class KeyType, class ...Args>
+ pair(try_emplace_t, BOOST_FWD_REF(KeyType) k, Args && ...args)
+ : first(boost::forward<KeyType>(k)), second(::boost::forward<Args>(args)...)\
+ {}
+ #else
+
+ //piecewise construction from boost::tuple
+ #define BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE(N)\
+ template< class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
+ pair( try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\
+ : first(boost::forward<KeyType>(k)), second(BOOST_MOVE_FWD##N)\
+ {}\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE)
+ #undef BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE
+
+ #endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ //piecewise construction from boost::tuple
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
+ template< template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ pair( piecewise_construct_t\
+ , BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
+ , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
+ : first(BOOST_MOVE_TMPL_GET##N), second(BOOST_MOVE_TMPL_GETQ##M)\
+ { (void)p; (void)q; }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
+ #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
+
+ //piecewise construction from variadic tuple (with delegating constructors)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ # if !defined(BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS)
+ private:
+ template<template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
+ pair(Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
+ : first (::boost::forward<Args1>(get<Indexes1>(t1))...)
+ , second(::boost::forward<Args2>(get<Indexes2>(t2))...)
+ { (void) t1; (void)t2; }
+
+ public:
+ template<template<class ...> class Tuple, class... Args1, class... Args2>
+ pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
+ : pair(t1, t2, typename build_number_seq<sizeof...(Args1)>::type(), typename build_number_seq<sizeof...(Args2)>::type())
+ {}
+ # else
+ //piecewise construction from variadic tuple (suboptimal, without delegating constructors)
+ private:
+ template<typename T, template<class ...> class Tuple, typename... Args>
+ static T build_from_args(Tuple<Args...>&& t)
+ { return do_build_from_args<T>(::boost::move(t), typename build_number_seq<sizeof...(Args)>::type()); }
+
+ template<typename T, template<class ...> class Tuple, typename... Args, std::size_t... Indexes>
+ static T do_build_from_args(Tuple<Args...> && t, const index_tuple<Indexes...>&)
+ { (void)t; return T(::boost::forward<Args>(get<Indexes>(t))...); }
+
+ public:
+ template<template<class ...> class Tuple, class... Args1, class... Args2>
+ pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
+ : first (build_from_args<first_type> (::boost::move(t1)))
+ , second (build_from_args<second_type>(::boost::move(t2)))
+ {}
+ # endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
+ //MSVC 2010 tuple implementation
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
+ template< template<class, class, class, class, class, class, class, class, class, class> class StdTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ pair( piecewise_construct_t\
+ , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
+ , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
+ : first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\
+ { (void)p; (void)q; }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
+ #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
+ #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
+ #if _VARIADIC_MAX >= 9
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
+ #else
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
+ #endif
+
+ //MSVC 2012 tuple implementation
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
+ template< template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ pair( piecewise_construct_t\
+ , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
+ , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
+ : first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\
+ { (void)p; (void)q; }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
+ #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
+ #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
+ #endif
//pair copy assignment
pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p)
@@ -283,6 +429,12 @@ struct is_enum< ::boost::container::container_detail::pair<T, U> >
static const bool value = false;
};
+template<class T, class U>
+struct is_enum< ::std::pair<T, U> >
+{
+ static const bool value = false;
+};
+
template <class T>
struct is_class;
@@ -325,8 +477,43 @@ struct is_class_or_union< std::pair<T1, T2> >
static const bool value = true;
};
+template<class T>
+struct is_union;
+
+template <class T1, class T2>
+struct is_union< ::boost::container::container_detail::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = false;
+};
+
+template <class T1, class T2>
+struct is_union< std::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = false;
+};
+template<class T>
+struct is_class;
+template <class T1, class T2>
+struct is_class< ::boost::container::container_detail::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
+
+template <class T1, class T2>
+struct is_class< std::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
} //namespace move_detail{
diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp
index 0fd6097650..853d0ad843 100644
--- a/boost/container/detail/tree.hpp
+++ b/boost/container/detail/tree.hpp
@@ -25,6 +25,7 @@
#include <boost/container/allocator_traits.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/options.hpp>
+#include <boost/container/node_handle.hpp>
// container/detail
#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
@@ -135,7 +136,7 @@ struct tree_node
typedef typename tree_internal_data_type<T>::type internal_type;
typedef tree_node< T, VoidPointer
- , tree_type_value, OptimizeSize> node_type;
+ , tree_type_value, OptimizeSize> node_t;
BOOST_CONTAINER_FORCEINLINE T &get_data()
{
@@ -199,11 +200,11 @@ class insert_equal_end_hint_functor
Icont &icont_;
public:
- insert_equal_end_hint_functor(Icont &icont)
+ BOOST_CONTAINER_FORCEINLINE insert_equal_end_hint_functor(Icont &icont)
: icont_(icont)
{}
- void operator()(Node &n)
+ BOOST_CONTAINER_FORCEINLINE void operator()(Node &n)
{ this->icont_.insert_equal(this->icont_.cend(), n); }
};
@@ -213,11 +214,11 @@ class push_back_functor
Icont &icont_;
public:
- push_back_functor(Icont &icont)
+ BOOST_CONTAINER_FORCEINLINE push_back_functor(Icont &icont)
: icont_(icont)
{}
- void operator()(Node &n)
+ BOOST_CONTAINER_FORCEINLINE void operator()(Node &n)
{ this->icont_.push_back(n); }
};
@@ -294,18 +295,18 @@ struct intrusive_tree_type
allocator_traits<Allocator>::size_type size_type;
typedef typename container_detail::tree_node
< value_type, void_pointer
- , tree_type_value, OptimizeSize> node_type;
+ , tree_type_value, OptimizeSize> node_t;
typedef value_to_node_compare
- <node_type, ValueCompare> node_compare_type;
- //Deducing the hook type from node_type (e.g. node_type::hook_type) would
- //provoke an early instantiation of node_type that could ruin recursive
+ <node_t, ValueCompare> node_compare_type;
+ //Deducing the hook type from node_t (e.g. node_t::hook_type) would
+ //provoke an early instantiation of node_t that could ruin recursive
//tree definitions, so retype the complete type to avoid any problem.
typedef typename intrusive_tree_hook
<void_pointer, tree_type_value
, OptimizeSize>::type hook_type;
public:
typedef typename intrusive_tree_dispatch
- < node_type, node_compare_type
+ < node_t, node_compare_type
, size_type, hook_type
, tree_type_value>::type type;
};
@@ -328,14 +329,14 @@ template< boost::container::tree_type_enum tree_type_value
struct intrusive_tree_proxy
{
template<class Icont>
- static void rebalance(Icont &) {}
+ BOOST_CONTAINER_FORCEINLINE static void rebalance(Icont &) {}
};
template<boost::container::tree_type_enum tree_type_value>
struct intrusive_tree_proxy<tree_type_value, true>
{
template<class Icont>
- static void rebalance(Icont &c)
+ BOOST_CONTAINER_FORCEINLINE static void rebalance(Icont &c)
{ c.rebalance(); }
};
@@ -351,7 +352,7 @@ template<class AllocHolder, bool DoMove>
class RecyclingCloner
{
typedef typename AllocHolder::intrusive_container intrusive_container;
- typedef typename AllocHolder::Node node_type;
+ typedef typename AllocHolder::Node node_t;
typedef typename AllocHolder::NodePtr node_ptr_type;
public:
@@ -359,13 +360,13 @@ class RecyclingCloner
: m_holder(holder), m_icont(itree)
{}
- 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); }
+ BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<true>)
+ { p->do_move_assign(const_cast<node_t &>(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_t &other, bool_<false>)
{ p->do_assign(other.m_data); }
- node_ptr_type operator()(const node_type &other) const
+ node_ptr_type operator()(const node_t &other) const
{
if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){
//First recycle a node (this can't throw)
@@ -393,59 +394,63 @@ class RecyclingCloner
intrusive_container &m_icont;
};
-template<class KeyValueCompare, class Node>
-//where KeyValueCompare is tree_value_compare<Key, T, Compare, KeyOfValue>
+template<class KeyCompare, class KeyOfValue>
struct key_node_compare
- : private KeyValueCompare
+ : public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
{
- explicit key_node_compare(const KeyValueCompare &comp)
- : KeyValueCompare(comp)
+ BOOST_CONTAINER_FORCEINLINE explicit key_node_compare(const KeyCompare &comp)
+ : base_t(comp)
{}
- template<class T>
- struct is_node
- {
- static const bool value = is_same<T, Node>::value;
- };
-
- template<class T>
- typename enable_if_c<is_node<T>::value, const typename KeyValueCompare::value_type &>::type
- key_forward(const T &node) const
- { return node.get_data(); }
-
- template<class T>
- #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
- #else
- typename enable_if_c<!is_node<T>::value, const T &>::type key_forward(const T &key) const
- #endif
- { return key; }
-
- template<class KeyType, class KeyType2>
- bool operator()(const KeyType &key1, const KeyType2 &key2) const
- { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
+ typedef boost::intrusive::detail::ebo_functor_holder<KeyCompare> base_t;
+ typedef KeyCompare key_compare;
+ typedef KeyOfValue key_of_value;
+ typedef typename KeyOfValue::type key_type;
+
+ BOOST_CONTAINER_FORCEINLINE const key_compare &key_comp() const
+ { return static_cast<const key_compare &>(*this); }
+
+ BOOST_CONTAINER_FORCEINLINE key_compare &key_comp()
+ { return static_cast<key_compare &>(*this); }
+
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const key_type &key2) const
+ { return this->key_comp()(key1, key2); }
+
+ template<class U>
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const U &nonkey2) const
+ { return this->key_comp()(key1, key_of_value()(nonkey2.get_data())); }
+
+ template<class U>
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const key_type &key2) const
+ { return this->key_comp()(key_of_value()(nonkey1.get_data()), key2); }
+
+ template<class U, class V>
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const V &nonkey2) const
+ { return this->key_comp()(key_of_value()(nonkey1.get_data()), key_of_value()(nonkey2.get_data())); }
};
-template <class Key, class T, class KeyOfValue,
+template <class T, class KeyOfValue,
class Compare, class Allocator,
class Options = tree_assoc_defaults>
class tree
- : protected container_detail::node_alloc_holder
+ : public container_detail::node_alloc_holder
< Allocator
, typename container_detail::intrusive_tree_type
- < Allocator, tree_value_compare<Key, T, Compare, KeyOfValue> //ValComp
+ < Allocator, tree_value_compare
+ <typename allocator_traits<Allocator>::pointer, Compare, KeyOfValue>
, Options::tree_type, Options::optimize_size>::type
>
{
typedef tree_value_compare
- <Key, T, Compare, KeyOfValue> ValComp;
+ < typename allocator_traits<Allocator>::pointer
+ , Compare, KeyOfValue> ValComp;
typedef typename container_detail::intrusive_tree_type
< Allocator, ValComp, Options::tree_type
, Options::optimize_size>::type Icont;
typedef container_detail::node_alloc_holder
<Allocator, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
- typedef tree < Key, T, KeyOfValue
+ typedef tree < T, KeyOfValue
, Compare, Allocator, Options> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef boost::container::
@@ -462,7 +467,7 @@ class tree
public:
- typedef Key key_type;
+ typedef typename KeyOfValue::type key_type;
typedef T value_type;
typedef Allocator allocator_type;
typedef Compare key_compare;
@@ -479,32 +484,36 @@ class tree
allocator_traits<Allocator>::size_type size_type;
typedef typename boost::container::
allocator_traits<Allocator>::difference_type difference_type;
- typedef difference_type tree_difference_type;
- typedef pointer tree_pointer;
- typedef const_pointer tree_const_pointer;
- typedef reference tree_reference;
- typedef const_reference tree_const_reference;
+ typedef container_detail::iterator_from_iiterator
+ <iiterator, false> iterator;
+ typedef container_detail::iterator_from_iiterator
+ <iiterator, true > const_iterator;
+ typedef boost::container::reverse_iterator
+ <iterator> reverse_iterator;
+ typedef boost::container::reverse_iterator
+ <const_iterator> const_reverse_iterator;
+ typedef node_handle
+ < Node, value_type, allocator_type, void> node_type;
+ typedef insert_return_type_base
+ <iterator, node_type> insert_return_type;
+
typedef NodeAlloc stored_allocator_type;
private:
- typedef key_node_compare<value_compare, Node> KeyNodeCompare;
+ typedef key_node_compare<key_compare, KeyOfValue> KeyNodeCompare;
public:
- typedef container_detail::iterator_from_iiterator<iiterator, false> iterator;
- typedef container_detail::iterator_from_iiterator<iiterator, true > const_iterator;
- typedef boost::container::reverse_iterator<iterator> reverse_iterator;
- typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
- tree()
+ BOOST_CONTAINER_FORCEINLINE tree()
: 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)
{}
- explicit tree(const allocator_type& a)
+ BOOST_CONTAINER_FORCEINLINE explicit tree(const allocator_type& a)
: AllocHolder(a)
{}
@@ -604,18 +613,19 @@ class tree
, 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)
{
this->icont().clone_from
(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)
: 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)
{
this->icont().clone_from
@@ -634,7 +644,7 @@ class tree
}
}
- ~tree()
+ BOOST_CONTAINER_FORCEINLINE ~tree()
{} //AllocHolder clears the tree
tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
@@ -669,8 +679,9 @@ class tree
}
tree& operator=(BOOST_RV_REF(tree) x)
- BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
- && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value )
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
{
BOOST_ASSERT(this != &x);
NodeAlloc &this_alloc = this->node_alloc();
@@ -712,43 +723,43 @@ class tree
public:
// accessors:
- value_compare value_comp() const
+ BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
{ 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(); }
- allocator_type get_allocator() const
+ BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
{ 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(); }
- stored_allocator_type &get_stored_allocator()
+ BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator()
{ return this->node_alloc(); }
- iterator begin()
+ BOOST_CONTAINER_FORCEINLINE iterator begin()
{ return iterator(this->icont().begin()); }
- const_iterator begin() const
+ BOOST_CONTAINER_FORCEINLINE const_iterator begin() const
{ return this->cbegin(); }
- iterator end()
+ BOOST_CONTAINER_FORCEINLINE iterator end()
{ return iterator(this->icont().end()); }
- const_iterator end() const
+ BOOST_CONTAINER_FORCEINLINE const_iterator end() const
{ return this->cend(); }
- reverse_iterator rbegin()
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin()
{ return reverse_iterator(end()); }
- const_reverse_iterator rbegin() const
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const
{ return this->crbegin(); }
- reverse_iterator rend()
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rend()
{ return reverse_iterator(begin()); }
- const_reverse_iterator rend() const
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const
{ return this->crend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -756,7 +767,7 @@ class tree
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin() const
+ BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const
{ return const_iterator(this->non_const_icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -764,7 +775,7 @@ class tree
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const
+ BOOST_CONTAINER_FORCEINLINE const_iterator cend() const
{ return const_iterator(this->non_const_icont().end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -773,7 +784,7 @@ class tree
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const
{ return const_reverse_iterator(cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -782,19 +793,19 @@ class tree
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const
{ return const_reverse_iterator(cbegin()); }
- bool empty() const
+ BOOST_CONTAINER_FORCEINLINE bool empty() const
{ return !this->size(); }
- size_type size() const
+ BOOST_CONTAINER_FORCEINLINE size_type size() const
{ return this->icont().size(); }
- size_type max_size() const
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const
{ 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::container::container_detail::is_nothrow_swappable<Compare>::value )
{ AllocHolder::swap(x); }
@@ -808,7 +819,7 @@ class tree
(const key_type& key, insert_commit_data &data)
{
std::pair<iiterator, bool> ret =
- this->icont().insert_unique_check(key, KeyNodeCompare(value_comp()), data);
+ this->icont().insert_unique_check(key, KeyNodeCompare(key_comp()), data);
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
}
@@ -817,19 +828,10 @@ class tree
{
BOOST_ASSERT((priv_is_linked)(hint));
std::pair<iiterator, bool> ret =
- this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(value_comp()), data);
+ this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(key_comp()), data);
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
}
- iterator insert_unique_commit(const value_type& v, insert_commit_data &data)
- {
- NodePtr tmp = AllocHolder::create_node(v);
- 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 MovableConvertible>
iterator insert_unique_commit
(BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data)
@@ -841,17 +843,6 @@ class tree
return ret;
}
- std::pair<iterator,bool> insert_unique(const value_type& v)
- {
- insert_commit_data data;
- std::pair<iterator,bool> ret =
- this->insert_unique_check(KeyOfValue()(v), data);
- if(ret.second){
- ret.first = this->insert_unique_commit(v, data);
- }
- return ret;
- }
-
template<class MovableConvertible>
std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) v)
{
@@ -866,6 +857,17 @@ class tree
private:
+ 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
{
iiterator const cur(position.get());
@@ -896,7 +898,7 @@ class tree
//No throw insertion part, release rollback
destroy_deallocator.release();
return std::pair<iterator,bool>
- ( iterator(iiterator(this->icont().insert_unique_commit(*p, data)))
+ ( iterator(this->icont().insert_unique_commit(*p, data))
, true );
}
@@ -911,7 +913,7 @@ class tree
Destroyer(this->node_alloc())(p);
return ret.first;
}
- return iterator(iiterator(this->icont().insert_unique_commit(*p, data)));
+ return iterator(this->icont().insert_unique_commit(*p, data));
}
public:
@@ -919,11 +921,11 @@ class tree
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
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)...)); }
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)...)); }
template <class... Args>
@@ -947,6 +949,22 @@ class tree
return ret;
}
+ template <class KeyType, class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace
+ (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
+ {
+ insert_commit_data data;
+ const key_type & k = key; //Support emulated rvalue references
+ std::pair<iiterator, bool> ret =
+ hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data)
+ : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
+ if(ret.second){
+ ret.first = this->icont().insert_unique_commit
+ (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key), boost::forward<Args>(args)...), data);
+ }
+ return std::pair<iterator, bool>(iterator(ret.first), ret.second);
+ }
+
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \
@@ -978,6 +996,22 @@ class tree
destroy_deallocator.release();\
return ret;\
}\
+ \
+ template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\
+ try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ insert_commit_data data;\
+ const key_type & k = key;\
+ std::pair<iiterator, bool> ret =\
+ hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data)\
+ : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);\
+ if(ret.second){\
+ ret.first = this->icont().insert_unique_commit\
+ (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\
+ }\
+ return std::pair<iterator, bool>(iterator(ret.first), ret.second);\
+ }\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_TREE_EMPLACE_CODE)
#undef BOOST_CONTAINER_TREE_EMPLACE_CODE
@@ -1044,27 +1078,21 @@ class tree
this->insert_equal(*first);
}
- template<class KeyConvertible>
- iterator insert_from_key(BOOST_FWD_REF(KeyConvertible) key)
+ 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)
{
insert_commit_data data;
const key_type & k = key; //Support emulated rvalue references
std::pair<iiterator, bool> ret =
- this->icont().insert_unique_check(k, KeyNodeCompare(value_comp()), data);
- return ret.second
- ? this->insert_unique_key_commit(boost::forward<KeyConvertible>(key), data)
- : iterator(ret.first);
- }
-
- template<class KeyConvertible>
- iterator 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;
+ hint == const_iterator() ? this->icont().insert_unique_check(k, KeyNodeCompare(key_comp()), data)
+ : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_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)
@@ -1073,8 +1101,8 @@ class tree
return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc())));
}
- size_type erase(const key_type& k)
- { return AllocHolder::erase_key(k, KeyNodeCompare(value_comp()), alloc_version()); }
+ BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& k)
+ { return AllocHolder::erase_key(k, KeyNodeCompare(key_comp()), alloc_version()); }
iterator erase(const_iterator first, const_iterator last)
{
@@ -1083,43 +1111,117 @@ class tree
return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version()));
}
- void clear()
+ node_type extract(const key_type& k)
+ {
+ iterator const it = this->find(k);
+ if(this->end() != it){
+ return this->extract(it);
+ }
+ return node_type();
+ }
+
+ node_type extract(const_iterator position)
+ {
+ BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position));
+ iiterator const iit(position.get());
+ this->icont().erase(iit);
+ return node_type(iit.operator->(), this->node_alloc());
+ }
+
+ insert_return_type insert_unique_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ return this->insert_unique_node(this->end(), boost::move(nh));
+ }
+
+ insert_return_type insert_unique_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ insert_return_type irt; //inserted == false, node.empty()
+ if(!nh.empty()){
+ insert_commit_data data;
+ std::pair<iterator,bool> ret =
+ this->insert_unique_check(hint, KeyOfValue()(nh.value()), data);
+ if(ret.second){
+ irt.inserted = true;
+ irt.position = iterator(this->icont().insert_unique_commit(*nh.get_node_pointer(), data));
+ nh.release();
+ }
+ else{
+ irt.position = ret.first;
+ irt.node = boost::move(nh);
+ }
+ }
+ else{
+ irt.position = this->end();
+ }
+ return BOOST_MOVE_RET(insert_return_type, irt);
+ }
+
+ iterator insert_equal_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ if(nh.empty()){
+ return this->end();
+ }
+ else{
+ NodePtr const p(nh.release());
+ return iterator(this->icont().insert_equal(*p));
+ }
+ }
+
+ iterator insert_equal_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ if(nh.empty()){
+ return this->end();
+ }
+ else{
+ NodePtr const p(nh.release());
+ return iterator(this->icont().insert_equal(hint.get(), *p));
+ }
+ }
+
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge_unique(tree<T, KeyOfValue, C2, Allocator, Options>& source)
+ { return this->icont().merge_unique(source.icont()); }
+
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge_equal(tree<T, KeyOfValue, C2, Allocator, Options>& source)
+ { return this->icont().merge_equal(source.icont()); }
+ BOOST_CONTAINER_FORCEINLINE void clear()
{ AllocHolder::clear(alloc_version()); }
// 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
- iterator find(const key_type& k)
- { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); }
+ BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& k)
+ { return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); }
- const_iterator find(const key_type& k) const
- { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); }
+ BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& k) const
+ { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); }
- size_type count(const key_type& k) const
- { return size_type(this->icont().count(k, KeyNodeCompare(value_comp()))); }
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& k) const
+ { return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); }
- iterator lower_bound(const key_type& k)
- { return iterator(this->icont().lower_bound(k, KeyNodeCompare(value_comp()))); }
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k)
+ { return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
- const_iterator lower_bound(const key_type& k) const
- { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(value_comp()))); }
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const
+ { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
- iterator upper_bound(const key_type& k)
- { return iterator(this->icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k)
+ { return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
- const_iterator upper_bound(const key_type& k) const
- { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const
+ { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
std::pair<iterator,iterator> equal_range(const key_type& k)
{
std::pair<iiterator, iiterator> ret =
- this->icont().equal_range(k, KeyNodeCompare(value_comp()));
+ this->icont().equal_range(k, KeyNodeCompare(key_comp()));
return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
}
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
{
std::pair<iiterator, iiterator> ret =
- this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp()));
+ this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp()));
return std::pair<const_iterator,const_iterator>
(const_iterator(ret.first), const_iterator(ret.second));
}
@@ -1127,40 +1229,40 @@ class tree
std::pair<iterator,iterator> lower_bound_range(const key_type& k)
{
std::pair<iiterator, iiterator> ret =
- this->icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
+ this->icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
}
std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
{
std::pair<iiterator, iiterator> ret =
- this->non_const_icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
+ this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
return std::pair<const_iterator,const_iterator>
(const_iterator(ret.first), const_iterator(ret.second));
}
- void rebalance()
+ BOOST_CONTAINER_FORCEINLINE void rebalance()
{ 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()); }
- 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()); }
- friend bool operator!=(const tree& x, const tree& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const tree& x, const tree& 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; }
- friend bool operator<=(const tree& x, const tree& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const tree& x, const tree& y)
{ 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); }
- friend void swap(tree& x, tree& y)
+ BOOST_CONTAINER_FORCEINLINE friend void swap(tree& x, tree& y)
{ x.swap(y); }
};
@@ -1172,11 +1274,11 @@ struct has_trivial_destructor_after_move;
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class Key, class T, class KeyOfValue, class Compare, class Allocator, class Options>
+template <class T, class KeyOfValue, class Compare, class Allocator, class Options>
struct has_trivial_destructor_after_move
<
::boost::container::container_detail::tree
- <Key, T, KeyOfValue, Compare, Allocator, Options>
+ <T, KeyOfValue, Compare, Allocator, Options>
>
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
diff --git a/boost/container/detail/value_init.hpp b/boost/container/detail/value_init.hpp
index eb4c976d92..faba70ee14 100644
--- a/boost/container/detail/value_init.hpp
+++ b/boost/container/detail/value_init.hpp
@@ -37,6 +37,8 @@ struct value_init
operator T &() { return m_t; }
+ T &get() { return m_t; }
+
T m_t;
};
diff --git a/boost/container/detail/variadic_templates_tools.hpp b/boost/container/detail/variadic_templates_tools.hpp
index d8c8443038..f5101c577c 100644
--- a/boost/container/detail/variadic_templates_tools.hpp
+++ b/boost/container/detail/variadic_templates_tools.hpp
@@ -21,6 +21,7 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <cstddef> //std::size_t
@@ -42,13 +43,13 @@ class tuple<Head, Tail...>
typedef tuple<Tail...> inherited;
public:
- tuple() { }
+ tuple()
+ : inherited(), m_head()
+ {}
- // implicit copy-constructor is okay
- // Construct tuple from separate arguments.
- tuple(typename add_const_reference<Head>::type v,
- typename add_const_reference<Tail>::type... vtail)
- : inherited(vtail...), m_head(v)
+ template<class U, class ...Args>
+ tuple(U &&u, Args && ...args)
+ : inherited(::boost::forward<Args>(args)...), m_head(::boost::forward<U>(u))
{}
// Construct tuple from another tuple.
@@ -77,8 +78,8 @@ class tuple<Head, Tail...>
template<typename... Values>
-tuple<Values&&...> tie_forward(Values&&... values)
-{ return tuple<Values&&...>(values...); }
+tuple<Values&&...> forward_as_tuple(Values&&... values)
+{ return tuple<Values&&...>(::boost::forward<Values>(values)...); }
template<int I, typename Tuple>
struct tuple_element;
@@ -135,18 +136,18 @@ typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>&
// in a function call.
////////////////////////////////////////////////////
-template<int... Indexes>
+template<std::size_t ... Indexes>
struct index_tuple{};
template<std::size_t Num, typename Tuple = index_tuple<> >
struct build_number_seq;
-template<std::size_t Num, int... Indexes>
+template<std::size_t Num, std::size_t ... Indexes>
struct build_number_seq<Num, index_tuple<Indexes...> >
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
{};
-template<int... Indexes>
+template<std::size_t ... Indexes>
struct build_number_seq<0, index_tuple<Indexes...> >
{ typedef index_tuple<Indexes...> type; };
diff --git a/boost/container/detail/workaround.hpp b/boost/container/detail/workaround.hpp
index ae9151c32d..64ecd6fd6b 100644
--- a/boost/container/detail/workaround.hpp
+++ b/boost/container/detail/workaround.hpp
@@ -29,12 +29,30 @@
#define BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST
#endif
+#if defined(BOOST_GCC_VERSION)
+# if (BOOST_GCC_VERSION < 40700) || !defined(BOOST_GCC_CXX11)
+# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
+# endif
+#elif defined(BOOST_MSVC)
+# if _MSC_FULL_VER < 180020827
+# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
+# endif
+#elif defined(BOOST_CLANG)
+# if !__has_feature(cxx_delegating_constructors)
+# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
+# endif
+#endif
+
#if !defined(BOOST_FALLTHOUGH)
#define BOOST_CONTAINER_FALLTHOUGH
#else
#define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH;
#endif
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || (defined(BOOST_MSVC) && (BOOST_MSVC == 1700 || BOOST_MSVC == 1600))
+#define BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+#endif
+
//Macros for documentation purposes. For code, expands to the argument
#define BOOST_CONTAINER_IMPDEF(TYPE) TYPE
#define BOOST_CONTAINER_SEEDOC(TYPE) TYPE