Complete support for user-provided containers to flat_[multi]map/set containers, and instantiate them with several container types.

This commit is contained in:
Ion Gaztañaga
2017-08-28 10:45:29 +02:00
parent 2297f6af72
commit c123accab1
8 changed files with 555 additions and 131 deletions
@@ -0,0 +1,49 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2017-2017. 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_CONTAINER_OR_ALLOCATOR_REBIND_HPP
#define BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/container_rebind.hpp>
#include <boost/container/detail/is_container.hpp>
namespace boost {
namespace container {
namespace container_detail {
template<class AllocatorOrContainer, class ToType, bool = is_container<AllocatorOrContainer>::value>
struct container_or_allocator_rebind_impl
: container_rebind<AllocatorOrContainer, ToType>
{};
template<class AllocatorOrContainer, class ToType>
struct container_or_allocator_rebind_impl<AllocatorOrContainer, ToType, false>
: allocator_traits<AllocatorOrContainer>::template portable_rebind_alloc<ToType>
{};
template<class AllocatorOrContainer, class ToType>
struct container_or_allocator_rebind
: container_or_allocator_rebind_impl<AllocatorOrContainer, ToType>
{};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_HPP
@@ -0,0 +1,258 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2017-2017. 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_CONTAINER_REBIND_HPP
#define BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/container/allocator_traits.hpp>
namespace boost {
namespace container {
namespace container_detail {
template <class Cont, class U>
struct container_rebind;
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <template <class, class, class...> class Cont, typename V, typename A, class... An, class U>
struct container_rebind<Cont<V, A, An...>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, An...> type;
};
//Needed for non-conforming compilers like GCC 4.3
template <template <class, class> class Cont, typename V, typename A, class U>
struct container_rebind<Cont<V, A>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
};
template <template <class> class Cont, typename V, class U>
struct container_rebind<Cont<V>, U>
{
typedef Cont<U> type;
};
//for small_vector,static_vector
template <template <class, std::size_t, class, class...> class Cont, typename V, std::size_t N, typename A, class... An, class U>
struct container_rebind<Cont<V, N, A, An...>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, An...> type;
};
//Needed for non-conforming compilers like GCC 4.3
template <template <class, std::size_t, class> class Cont, typename V, std::size_t N, typename A, class U>
struct container_rebind<Cont<V, N, A>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
};
template <template <class, std::size_t> class Cont, typename V, std::size_t N, class U>
struct container_rebind<Cont<V, N>, U>
{
typedef Cont<U, N> type;
};
#else //C++03 compilers
template <template <class> class Cont //0arg
, typename V
, class U>
struct container_rebind<Cont<V>, U>
{
typedef Cont<U> type;
};
template <template <class, class> class Cont //0arg
, typename V, typename A
, class U>
struct container_rebind<Cont<V, A>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
};
template <template <class, class, class> class Cont //1arg
, typename V, typename A, class P0
, class U>
struct container_rebind<Cont<V, A, P0>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0> type;
};
template <template <class, class, class, class> class Cont //2arg
, typename V, typename A, class P0, class P1
, class U>
struct container_rebind<Cont<V, A, P0, P1>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1> type;
};
template <template <class, class, class, class, class> class Cont //3arg
, typename V, typename A, class P0, class P1, class P2
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
};
template <template <class, class, class, class, class, class> class Cont //4arg
, typename V, typename A, class P0, class P1, class P2, class P3
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
};
template <template <class, class, class, class, class, class, class> class Cont //5arg
, typename V, typename A, class P0, class P1, class P2, class P3, class P4
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
};
template <template <class, class, class, class, class, class, class, class> class Cont //6arg
, typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
};
template <template <class, class, class, class, class, class, class, class, class> class Cont //7arg
, typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
};
template <template <class, class, class, class, class, class, class, class, class, class> class Cont //8arg
, typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
};
template <template <class, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
, typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
{
typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
};
//For small_vector/static_vector
template <template <class, std::size_t> class Cont //0arg
, typename V, std::size_t N
, class U>
struct container_rebind<Cont<V, N>, U>
{
typedef Cont<U, N> type;
};
template <template <class, std::size_t, class> class Cont //0arg
, typename V, std::size_t N, typename A
, class U>
struct container_rebind<Cont<V, N, A>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
};
template <template <class, std::size_t, class, class> class Cont //1arg
, typename V, std::size_t N, typename A, class P0
, class U>
struct container_rebind<Cont<V, N, A, P0>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0> type;
};
template <template <class, std::size_t, class, class, class> class Cont //2arg
, typename V, std::size_t N, typename A, class P0, class P1
, class U>
struct container_rebind<Cont<V, N, A, P0, P1>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1> type;
};
template <template <class, std::size_t, class, class, class, class> class Cont //3arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
};
template <template <class, std::size_t, class, class, class, class, class> class Cont //4arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
};
template <template <class, std::size_t, class, class, class, class, class, class> class Cont //5arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
};
template <template <class, std::size_t, class, class, class, class, class, class, class> class Cont //6arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
};
template <template <class, std::size_t, class, class, class, class, class, class, class, class> class Cont //7arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
};
template <template <class, std::size_t, class, class, class, class, class, class, class, class, class> class Cont //8arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
};
template <template <class, std::size_t, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
, typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
, class U>
struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
{
typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
};
#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_HPP
+143 -65
View File
@@ -86,60 +86,87 @@
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//reserve
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME reserve
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//capacity
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME capacity
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
namespace container {
namespace container_detail {
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
(SequenceContainer& dest, Iterator begin, Iterator end, Compare comp, container_detail::false_)
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, container_detail::true_)
{
dest.merge(first, last, comp);
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal_non_merge_member
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, container_detail::true_)
{
typedef typename SequenceContainer::iterator iterator;
typedef typename SequenceContainer::value_type value_type;
iterator it = dest.insert( dest.end(), boost::make_move_iterator(begin), boost::make_move_iterator(end) );
if (is_contiguous_container<SequenceContainer>::value){
value_type *const braw = boost::movelib::iterator_to_raw_pointer(dest.begin());
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
value_type *const sraw = boost::movelib::iterator_to_raw_pointer(dest.begin()+dest.size());
boost::movelib::adaptive_sort(iraw, eraw, comp, sraw, dest.capacity());
boost::movelib::adaptive_merge(braw, iraw, eraw, comp, sraw, dest.capacity()- dest.size());
}
else{
boost::movelib::adaptive_sort(it, dest.end(), comp);
boost::movelib::adaptive_merge(dest.begin(), it, dest.end(), comp);
}
iterator const it = dest.insert( dest.end(), first, last );
value_type *const braw = boost::movelib::iterator_to_raw_pointer(dest.begin());
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
value_type *const sraw = boost::movelib::iterator_to_raw_pointer(dest.begin()+dest.size());
boost::movelib::adaptive_sort(iraw, eraw, comp, sraw, dest.capacity());
boost::movelib::adaptive_merge(braw, iraw, eraw, comp, sraw, dest.capacity()- dest.size());
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique
(SequenceContainer& dest, Iterator begin, Iterator end, Compare comp, container_detail::false_)
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal_non_merge_member
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, container_detail::false_)
{
(flat_tree_merge_equal)(dest, begin, end, comp, container_detail::false_());
dest.erase(boost::movelib::unique
(dest.begin(), dest.end(), boost::movelib::negate<Compare>(comp)), dest.cend());
typedef typename SequenceContainer::iterator iterator;
iterator const it = dest.insert( dest.end(), first, last );
boost::movelib::adaptive_sort(it, dest.end(), comp);
boost::movelib::adaptive_merge(dest.begin(), it, dest.end(), comp);
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
(SequenceContainer& dest, Iterator begin, Iterator end, Compare comp, container_detail::true_)
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, container_detail::false_)
{
dest.merge(begin, end, comp);
(flat_tree_merge_equal_non_merge_member)( dest, first, last, comp
, container_detail::bool_<is_contiguous_container<SequenceContainer>::value>());
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique
(SequenceContainer& dest, Iterator begin, Iterator end, Compare comp, container_detail::true_)
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, container_detail::true_)
{
dest.merge_unique(begin, end, comp);
dest.merge_unique(first, last, comp);
}
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, container_detail::false_)
{
(flat_tree_merge_equal)(dest, first, last, comp, container_detail::false_());
dest.erase(boost::movelib::unique
(dest.begin(), dest.end(), boost::movelib::negate<Compare>(comp)), dest.cend());
}
template<class SequenceContainer, class Iterator>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
@@ -192,12 +219,83 @@ BOOST_CONTAINER_FORCEINLINE const typename SequenceContainer::stored_allocator_t
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::allocator_type
flat_tree_get_stored_allocator
flat_tree_get_stored_allocator
(SequenceContainer& cont, container_detail::false_)
{
return cont.get_allocator();
}
template<class SequenceContainer, class Compare>
void flat_tree_adopt_sequence_equal(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, container_detail::true_)
{
tseq.clear();
boost::movelib::adaptive_sort
(boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, comp
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size());
tseq = boost::move(seq);
}
template<class SequenceContainer, class Compare>
void flat_tree_adopt_sequence_equal(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, container_detail::false_)
{
boost::movelib::adaptive_sort(seq.begin(), seq.end(), comp);
tseq = boost::move(seq);
}
template<class SequenceContainer, class Compare>
void flat_tree_adopt_sequence_unique(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, container_detail::true_)
{
boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, comp
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size());
seq.erase(boost::movelib::unique
( seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp))
, seq.cend());
tseq = boost::move(seq);
}
template<class SequenceContainer, class Compare>
void flat_tree_adopt_sequence_unique(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, container_detail::false_)
{
boost::movelib::adaptive_sort(seq.begin(), seq.end(), comp);
seq.erase(boost::movelib::unique
(seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
tseq = boost::move(seq);
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE void
flat_tree_reserve(SequenceContainer &tseq, typename SequenceContainer::size_type cap, container_detail::true_)
{
tseq.reserve(cap);
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE void
flat_tree_reserve(SequenceContainer &, typename SequenceContainer::size_type, container_detail::false_)
{
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
flat_tree_capacity(const SequenceContainer &tseq, container_detail::true_)
{
return tseq.capacity();
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
flat_tree_capacity(const SequenceContainer &tseq, container_detail::false_)
{
return tseq.size();
}
template<class Compare, class Value, class KeyOfValue>
class flat_tree_value_compare
: private Compare
@@ -268,6 +366,7 @@ class flat_tree
typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
private:
struct Data
//Inherit from value_compare to do EBO
: public value_compare
@@ -1088,10 +1187,18 @@ class flat_tree
{ return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
BOOST_CONTAINER_FORCEINLINE size_type capacity() const
{ return this->m_data.m_seq.capacity(); }
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_capacity<container_type>::value;
return (flat_tree_capacity)(this->m_data.m_seq, container_detail::bool_<value>());
}
BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
{ this->m_data.m_seq.reserve(cnt); }
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_reserve<container_type, size_type>::value;
(flat_tree_reserve)(this->m_data.m_seq, cnt, container_detail::bool_<value>());
}
BOOST_CONTAINER_FORCEINLINE container_type extract_sequence()
{
@@ -1103,57 +1210,28 @@ class flat_tree
return m_data.m_seq;
}
void adopt_sequence_equal(BOOST_RV_REF(container_type) seq)
BOOST_CONTAINER_FORCEINLINE void adopt_sequence_equal(BOOST_RV_REF(container_type) seq)
{
container_type &tseq = m_data.m_seq;
if (is_contiguous_container<container_type>::value){
boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, this->priv_value_comp()
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size());
}
else{
boost::movelib::adaptive_sort
(seq.begin(), seq.end(), this->priv_value_comp());
}
tseq = boost::move(seq);
(flat_tree_adopt_sequence_equal)( m_data.m_seq, boost::move(seq), this->priv_value_comp()
, container_detail::bool_<is_contiguous_container<container_type>::value>());
}
void adopt_sequence_unique(BOOST_RV_REF(container_type) seq)
BOOST_CONTAINER_FORCEINLINE void adopt_sequence_unique(BOOST_RV_REF(container_type) seq)
{
container_type &tseq = m_data.m_seq;
if (is_contiguous_container<container_type>::value){
boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, this->priv_value_comp()
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size());
}
else{
boost::movelib::adaptive_sort
( seq.begin(), seq.end(), this->priv_value_comp());
}
seq.erase( boost::movelib::unique
(seq.begin(), seq.end(), boost::movelib::negate<value_compare>(this->m_data.get_comp()))
, seq.cend());
tseq = boost::move(seq);
(flat_tree_adopt_sequence_unique)(m_data.m_seq, boost::move(seq), this->priv_value_comp()
, container_detail::bool_<is_contiguous_container<container_type>::value>());
}
void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(container_type) seq)
{
BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
container_type &tseq = m_data.m_seq;
tseq = boost::move(seq);
m_data.m_seq = boost::move(seq);
}
void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(container_type) seq)
{
BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
container_type &tseq = m_data.m_seq;
tseq = boost::move(seq);
m_data.m_seq = boost::move(seq);
}
BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_tree& x, const flat_tree& y)
+12 -9
View File
@@ -30,6 +30,7 @@
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/algorithm.hpp> //equal()
#include <boost/container/detail/container_or_allocator_rebind.hpp>
// move
#include <boost/move/utility_core.hpp>
#include <boost/move/traits.hpp>
@@ -125,8 +126,8 @@ class flat_map
container_detail::pair<Key, T>,
container_detail::select1st<Key>,
Compare,
typename allocator_traits<AllocatorOrContainer>::template portable_rebind_alloc
<container_detail::pair<Key, T> >::type> impl_tree_t;
typename container_detail::container_or_allocator_rebind<AllocatorOrContainer, container_detail::pair<Key, T> >::type
> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
typedef typename impl_tree_t::value_type impl_value_type;
@@ -652,7 +653,8 @@ class flat_map
BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
//! <b>Effects</b>: If n is less than or equal to capacity(), or the
//! underlying container has no `reserve` member, this call has no
//! effect. Otherwise, it is a request for allocation of additional memory.
//! If the request is successful, then capacity() is greater than or equal to
//! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
@@ -1507,8 +1509,8 @@ class flat_multimap
container_detail::pair<Key, T>,
container_detail::select1st<Key>,
Compare,
typename allocator_traits<AllocatorOrContainer>::template portable_rebind_alloc
<container_detail::pair<Key, T> >::type> impl_tree_t;
typename container_detail::container_or_allocator_rebind<AllocatorOrContainer, container_detail::pair<Key, T> >::type
> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
typedef typename impl_tree_t::value_type impl_value_type;
@@ -1798,7 +1800,7 @@ class flat_multimap
: m_flat_tree( ordered_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, comp, a)
, comp, container_detail::force<const impl_allocator_type>(a))
{}
#endif
@@ -1826,7 +1828,7 @@ class flat_multimap
//! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE
flat_multimap(const flat_multimap& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
: m_flat_tree(x.m_flat_tree, container_detail::force<const impl_allocator_type>(a))
{}
//! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator.
@@ -1835,7 +1837,7 @@ class flat_multimap
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
BOOST_CONTAINER_FORCEINLINE
flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
: m_flat_tree(boost::move(x.m_flat_tree), container_detail::force<const impl_allocator_type>(a))
{}
//! <b>Effects</b>: Makes *this a copy of x.
@@ -2061,7 +2063,8 @@ class flat_multimap
size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
//! <b>Effects</b>: If n is less than or equal to capacity(), or the
//! underlying container has no `reserve` member, this call has no
//! effect. Otherwise, it is a request for allocation of additional memory.
//! If the request is successful, then capacity() is greater than or equal to
//! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+3 -2
View File
@@ -543,12 +543,13 @@ class flat_set
//! <b>Complexity</b>: Constant.
size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW;
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
//! <b>Effects</b>: If n is less than or equal to capacity(), or the
//! underlying container has no `reserve` member, this call has no
//! effect. Otherwise, it is a request for allocation of additional memory.
//! If the request is successful, then capacity() is greater than or equal to
//! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
//!
//! <b>Throws</b>: If memory allocation allocation throws or Key's copy constructor throws.
//! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
//!
//! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
//! to values might be invalidated.