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

View File

@@ -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

View File

@@ -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

View File

@@ -86,23 +86,45 @@
#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){
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());
@@ -110,36 +132,41 @@ BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
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);
}
}
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
@@ -198,6 +225,77 @@ flat_tree_get_stored_allocator
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)

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.

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.

View File

@@ -13,6 +13,10 @@
#include <boost/container/allocator.hpp>
#include <boost/container/detail/flat_tree.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/container/deque.hpp>
#include <boost/container/static_vector.hpp>
#include <boost/container/detail/container_or_allocator_rebind.hpp>
#include "print_container.hpp"
#include "dummy_test_allocator.hpp"
@@ -23,7 +27,6 @@
#include "emplace_test.hpp"
#include "../../intrusive/test/iterator_test.hpp"
#include <vector>
#include <map>
@@ -35,29 +38,20 @@ namespace container {
//Explicit instantiation to detect compilation errors
//flat_map
typedef std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> test_pair_t;
template class flat_map
< test::movable_and_copyable_int
, test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, test::simple_allocator
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
, test::simple_allocator< test_pair_t >
>;
template class flat_map
< test::movable_and_copyable_int
, test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, std::allocator
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
>;
template class flat_map
< test::movable_and_copyable_int
, test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, allocator
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
, small_vector< test_pair_t, 10, std::allocator< test_pair_t > >
>;
//flat_multimap
@@ -65,8 +59,21 @@ template class flat_multimap
< test::movable_and_copyable_int
, test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, test::simple_allocator
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
, stable_vector< test_pair_t, allocator< test_pair_t > >
>;
template class flat_multimap
< test::movable_and_copyable_int
, test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, deque<test_pair_t, test::simple_allocator< test_pair_t > >
>;
template class flat_multimap
< test::movable_and_copyable_int
, test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, static_vector<test_pair_t, 10 >
>;
//As flat container iterators are typedefs for vector::[const_]iterator,
@@ -74,6 +81,24 @@ template class flat_multimap
}} //boost::container
#if (__cplusplus > 201103L)
#include <vector>
namespace boost{
namespace container{
template class flat_map
< test::movable_and_copyable_int
, test::movable_and_copyable_int
, test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, std::vector<test_pair_t>
>;
} //container_detail {
}} //boost::container
#endif
class recursive_flat_map
{
@@ -337,39 +362,23 @@ bool flat_tree_extract_adopt_test()
}}}
template<class VoidAllocatorOrContainer, class ValueType, bool = boost::container::container_detail::is_container<VoidAllocatorOrContainer>::value>
struct RebindAllocatorOrContainer
{
typedef typename allocator_traits<VoidAllocatorOrContainer>
::template portable_rebind_alloc< std::pair<ValueType, ValueType> >::type type;
};
template<class SomeType, class ValueType, template <class> class Allocator>
struct RebindAllocatorOrContainer< boost::container::stable_vector<SomeType, Allocator<SomeType> >, ValueType, true>
{
typedef std::pair<ValueType, ValueType> type_t;
typedef typename allocator_traits< Allocator<SomeType> >
::template portable_rebind_alloc< type_t >::type allocator_t;
typedef typename boost::container::stable_vector<type_t, allocator_t> type;
};
template<class VoidAllocatorOrContainer>
struct GetMapContainer
{
template<class ValueType>
struct apply
{
typedef std::pair<ValueType, ValueType> type_t;
typedef flat_map< ValueType
, ValueType
, std::less<ValueType>
, typename RebindAllocatorOrContainer<VoidAllocatorOrContainer, ValueType>::type
, typename boost::container::container_detail::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
> map_type;
typedef flat_multimap< ValueType
, ValueType
, std::less<ValueType>
, typename RebindAllocatorOrContainer<VoidAllocatorOrContainer, ValueType>::type
, typename boost::container::container_detail::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
> multimap_type;
};
};

View File

