mirror of
https://github.com/boostorg/multi_index.git
synced 2025-05-09 23:14:04 +00:00
added partial merge functionality to key-based indices
plus fixed a compile-time error with legacy splice code when applied to different-type indices
This commit is contained in:
parent
4d15bf41fa
commit
dc480499a2
@ -331,9 +331,6 @@ protected:
|
||||
void final_delete_all_nodes_(){final().delete_all_nodes_();}
|
||||
void final_clear_(){final().clear_();}
|
||||
|
||||
template<typename Index>
|
||||
void final_transfer_range_(Index& x)
|
||||
{final_transfer_range_(x,x.begin(),x.end());}
|
||||
template<typename Index>
|
||||
void final_transfer_range_(
|
||||
Index& x,
|
||||
|
@ -238,11 +238,9 @@ protected:
|
||||
typedef typename call_traits<
|
||||
key_type>::param_type key_param_type;
|
||||
|
||||
/* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
|
||||
* expansion.
|
||||
*/
|
||||
/* needed to avoid commas in some macros */
|
||||
|
||||
typedef std::pair<iterator,bool> emplace_return_type;
|
||||
typedef std::pair<iterator,bool> pair_return_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -305,7 +303,7 @@ public:
|
||||
/* modifiers */
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
|
||||
emplace_return_type,emplace,emplace_impl)
|
||||
pair_return_type,emplace,emplace_impl)
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
|
||||
iterator,emplace_hint,emplace_hint_impl,iterator,position)
|
||||
@ -540,17 +538,69 @@ public:
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(ordered_index_impl,Index,void)
|
||||
merge(Index& x)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,x);
|
||||
BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
|
||||
if(x.end().get_node()!=this->header()){ /* different containers */
|
||||
this->final_transfer_range_(x);
|
||||
}
|
||||
merge(x,x.begin(),x.end());
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(ordered_index_impl,Index,void)
|
||||
merge(BOOST_RV_REF(Index) x){merge(static_cast<Index&>(x));}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(
|
||||
ordered_index_impl,Index,pair_return_type)
|
||||
merge(Index& x,BOOST_DEDUCED_TYPENAME Index::iterator i)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
|
||||
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
|
||||
BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
|
||||
if(x.end().get_node()==this->header()){ /* same container */
|
||||
return std::pair<iterator,bool>(
|
||||
make_iterator(static_cast<final_node_type*>(i.get_node())),true);
|
||||
}
|
||||
else{
|
||||
std::pair<final_node_type*,bool> p=this->final_transfer_(
|
||||
x,static_cast<final_node_type*>(i.get_node()));
|
||||
return std::pair<iterator,bool>(make_iterator(p.first),p.second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(
|
||||
ordered_index_impl,Index,pair_return_type)
|
||||
merge(BOOST_RV_REF(Index) x,BOOST_DEDUCED_TYPENAME Index::iterator i)
|
||||
{
|
||||
return merge(static_cast<Index&>(x),i);
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(ordered_index_impl,Index,void)
|
||||
merge(
|
||||
Index& x,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator first,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator last)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
|
||||
BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
|
||||
if(x.end().get_node()!=this->header()){ /* different containers */
|
||||
this->final_transfer_range_(x,first,last);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(ordered_index_impl,Index,void)
|
||||
merge(
|
||||
BOOST_RV_REF(Index) x,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator first,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator last)
|
||||
{
|
||||
merge(static_cast<Index&>(x),first,last);
|
||||
}
|
||||
|
||||
/* observers */
|
||||
|
||||
key_from_value key_extractor()const{return key;}
|
||||
|
@ -206,11 +206,9 @@ private:
|
||||
typedef typename call_traits<
|
||||
key_type>::param_type key_param_type;
|
||||
|
||||
/* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
|
||||
* expansion.
|
||||
*/
|
||||
/* needed to avoid commas in some macros */
|
||||
|
||||
typedef std::pair<iterator,bool> emplace_return_type;
|
||||
typedef std::pair<iterator,bool> pair_return_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -280,7 +278,7 @@ public:
|
||||
/* modifiers */
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
|
||||
emplace_return_type,emplace,emplace_impl)
|
||||
pair_return_type,emplace,emplace_impl)
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
|
||||
iterator,emplace_hint,emplace_hint_impl,iterator,position)
|
||||
@ -519,17 +517,67 @@ public:
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,void)
|
||||
merge(Index& x)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,x);
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
if(x.end().get_node()!=this->header()){ /* different containers */
|
||||
this->final_transfer_range_(x);
|
||||
}
|
||||
merge(x,x.begin(),x.end());
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,void)
|
||||
merge(BOOST_RV_REF(Index) x){merge(static_cast<Index&>(x));}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,pair_return_type)
|
||||
merge(Index& x,BOOST_DEDUCED_TYPENAME Index::iterator i)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
|
||||
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
if(x.end().get_node()==this->header()){ /* same container */
|
||||
return std::pair<iterator,bool>(
|
||||
make_iterator(static_cast<final_node_type*>(i.get_node())),true);
|
||||
}
|
||||
else{
|
||||
std::pair<final_node_type*,bool> p=this->final_transfer_(
|
||||
x,static_cast<final_node_type*>(i.get_node()));
|
||||
return std::pair<iterator,bool>(make_iterator(p.first),p.second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,pair_return_type)
|
||||
merge(BOOST_RV_REF(Index) x,BOOST_DEDUCED_TYPENAME Index::iterator i)
|
||||
{
|
||||
return merge(static_cast<Index&>(x),i);
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,void)
|
||||
merge(
|
||||
Index& x,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator first,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator last)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
|
||||
BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
|
||||
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
|
||||
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
|
||||
if(x.end().get_node()!=this->header()){ /* different containers */
|
||||
this->final_transfer_range_(x,first,last);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,void)
|
||||
merge(
|
||||
BOOST_RV_REF(Index) x,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator first,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator last)
|
||||
{
|
||||
merge(static_cast<Index&>(x),first,last);
|
||||
}
|
||||
|
||||
/* observers */
|
||||
|
||||
key_from_value key_extractor()const{return key;}
|
||||
|
@ -184,7 +184,7 @@ private:
|
||||
|
||||
/* needed to avoid commas in some macros */
|
||||
|
||||
typedef std::pair<iterator,bool> insertion_return_type;
|
||||
typedef std::pair<iterator,bool> pair_return_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -330,7 +330,7 @@ public:
|
||||
/* modifiers */
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
|
||||
insertion_return_type,emplace_front,emplace_front_impl)
|
||||
pair_return_type,emplace_front,emplace_front_impl)
|
||||
|
||||
std::pair<iterator,bool> push_front(const value_type& x)
|
||||
{return insert(begin(),x);}
|
||||
@ -339,7 +339,7 @@ public:
|
||||
void pop_front(){erase(begin());}
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
|
||||
insertion_return_type,emplace_back,emplace_back_impl)
|
||||
pair_return_type,emplace_back,emplace_back_impl)
|
||||
|
||||
std::pair<iterator,bool> push_back(const value_type& x)
|
||||
{return insert(end(),x);}
|
||||
@ -348,7 +348,7 @@ public:
|
||||
void pop_back(){erase(--end());}
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
|
||||
insertion_return_type,emplace,emplace_impl,iterator,position)
|
||||
pair_return_type,emplace,emplace_impl,iterator,position)
|
||||
|
||||
std::pair<iterator,bool> insert(iterator position,const value_type& x)
|
||||
{
|
||||
@ -557,7 +557,7 @@ public:
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(
|
||||
random_access_index,Index,insertion_return_type)
|
||||
random_access_index,Index,pair_return_type)
|
||||
splice(
|
||||
iterator position,Index& x,BOOST_DEDUCED_TYPENAME Index::iterator i)
|
||||
{
|
||||
@ -583,7 +583,7 @@ public:
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(
|
||||
random_access_index,Index,insertion_return_type)
|
||||
random_access_index,Index,pair_return_type)
|
||||
splice(
|
||||
iterator position,BOOST_RV_REF(Index) x,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator i)
|
||||
@ -1121,20 +1121,7 @@ private:
|
||||
/* backwards compatibility with old, non-transfer-based splice */
|
||||
|
||||
std::pair<iterator,bool> p=insert(position,*i);
|
||||
if(p.second){
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
/* MSVC++ 6.0 optimizer has a hard time with safe mode, and the
|
||||
* following workaround is needed. Left it for all compilers as it
|
||||
* does no harm.
|
||||
*/
|
||||
|
||||
i.detach();
|
||||
x.erase(x.make_iterator(i.get_node()));
|
||||
#else
|
||||
x.erase(i);
|
||||
#endif
|
||||
}
|
||||
if(p.second)x.erase(i);
|
||||
return std::pair<final_node_type*,bool>(
|
||||
static_cast<final_node_type*>(p.first.get_node()),p.second);
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ private:
|
||||
|
||||
/* needed to avoid commas in some macros */
|
||||
|
||||
typedef std::pair<iterator,bool> insertion_return_type;
|
||||
typedef std::pair<iterator,bool> pair_return_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -292,7 +292,7 @@ public:
|
||||
/* modifiers */
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
|
||||
insertion_return_type,emplace_front,emplace_front_impl)
|
||||
pair_return_type,emplace_front,emplace_front_impl)
|
||||
|
||||
std::pair<iterator,bool> push_front(const value_type& x)
|
||||
{return insert(begin(),x);}
|
||||
@ -301,7 +301,7 @@ public:
|
||||
void pop_front(){erase(begin());}
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
|
||||
insertion_return_type,emplace_back,emplace_back_impl)
|
||||
pair_return_type,emplace_back,emplace_back_impl)
|
||||
|
||||
std::pair<iterator,bool> push_back(const value_type& x)
|
||||
{return insert(end(),x);}
|
||||
@ -310,7 +310,7 @@ public:
|
||||
void pop_back(){erase(--end());}
|
||||
|
||||
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
|
||||
insertion_return_type,emplace,emplace_impl,iterator,position)
|
||||
pair_return_type,emplace,emplace_impl,iterator,position)
|
||||
|
||||
std::pair<iterator,bool> insert(iterator position,const value_type& x)
|
||||
{
|
||||
@ -508,7 +508,7 @@ public:
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(
|
||||
sequenced_index,Index,insertion_return_type)
|
||||
sequenced_index,Index,pair_return_type)
|
||||
splice(
|
||||
iterator position,Index& x,BOOST_DEDUCED_TYPENAME Index::iterator i)
|
||||
{
|
||||
@ -534,7 +534,7 @@ public:
|
||||
|
||||
template<typename Index>
|
||||
BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(
|
||||
sequenced_index,Index,insertion_return_type)
|
||||
sequenced_index,Index,pair_return_type)
|
||||
splice(
|
||||
iterator position,BOOST_RV_REF(Index) x,
|
||||
BOOST_DEDUCED_TYPENAME Index::iterator i)
|
||||
@ -1034,20 +1034,7 @@ private:
|
||||
/* backwards compatibility with old, non-transfer-based splice */
|
||||
|
||||
std::pair<iterator,bool> p=insert(position,*i);
|
||||
if(p.second){
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
/* MSVC++ 6.0 optimizer has a hard time with safe mode, and the
|
||||
* following workaround is needed. Left it for all compilers as it
|
||||
* does no harm.
|
||||
*/
|
||||
|
||||
i.detach();
|
||||
x.erase(x.make_iterator(i.get_node()));
|
||||
#else
|
||||
x.erase(i);
|
||||
#endif
|
||||
}
|
||||
if(p.second)x.erase(i);
|
||||
return std::pair<final_node_type*,bool>(
|
||||
static_cast<final_node_type*>(p.first.get_node()),p.second);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "count_allocator.hpp"
|
||||
@ -454,6 +455,44 @@ void merge(
|
||||
dst.splice(dst.end(),final_forward<Src>(src));
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
std::pair<typename Dst::iterator,bool> merge(
|
||||
Dst& dst,BOOST_FWD_REF(Src) src,
|
||||
typename boost::remove_reference<Src>::type::iterator i,
|
||||
typename enable_if_key_based<Dst>::type=0)
|
||||
{
|
||||
return dst.merge(final_forward<Src>(src),i);
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
std::pair<typename Dst::iterator,bool> merge(
|
||||
Dst& dst,BOOST_FWD_REF(Src) src,
|
||||
typename boost::remove_reference<Src>::type::iterator i,
|
||||
typename enable_if_not_key_based<Dst>::type=0)
|
||||
{
|
||||
return dst.splice(dst.end(),final_forward<Src>(src),i);
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
void merge(
|
||||
Dst& dst,BOOST_FWD_REF(Src) src,
|
||||
typename boost::remove_reference<Src>::type::iterator first,
|
||||
typename boost::remove_reference<Src>::type::iterator last,
|
||||
typename enable_if_key_based<Dst>::type=0)
|
||||
{
|
||||
dst.merge(final_forward<Src>(src),first,last);
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
void merge(
|
||||
Dst& dst,BOOST_FWD_REF(Src) src,
|
||||
typename boost::remove_reference<Src>::type::iterator first,
|
||||
typename boost::remove_reference<Src>::type::iterator last,
|
||||
typename enable_if_not_key_based<Dst>::type=0)
|
||||
{
|
||||
dst.splice(dst.end(),final_forward<Src>(src),first,last);
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
void test_merge_same(Dst& dst,BOOST_FWD_REF(Src) src)
|
||||
{
|
||||
@ -480,27 +519,160 @@ void test_merge_different(Dst& dst,BOOST_FWD_REF(Src) src)
|
||||
}
|
||||
|
||||
merge(dst,boost::forward<Src>(src));
|
||||
BOOST_TEST(dst.size()+src.size()==n+m);
|
||||
BOOST_TEST(dst.size()>=n && m>=src.size() && dst.size()-n==m-src.size());
|
||||
for(std::size_t i=0;i<v.size();++i){
|
||||
BOOST_TEST(&*(v[i].first)==v[i].second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
void test_merge_same(
|
||||
Dst& dst,BOOST_FWD_REF(Src) src,
|
||||
typename boost::remove_reference<Src>::type::iterator i,
|
||||
bool key_based=is_key_based<Dst>::value)
|
||||
{
|
||||
typedef typename Dst::iterator dst_iterator;
|
||||
|
||||
std::size_t n=dst.size();
|
||||
|
||||
std::pair<dst_iterator,bool> p=merge(dst,boost::forward<Src>(src),i);
|
||||
BOOST_TEST(dst.size()==n);
|
||||
BOOST_TEST(src.size()==n);
|
||||
BOOST_TEST(&*(p.first)==&*i && p.second);
|
||||
if(!key_based)BOOST_TEST(boost::next(p.first)==dst.end());
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
void test_merge_different(
|
||||
Dst& dst,BOOST_FWD_REF(Src) src,
|
||||
typename boost::remove_reference<Src>::type::iterator i,
|
||||
bool key_based=is_key_based<Dst>::value)
|
||||
{
|
||||
typedef typename Dst::iterator dst_iterator;
|
||||
|
||||
std::size_t n=dst.size(),m=src.size();
|
||||
const typename Dst::value_type* pi=&*i;
|
||||
|
||||
std::pair<dst_iterator,bool> p=merge(dst,boost::forward<Src>(src),i);
|
||||
BOOST_TEST(dst.size()+src.size()==n+m);
|
||||
BOOST_TEST(p.second?
|
||||
&*(p.first)==pi:
|
||||
&*(p.first)!=pi && *(p.first)==*i);
|
||||
if(!key_based)BOOST_TEST(!p.second || boost::next(p.first)==dst.end());
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
void test_merge_same(
|
||||
Dst& dst,BOOST_FWD_REF(Src) src,
|
||||
typename boost::remove_reference<Src>::type::iterator first,
|
||||
typename boost::remove_reference<Src>::type::iterator last,
|
||||
bool key_based=is_key_based<Dst>::value)
|
||||
{
|
||||
typedef typename Dst::iterator dst_iterator;
|
||||
typedef typename boost::remove_reference<Src>::
|
||||
type::iterator src_iterator;
|
||||
typedef typename boost::remove_reference<Src>::
|
||||
type::value_type src_value_type;
|
||||
|
||||
std::size_t n=dst.size(),d=std::distance(first,last);
|
||||
std::vector<const src_value_type*> v;
|
||||
for(src_iterator it=first;it!=last;++it)v.push_back(&*it);
|
||||
|
||||
merge(dst,boost::forward<Src>(src),first,last);
|
||||
BOOST_TEST(dst.size()==n);
|
||||
BOOST_TEST(src.size()==n);
|
||||
if(!key_based){
|
||||
dst_iterator it=boost::next(dst.begin(),dst.size()-d);
|
||||
for(std::size_t i=0;i<d;++i){
|
||||
BOOST_TEST(&*it++==v[i]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
src_iterator it=first;
|
||||
for(std::size_t i=0;i<d;++i){
|
||||
BOOST_TEST(&*it++==v[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Iterator,typename Value>
|
||||
bool find_address(Iterator first,Iterator last,const Value* x)
|
||||
{
|
||||
while(first!=last)if(&*first++==x)return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Dst,typename Src>
|
||||
void test_merge_different(
|
||||
Dst& dst,BOOST_FWD_REF(Src) src,
|
||||
typename boost::remove_reference<Src>::type::iterator first,
|
||||
typename boost::remove_reference<Src>::type::iterator last,
|
||||
bool key_based=is_key_based<Dst>::value)
|
||||
{
|
||||
typedef typename Dst::iterator dst_iterator;
|
||||
typedef typename boost::remove_reference<Src>::
|
||||
type::iterator src_iterator;
|
||||
typedef typename boost::remove_reference<Src>::
|
||||
type::value_type src_value_type;
|
||||
|
||||
std::size_t n=dst.size(),
|
||||
m=src.size(),
|
||||
d=std::distance(first,last);
|
||||
std::vector<const src_value_type*> v;
|
||||
for(src_iterator it=first;it!=last;++it)v.push_back(&*it);
|
||||
|
||||
merge(dst,boost::forward<Src>(src),first,last);
|
||||
BOOST_TEST(dst.size()>=n && m>=src.size() && dst.size()-n==m-src.size());
|
||||
if(!key_based){
|
||||
for(dst_iterator it=boost::next(dst.begin(),n);it!=dst.end();++it){
|
||||
BOOST_TEST(std::find(v.begin(),v.end(),&*it)!=v.end());
|
||||
}
|
||||
}
|
||||
for(std::size_t i=0;i<v.size();++i){
|
||||
BOOST_TEST(
|
||||
find_address(src.begin(),src.end(),v[i])||
|
||||
find_address(dst.begin(),dst.end(),v[i]));
|
||||
}
|
||||
}
|
||||
|
||||
template<int N,int M,typename Dst>
|
||||
void test_merge_same(Dst& dst)
|
||||
{
|
||||
Dst dst1=dst;
|
||||
test_merge_same(
|
||||
dst1.template get<N>(),dst1.template get<M>());
|
||||
test_merge_same(
|
||||
dst1.template get<N>(),boost::move(dst1.template get<M>()));
|
||||
const Dst dst1=dst;
|
||||
{
|
||||
Dst dst2=dst1;
|
||||
test_merge_same(
|
||||
dst2.template get<N>(),dst2.template get<M>());
|
||||
test_merge_same(
|
||||
dst2.template get<N>(),boost::move(dst2.template get<M>()));
|
||||
}
|
||||
{
|
||||
Dst dst2=dst1;
|
||||
test_merge_same(
|
||||
dst2.template get<N>(),dst2.template get<M>(),
|
||||
boost::next(dst2.template get<M>().begin(),dst2.size()/2));
|
||||
test_merge_same(
|
||||
dst2.template get<N>(),boost::move(dst2.template get<M>()),
|
||||
boost::next(dst2.template get<M>().begin(),dst2.size()/2));
|
||||
}
|
||||
{
|
||||
Dst dst2=dst1;
|
||||
test_merge_same(
|
||||
dst2.template get<N>(),dst2.template get<M>(),
|
||||
dst2.template get<M>().begin(),
|
||||
boost::next(dst2.template get<M>().begin(),dst2.size()/2));
|
||||
test_merge_same(
|
||||
dst2.template get<N>(),boost::move(dst2.template get<M>()),
|
||||
dst2.template get<M>().begin(),
|
||||
boost::next(dst2.template get<M>().begin(),dst2.size()/2));
|
||||
}
|
||||
}
|
||||
|
||||
template<int N,int M,typename Dst,typename Src>
|
||||
void test_merge_different(Dst& dst,Src& src)
|
||||
{
|
||||
Dst dst1=dst;
|
||||
Src src1=src;
|
||||
const Dst dst1=dst;
|
||||
const Src src1=src;
|
||||
{
|
||||
Dst dst2=dst1;
|
||||
Src src2=src1;
|
||||
@ -513,6 +685,36 @@ void test_merge_different(Dst& dst,Src& src)
|
||||
test_merge_different(
|
||||
dst2.template get<N>(),boost::move(src2.template get<M>()));
|
||||
}
|
||||
{
|
||||
Dst dst2=dst1;
|
||||
Src src2=src1;
|
||||
test_merge_different(
|
||||
dst2.template get<N>(),src2.template get<M>(),
|
||||
boost::next(src2.template get<M>().begin(),src2.size()/2));
|
||||
}
|
||||
{
|
||||
Dst dst2=dst1;
|
||||
Src src2=src1;
|
||||
test_merge_different(
|
||||
dst2.template get<N>(),boost::move(src2.template get<M>()),
|
||||
boost::next(src2.template get<M>().begin(),src2.size()/2));
|
||||
}
|
||||
{
|
||||
Dst dst2=dst1;
|
||||
Src src2=src1;
|
||||
test_merge_different(
|
||||
dst2.template get<N>(),src2.template get<M>(),
|
||||
src2.template get<M>().begin(),
|
||||
boost::next(src2.template get<M>().begin(),src2.size()/2));
|
||||
}
|
||||
{
|
||||
Dst dst2=dst1;
|
||||
Src src2=src1;
|
||||
test_merge_different(
|
||||
dst2.template get<N>(),boost::move(src2.template get<M>()),
|
||||
src2.template get<M>().begin(),
|
||||
boost::next(src2.template get<M>().begin(),src2.size()/2));
|
||||
}
|
||||
}
|
||||
|
||||
template<int N,int M,typename Dst,typename Src>
|
||||
@ -528,6 +730,14 @@ void test_merge(Dst& dst,Dst& src)
|
||||
else test_merge_different<N,M>(dst,src);
|
||||
}
|
||||
|
||||
struct another_int_hash
|
||||
{
|
||||
std::size_t operator()(int x)const
|
||||
{
|
||||
return boost::hash<int>()(x)*2;
|
||||
}
|
||||
};
|
||||
|
||||
void test_merge()
|
||||
{
|
||||
typedef multi_index_container<
|
||||
@ -544,8 +754,14 @@ void test_merge()
|
||||
typedef multi_index_container<
|
||||
int,
|
||||
indexed_by<
|
||||
ordered_unique<identity<int> >,
|
||||
hashed_unique<identity<int> >,
|
||||
ordered_unique<
|
||||
identity<int>,
|
||||
std::greater<int>
|
||||
>,
|
||||
hashed_unique<
|
||||
identity<int>,
|
||||
another_int_hash
|
||||
>,
|
||||
random_access<>,
|
||||
sequenced<>,
|
||||
ranked_unique<
|
||||
@ -557,7 +773,7 @@ void test_merge()
|
||||
|
||||
container1 c1;
|
||||
container2 c2;
|
||||
for(int i=0;i<5;++i){
|
||||
for(int i=0;i<10;++i){
|
||||
c1.insert(i);
|
||||
c2.insert(2*i);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user