mirror of
https://github.com/boostorg/multi_index.git
synced 2025-05-09 23:14:04 +00:00
449 lines
13 KiB
C++
449 lines
13 KiB
C++
/* Boost.MultiIndex test for composite_key.
|
|
*
|
|
* Copyright Joaquín M López Muñoz 2003-2004. Use, modification, and
|
|
* distribution are subject to 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/multi_index for library home page.
|
|
*/
|
|
|
|
#include "test_composite_key.hpp"
|
|
|
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
|
#include "pre_multi_index.hpp"
|
|
#include <boost/multi_index_container.hpp>
|
|
#include <boost/multi_index/composite_key.hpp>
|
|
#include <boost/multi_index/member.hpp>
|
|
#include <boost/multi_index/ordered_index.hpp>
|
|
#include <boost/test/test_tools.hpp>
|
|
|
|
using namespace boost::multi_index;
|
|
using namespace boost::tuples;
|
|
|
|
template<typename T>
|
|
struct is_composite_key_result
|
|
{
|
|
typedef char yes;
|
|
struct no{char m[2];};
|
|
|
|
static no test(void *);
|
|
|
|
template<typename CompositeKey>
|
|
static yes test(composite_key_result<CompositeKey>*);
|
|
|
|
static T* make();
|
|
|
|
BOOST_STATIC_CONSTANT(bool,value=(sizeof(test(make()))==sizeof(yes)));
|
|
};
|
|
|
|
template<typename CompositeKeyResult>
|
|
struct composite_key_result_length
|
|
{
|
|
BOOST_STATIC_CONSTANT(int,
|
|
value=boost::tuples::length<
|
|
BOOST_DEDUCED_TYPENAME
|
|
CompositeKeyResult::composite_key_type::key_extractor_tuple
|
|
>::value);
|
|
};
|
|
|
|
template<typename T>
|
|
struct composite_object_length
|
|
{
|
|
typedef typename boost::mpl::if_c<
|
|
is_composite_key_result<T>::value,
|
|
composite_key_result_length<T>,
|
|
boost::tuples::length<T>
|
|
>::type type;
|
|
|
|
BOOST_STATIC_CONSTANT(int,value=type::value);
|
|
};
|
|
|
|
template<typename CompositeKeyResult,typename T2>
|
|
struct comparison_equal_length
|
|
{
|
|
static bool is_less(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
composite_key_result_less<CompositeKeyResult> lt;
|
|
composite_key_result_greater<CompositeKeyResult> gt;
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
std::less<CompositeKeyResult> std_lt;
|
|
std::greater<CompositeKeyResult> std_gt;
|
|
#endif
|
|
|
|
return (x< y) && !(y< x)&&
|
|
!(x==y) && !(y==x)&&
|
|
(x!=y) && (y!=x)&&
|
|
!(x> y) && (y> x)&&
|
|
!(x>=y) && (y>=x)&&
|
|
(x<=y) && !(y<=x)&&
|
|
|
|
lt(x,y) && !lt(y,x)&&
|
|
!gt(x,y) && gt(y,x)
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
&&
|
|
std_lt(x,y) && !std_lt(y,x)&&
|
|
!std_gt(x,y) && std_gt(y,x)
|
|
#endif
|
|
;
|
|
}
|
|
|
|
static bool is_greater(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
composite_key_result_less<CompositeKeyResult> lt;
|
|
composite_key_result_greater<CompositeKeyResult> gt;
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
std::less<CompositeKeyResult> std_lt;
|
|
std::greater<CompositeKeyResult> std_gt;
|
|
#endif
|
|
|
|
return !(x< y) && (y< x)&&
|
|
!(x==y) && !(y==x)&&
|
|
(x!=y) && (y!=x)&&
|
|
(x> y) && !(y> x)&&
|
|
(x>=y) && !(y>=x)&&
|
|
!(x<=y) && (y<=x)&&
|
|
|
|
!lt(x,y) && lt(y,x)&&
|
|
gt(x,y) && !gt(y,x)
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
&&
|
|
!std_lt(x,y) && std_lt(y,x)&&
|
|
std_gt(x,y) && !std_gt(y,x)
|
|
#endif
|
|
;
|
|
}
|
|
|
|
static bool is_equiv(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
composite_key_result_less<CompositeKeyResult> lt;
|
|
composite_key_result_greater<CompositeKeyResult> gt;
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
std::less<CompositeKeyResult> std_lt;
|
|
std::greater<CompositeKeyResult> std_gt;
|
|
#endif
|
|
|
|
return !(x< y) && !(y< x)&&
|
|
(x==y) && (y==x)&&
|
|
!(x!=y) && !(y!=x)&&
|
|
!(x> y) && !(y> x)&&
|
|
(x>=y) && (y>=x)&&
|
|
(x<=y) && (y<=x)&&
|
|
|
|
!lt(x,y) && !lt(y,x)&&
|
|
!gt(x,y) && !gt(y,x)
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
&&
|
|
!std_lt(x,y) && !std_lt(y,x)&&
|
|
!std_gt(x,y) && !std_gt(y,x)
|
|
#endif
|
|
;
|
|
}
|
|
};
|
|
|
|
template<typename CompositeKeyResult,typename T2>
|
|
struct comparison_different_length
|
|
{
|
|
static bool is_less(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
composite_key_result_less<CompositeKeyResult> lt;
|
|
composite_key_result_greater<CompositeKeyResult> gt;
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
std::less<CompositeKeyResult> std_lt;
|
|
std::greater<CompositeKeyResult> std_gt;
|
|
#endif
|
|
|
|
return (x< y) && !(y< x)&&
|
|
!(x> y) && (y> x)&&
|
|
!(x>=y) && (y>=x)&&
|
|
(x<=y) && !(y<=x)&&
|
|
|
|
lt(x,y) && !lt(y,x)&&
|
|
!gt(x,y) && gt(y,x)
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
&&
|
|
std_lt(x,y) && !std_lt(y,x)&&
|
|
!std_gt(x,y) && std_gt(y,x)
|
|
#endif
|
|
;
|
|
}
|
|
|
|
static bool is_greater(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
composite_key_result_less<CompositeKeyResult> lt;
|
|
composite_key_result_greater<CompositeKeyResult> gt;
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
std::less<CompositeKeyResult> std_lt;
|
|
std::greater<CompositeKeyResult> std_gt;
|
|
#endif
|
|
|
|
return !(x< y) && (y< x)&&
|
|
(x> y) && !(y> x)&&
|
|
(x>=y) && !(y>=x)&&
|
|
!(x<=y) && (y<=x)&&
|
|
|
|
!lt(x,y) && lt(y,x)&&
|
|
gt(x,y) && !gt(y,x)
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
&&
|
|
!std_lt(x,y) && std_lt(y,x)&&
|
|
std_gt(x,y) && !std_gt(y,x)
|
|
#endif
|
|
;
|
|
}
|
|
|
|
static bool is_equiv(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
composite_key_result_less<CompositeKeyResult> lt;
|
|
composite_key_result_greater<CompositeKeyResult> gt;
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
std::less<CompositeKeyResult> std_lt;
|
|
std::greater<CompositeKeyResult> std_gt;
|
|
#endif
|
|
|
|
return !(x< y) && !(y< x)&&
|
|
!(x> y) && !(y> x)&&
|
|
(x>=y) && (y>=x)&&
|
|
(x<=y) && (y<=x)&&
|
|
|
|
!lt(x,y) && !lt(y,x)&&
|
|
!gt(x,y) && !gt(y,x)
|
|
|
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
&&
|
|
!std_lt(x,y) && !std_lt(y,x)&&
|
|
!std_gt(x,y) && !std_gt(y,x)
|
|
#endif
|
|
;
|
|
}
|
|
};
|
|
|
|
template<typename CompositeKeyResult,typename T2>
|
|
struct comparison_helper:
|
|
boost::mpl::if_c<
|
|
composite_key_result_length<CompositeKeyResult>::value==
|
|
composite_object_length<T2>::value,
|
|
comparison_equal_length<CompositeKeyResult,T2>,
|
|
comparison_different_length<CompositeKeyResult,T2>
|
|
>::type
|
|
{
|
|
};
|
|
|
|
template<typename CompositeKeyResult,typename T2>
|
|
static bool is_less(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
return comparison_helper<CompositeKeyResult,T2>::is_less(x,y);
|
|
}
|
|
|
|
template<typename CompositeKeyResult,typename T2>
|
|
static bool is_greater(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
return comparison_helper<CompositeKeyResult,T2>::is_greater(x,y);
|
|
}
|
|
|
|
template<typename CompositeKeyResult,typename T2>
|
|
static bool is_equiv(const CompositeKeyResult& x,const T2& y)
|
|
{
|
|
return comparison_helper<CompositeKeyResult,T2>::is_equiv(x,y);
|
|
}
|
|
|
|
template<typename T1,typename T2,typename Compare>
|
|
static bool is_less(const T1& x,const T2& y,const Compare& c)
|
|
{
|
|
return c(x,y)&&!c(y,x);
|
|
}
|
|
|
|
template<typename T1,typename T2,typename Compare>
|
|
static bool is_greater(const T1& x,const T2& y,const Compare& c)
|
|
{
|
|
return c(y,x)&&!c(x,y);
|
|
}
|
|
|
|
template<typename T1,typename T2,typename Compare>
|
|
static bool is_equiv(const T1& x,const T2& y,const Compare& c)
|
|
{
|
|
return !c(x,y)&&!c(y,x);
|
|
}
|
|
|
|
struct xyz
|
|
{
|
|
xyz(int x_=0,int y_=0,int z_=0):x(x_),y(y_),z(z_){}
|
|
|
|
int x;
|
|
int y;
|
|
int z;
|
|
};
|
|
|
|
void test_composite_key()
|
|
{
|
|
typedef composite_key<
|
|
xyz,
|
|
BOOST_MULTI_INDEX_MEMBER(xyz,int,x),
|
|
BOOST_MULTI_INDEX_MEMBER(xyz,int,y),
|
|
BOOST_MULTI_INDEX_MEMBER(xyz,int,z)
|
|
> ckey_t1;
|
|
|
|
typedef multi_index_container<
|
|
xyz,
|
|
indexed_by<
|
|
ordered_unique<
|
|
ckey_t1
|
|
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
,composite_key_result_less<ckey_t1::result_type>
|
|
#endif
|
|
>
|
|
>
|
|
> indexed_t;
|
|
|
|
indexed_t mc;
|
|
mc.insert(xyz(0,0,0));
|
|
mc.insert(xyz(0,0,1));
|
|
mc.insert(xyz(0,1,0));
|
|
mc.insert(xyz(0,1,1));
|
|
mc.insert(xyz(1,0,0));
|
|
mc.insert(xyz(1,0,1));
|
|
mc.insert(xyz(1,1,0));
|
|
mc.insert(xyz(1,1,1));
|
|
|
|
BOOST_CHECK(mc.size()==8);
|
|
BOOST_CHECK(
|
|
std::distance(
|
|
mc.find(mc.key_extractor()(xyz(0,0,0))),
|
|
mc.find(mc.key_extractor()(xyz(1,0,0))))==4);
|
|
BOOST_CHECK(
|
|
std::distance(
|
|
mc.find(make_tuple(0,0,0)),
|
|
mc.find(make_tuple(1,0,0)))==4);
|
|
BOOST_CHECK(
|
|
std::distance(
|
|
mc.lower_bound(make_tuple(0,0)),
|
|
mc.upper_bound(make_tuple(1,0)))==6);
|
|
|
|
ckey_t1 ck1;
|
|
ckey_t1 ck2(ck1);
|
|
ckey_t1 ck3(
|
|
boost::make_tuple(
|
|
BOOST_MULTI_INDEX_MEMBER(xyz,int,x)(),
|
|
BOOST_MULTI_INDEX_MEMBER(xyz,int,y)(),
|
|
BOOST_MULTI_INDEX_MEMBER(xyz,int,z)()));
|
|
ckey_t1 ck4(get<0>(ck1.key_extractors()));
|
|
|
|
get<2>(ck4.key_extractors())=
|
|
get<2>(ck2.key_extractors());
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0))));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0))));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0))));
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0)));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(1)));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(-1)));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0)));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,1)));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,-1)));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0)));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1)));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1)));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0,1)));
|
|
|
|
typedef composite_key_result_less<ckey_t1::result_type> ckey_comp_t1;
|
|
|
|
ckey_comp_t1 cp1;
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp1));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp1));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp1));
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp1));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(1),cp1));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(-1),cp1));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp1));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,1),cp1));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,-1),cp1));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp1));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1),cp1));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp1));
|
|
|
|
typedef composite_key_result_greater<ckey_t1::result_type> ckey_comp_t2;
|
|
|
|
ckey_comp_t2 cp2;
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp2));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp2));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp2));
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp2));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(1),cp2));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(-1),cp2));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp2));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,1),cp2));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,-1),cp2));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp2));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,1),cp2));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp2));
|
|
|
|
typedef composite_key_compare<
|
|
std::less<int>,
|
|
std::greater<int>, /* order reversed */
|
|
std::less<int>
|
|
> ckey_comp_t3;
|
|
|
|
ckey_comp_t3 cp3;
|
|
ckey_comp_t3 cp4(cp3);
|
|
ckey_comp_t3 cp5(
|
|
boost::make_tuple(
|
|
std::less<int>(),
|
|
std::greater<int>(),
|
|
std::less<int>()));
|
|
ckey_comp_t3 cp6(get<0>(cp3.key_comps()));
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp3));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp3));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp3));
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp3));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(1),cp3));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(-1),cp3));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp3));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,-1),cp3));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,1),cp3));
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp3));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1),cp3));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp3));
|
|
|
|
typedef composite_key<
|
|
xyz,
|
|
BOOST_MULTI_INDEX_MEMBER(xyz,int,y), /* members reversed */
|
|
BOOST_MULTI_INDEX_MEMBER(xyz,int,x)
|
|
> ckey_t2;
|
|
|
|
ckey_t2 ck5;
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0))));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0))));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0))));
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp1));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp1));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp1));
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp2));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp2));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp2));
|
|
|
|
BOOST_CHECK(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp3));
|
|
BOOST_CHECK(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp3));
|
|
BOOST_CHECK(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp3));
|
|
}
|