@@ -9,9 +9,16 @@
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/detail/config_begin.hpp>
#include <set>
#include <boost/container/flat_set.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/container/deque.hpp>
#include <boost/container/static_vector.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/detail/container_or_allocator_rebind.hpp>
#include "print_container.hpp"
#include "dummy_test_allocator.hpp"
@@ -20,8 +27,6 @@
#include "propagate_allocator_test.hpp"
#include "emplace_test.hpp"
#include "container_common_tests.hpp"
#include <vector>
#include <boost/container/detail/flat_tree.hpp>
#include "../../intrusive/test/iterator_test.hpp"
using namespace boost::container;
@@ -41,20 +46,26 @@ template class flat_set
template class flat_set
< test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, allocator<test::movable_and_copyable_int>
, small_vector<test::movable_and_copyable_int, 10, allocator<test::movable_and_copyable_int> >
>;
//flat_multiset
template class flat_multiset
< test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, test::simple_allocator<test::movable_and_copyable_int>
, stable_vector<test::movable_and_copyable_int, test::simple_allocator<test::movable_and_copyable_int> >
>;
template class flat_multiset
< test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, allocator<test::movable_and_copyable_int>
, deque<test::movable_and_copyable_int, test::simple_allocator< test::movable_and_copyable_int > >
>;
template class flat_multiset
< test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, static_vector<test::movable_and_copyable_int, 10 >
>;
//As flat container iterators are typedefs for vector::[const_]iterator,
@@ -62,6 +73,24 @@ template class flat_multiset
}} //boost::container
#if (__cplusplus > 201103L)
#include <vector>
namespace boost{
namespace container{
template class flat_set
< test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int>
, std::vector<test::movable_and_copyable_int>
>;
} //container_detail {
}} //boost::container
#endif
//Test recursive structures
class recursive_flat_set
{
@@ -405,23 +434,20 @@ bool flat_tree_extract_adopt_test()
}}}
template<class VoidAllocator>
struct GetAllocatorSet
template<class VoidAllocatorOrContainer>
struct GetSetContainer
{
template<class ValueType>
struct apply
{
typedef flat_set < ValueType
, std::less<ValueType>
, typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc<ValueType>::type
, typename boost::container::container_detail::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type
> set_type;
typedef flat_multiset < ValueType
, std::less<ValueType>
, typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc<ValueType>::type
, typename boost::container::container_detail::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type
> multiset_type;
};
};
@@ -429,15 +455,15 @@ struct GetAllocatorSet
template<class VoidAllocator>
int test_set_variants()
{
typedef typename GetAllocatorSet<VoidAllocator>::template apply<int>::set_type MySet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_int>::set_type MyMoveSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_and_copyable_int>::set_type MyCopyMoveSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::copyable_int>::set_type MyCopySet;
typedef typename GetSetContainer<VoidAllocator>::template apply<int>::set_type MySet;
typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_int>::set_type MyMoveSet;
typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_and_copyable_int>::set_type MyCopyMoveSet;
typedef typename GetSetContainer<VoidAllocator>::template apply<test::copyable_int>::set_type MyCopySet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<int>::multiset_type MyMultiSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_int>::multiset_type MyMoveMultiSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_and_copyable_int>::multiset_type MyCopyMoveMultiSet;
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet;
typedef typename GetSetContainer<VoidAllocator>::template apply<int>::multiset_type MyMultiSet;
typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_int>::multiset_type MyMoveMultiSet;
typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_and_copyable_int>::multiset_type MyCopyMoveMultiSet;
typedef typename GetSetContainer<VoidAllocator>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet;
typedef std::set<int> MyStdSet;
typedef std::multiset<int> MyStdMultiSet;

View File

@@ -92,7 +92,7 @@ template class flat_tree
} //container_detail {
}} //boost::container
#if (__cplusplus >= 201402L)
#if (__cplusplus > 201103L)
#include <vector>
namespace boost{