/* Boost.MultiIndex test for composite_key. * * Copyright 2003-2018 Joaquin M Lopez Munoz. * 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/multi_index for library home page. */ #include "test_composite_key.hpp" #include /* keep it first to prevent nasty warns in MSVC */ #include #include "pre_multi_index.hpp" #include #include #include #include #include #include #include #include using namespace boost::multi_index; using namespace boost::tuples; struct is_composite_key_result_helper { typedef char yes; struct no{char m[2];}; static no test(void*); template static yes test(composite_key_result*); }; template struct is_composite_key_result { typedef is_composite_key_result_helper helper; BOOST_STATIC_CONSTANT(bool, value=( sizeof(helper::test((T*)0))== sizeof(typename helper::yes))); }; template struct composite_key_result_length { BOOST_STATIC_CONSTANT(int, value=boost::tuples::length< BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type::key_extractor_tuple >::value); }; #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) struct is_boost_tuple_helper { typedef char yes; struct no{char m[2];}; static no test(void*); template static yes test(boost::tuple*); }; template struct is_boost_tuple { typedef is_boost_tuple_helper helper; BOOST_STATIC_CONSTANT(bool, value=( sizeof(helper::test((T*)0))== sizeof(typename helper::yes))); }; template struct composite_object_length { typedef typename boost::mpl::if_c< is_composite_key_result::value, composite_key_result_length, typename boost::mpl::if_c< is_boost_tuple::value, boost::tuples::length, std::tuple_size >::type >::type type; BOOST_STATIC_CONSTANT(int,value=type::value); }; #else template struct composite_object_length { typedef typename boost::mpl::if_c< is_composite_key_result::value, composite_key_result_length, boost::tuples::length >::type type; BOOST_STATIC_CONSTANT(int,value=type::value); }; #endif template struct comparison_equal_length { static bool is_less(const CompositeKeyResult& x,const T2& y) { composite_key_result_equal_to eq; composite_key_result_less lt; composite_key_result_greater gt; std::equal_to std_eq; std::less std_lt; std::greater std_gt; 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)&& !eq(x,y) && !eq(y,x)&& lt(x,y) && !lt(y,x)&& !gt(x,y) && gt(y,x)&& !std_eq(x,y) && !std_eq(y,x)&& std_lt(x,y) && !std_lt(y,x)&& !std_gt(x,y) && std_gt(y,x); } static bool is_greater(const CompositeKeyResult& x,const T2& y) { composite_key_result_equal_to eq; composite_key_result_less lt; composite_key_result_greater gt; std::equal_to std_eq; std::less std_lt; std::greater std_gt; 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)&& !eq(x,y) && !eq(y,x)&& !lt(x,y) && lt(y,x)&& gt(x,y) && !gt(y,x)&& !std_eq(x,y) && !std_eq(y,x)&& !std_lt(x,y) && std_lt(y,x)&& std_gt(x,y) && !std_gt(y,x); } static bool is_equiv(const CompositeKeyResult& x,const T2& y) { composite_key_result_equal_to eq; composite_key_result_less lt; composite_key_result_greater gt; std::equal_to std_eq; std::less std_lt; std::greater std_gt; 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)&& eq(x,y) && eq(y,x)&& !lt(x,y) && !lt(y,x)&& !gt(x,y) && !gt(y,x)&& std_eq(x,y) && std_eq(y,x)&& !std_lt(x,y) && !std_lt(y,x)&& !std_gt(x,y) && !std_gt(y,x); } }; template struct comparison_different_length { static bool is_less(const CompositeKeyResult& x,const T2& y) { composite_key_result_less lt; composite_key_result_greater gt; std::less std_lt; std::greater std_gt; 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)&& std_lt(x,y) && !std_lt(y,x)&& !std_gt(x,y) && std_gt(y,x); } static bool is_greater(const CompositeKeyResult& x,const T2& y) { composite_key_result_less lt; composite_key_result_greater gt; std::less std_lt; std::greater std_gt; 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)&& !std_lt(x,y) && std_lt(y,x)&& std_gt(x,y) && !std_gt(y,x); } static bool is_equiv(const CompositeKeyResult& x,const T2& y) { composite_key_result_less lt; composite_key_result_greater gt; std::less std_lt; std::greater std_gt; 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)&& !std_lt(x,y) && !std_lt(y,x)&& !std_gt(x,y) && !std_gt(y,x); } }; template struct comparison_helper: boost::mpl::if_c< composite_key_result_length::value== composite_object_length::value, comparison_equal_length, comparison_different_length >::type { }; template static bool is_less(const CompositeKeyResult& x,const T2& y) { return comparison_helper::is_less(x,y); } template static bool is_greater(const CompositeKeyResult& x,const T2& y) { return comparison_helper::is_greater(x,y); } template static bool is_equiv(const CompositeKeyResult& x,const T2& y) { return comparison_helper::is_equiv(x,y); } template static bool is_less(const T1& x,const T2& y,const Compare& c) { return c(x,y)&&!c(y,x); } template static bool is_greater(const T1& x,const T2& y,const Compare& c) { return c(y,x)&&!c(x,y); } template static bool is_equiv(const T1& x,const T2& y,const Compare& c) { return !c(x,y)&&!c(y,x); } template static bool is_less( const T1& x,const T2& y,const Compare& c,const Equiv& eq) { return c(x,y)&&!c(y,x)&&!eq(x,y)&&!eq(y,x); } template static bool is_greater( const T1& x,const T2& y,const Compare& c,const Equiv& eq) { return c(y,x)&&!c(x,y)&&!eq(x,y)&&!eq(y,x); } template static bool is_equiv( const T1& x,const T2& y,const Compare& c,const Equiv& eq) { return !c(x,y)&&!c(y,x)&&eq(x,y)&&eq(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; }; struct modulo_equal { modulo_equal(int i):i_(i){} bool operator ()(int x,int y)const{return (x%i_)==(y%i_);} private: int i_; }; struct xystr { xystr(int x_=0,int y_=0,std::string str_=0):x(x_),y(y_),str(str_){} int x; int y; std::string str; }; #define TUPLE_MAKER_CREATE(z,n,tuple) \ template \ static tuple \ create(BOOST_PP_ENUM_BINARY_PARAMS(n,const T,& t)){ \ return tuple( \ BOOST_PP_ENUM_PARAMS(n,t)); \ } #define DEFINE_TUPLE_MAKER(name,tuple) \ struct name \ { \ static tuple<> create(){return tuple<>();} \ BOOST_PP_REPEAT_FROM_TO(1,5,TUPLE_MAKER_CREATE,tuple) \ }; DEFINE_TUPLE_MAKER(boost_tuple_maker,boost::tuple) #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) DEFINE_TUPLE_MAKER(std_tuple_maker,std::tuple) #endif #undef DEFINE_TUPLE_MAKER #undef TUPLE_MAKER_CREATE template void test_composite_key_template() { 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 > > indexed_t1; indexed_t1 mc1; mc1.insert(xyz(0,0,0)); mc1.insert(xyz(0,0,1)); mc1.insert(xyz(0,1,0)); mc1.insert(xyz(0,1,1)); mc1.insert(xyz(1,0,0)); mc1.insert(xyz(1,0,1)); mc1.insert(xyz(1,1,0)); mc1.insert(xyz(1,1,1)); BOOST_TEST(mc1.size()==8); BOOST_TEST( std::distance( mc1.find(mc1.key_extractor()(xyz(0,0,0))), mc1.find(mc1.key_extractor()(xyz(1,0,0))))==4); BOOST_TEST( std::distance( mc1.find(TupleMaker::create(0,0,0)), mc1.find(TupleMaker::create(1,0,0)))==4); BOOST_TEST( std::distance( mc1.lower_bound(TupleMaker::create(0,0)), mc1.upper_bound(TupleMaker::create(1,0)))==6); #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) BOOST_TEST( std::distance( mc1.lower_bound(1), mc1.upper_bound(1))==4); #endif 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())); (void)ck3; /* prevent unused var */ get<2>(ck4.key_extractors())= get<2>(ck2.key_extractors()); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)))); BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0)))); BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)))); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0))); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1))); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1))); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0))); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,1))); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,-1))); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0))); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1))); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1))); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0,1))); typedef composite_key_result_less ckey_comp_t1; typedef composite_key_result_equal_to ckey_eq_t1; ckey_comp_t1 cp1; ckey_eq_t1 eq1; BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp1,eq1)); BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp1,eq1)); BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp1,eq1)); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp1)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1),cp1)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1),cp1)); #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),0,cp1)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),1,cp1)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),-1,cp1)); #endif BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp1)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp1)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp1)); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp1,eq1)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp1,eq1)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp1,eq1)); typedef composite_key_result_greater ckey_comp_t2; ckey_comp_t2 cp2; BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp2)); BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp2)); BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp2)); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp2)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(1),cp2)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(-1),cp2)); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp2)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp2)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp2)); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp2)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp2)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp2)); typedef composite_key_equal_to< modulo_equal, modulo_equal, std::equal_to, std::equal_to > ckey_eq_t2; ckey_eq_t2 eq2( boost::make_tuple( modulo_equal(2), modulo_equal(3), std::equal_to(), std::equal_to())); ckey_eq_t2 eq3(eq2); ckey_eq_t2 eq4( get<0>(eq3.key_eqs()), get<1>(eq3.key_eqs())); eq3=eq4; /* prevent unused var */ eq4=eq3; /* prevent unused var */ BOOST_TEST( eq2(ck1(xyz(0,0,0)),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(0,1,0)),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(0,2,0)),ck1(xyz(0,0,0)))); BOOST_TEST( eq2(ck1(xyz(0,3,0)),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(1,0,0)),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(1,1,0)),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(1,2,0)),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(1,3,0)),ck1(xyz(0,0,0)))); BOOST_TEST( eq2(ck1(xyz(2,0,0)),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(2,1,0)),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(2,2,0)),ck1(xyz(0,0,0)))); BOOST_TEST( eq2(ck1(xyz(2,3,0)),ck1(xyz(0,0,0)))); BOOST_TEST( eq2(TupleMaker::create(0,0,0),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(0,1,0)) ,TupleMaker::create(0,0,0))); BOOST_TEST(!eq2(TupleMaker::create(0,2,0),ck1(xyz(0,0,0)))); BOOST_TEST( eq2(ck1(xyz(0,3,0)) ,TupleMaker::create(0,0,0))); BOOST_TEST(!eq2(TupleMaker::create(1,0,0),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(1,1,0)) ,TupleMaker::create(0,0,0))); BOOST_TEST(!eq2(TupleMaker::create(1,2,0),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(1,3,0)) ,TupleMaker::create(0,0,0))); BOOST_TEST( eq2(TupleMaker::create(2,0,0),ck1(xyz(0,0,0)))); BOOST_TEST(!eq2(ck1(xyz(2,1,0)) ,TupleMaker::create(0,0,0))); BOOST_TEST(!eq2(TupleMaker::create(2,2,0),ck1(xyz(0,0,0)))); BOOST_TEST( eq2(ck1(xyz(2,3,0)) ,TupleMaker::create(0,0,0))); typedef composite_key_compare< std::less, std::greater, /* order reversed */ std::less > ckey_comp_t3; ckey_comp_t3 cp3; ckey_comp_t3 cp4(cp3); ckey_comp_t3 cp5( boost::make_tuple( std::less(), std::greater(), std::less())); ckey_comp_t3 cp6(get<0>(cp3.key_comps())); cp4=cp5; /* prevent unused var */ cp5=cp6; /* prevent unused var */ cp6=cp4; /* prevent unused var */ BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp3)); BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp3)); BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp3)); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp3)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1),cp3)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1),cp3)); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp3)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp3)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp3)); BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp3)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp3)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(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_TEST(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)))); BOOST_TEST(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)))); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)))); BOOST_TEST(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp1)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp1)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp1)); BOOST_TEST(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp2)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp2)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp2)); BOOST_TEST(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp3)); BOOST_TEST(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp3)); BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp3)); typedef multi_index_container< xyz, indexed_by< hashed_unique > > indexed_t2; indexed_t2 mc2; mc2.insert(xyz(0,0,0)); mc2.insert(xyz(0,0,1)); mc2.insert(xyz(0,1,0)); mc2.insert(xyz(0,1,1)); mc2.insert(xyz(1,0,0)); mc2.insert(xyz(1,0,1)); mc2.insert(xyz(1,1,0)); mc2.insert(xyz(1,1,1)); mc2.insert(xyz(0,0,0)); mc2.insert(xyz(0,0,1)); mc2.insert(xyz(0,1,0)); mc2.insert(xyz(0,1,1)); mc2.insert(xyz(1,0,0)); mc2.insert(xyz(1,0,1)); mc2.insert(xyz(1,1,0)); mc2.insert(xyz(1,1,1)); BOOST_TEST(mc2.size()==8); BOOST_TEST(mc2.find(TupleMaker::create(0,0,1))->z==1); BOOST_TEST(ck1(*(mc2.find(TupleMaker::create(1,0,1))))== TupleMaker::create(1,0,1)); typedef composite_key< xystr, BOOST_MULTI_INDEX_MEMBER(xystr,std::string,str), BOOST_MULTI_INDEX_MEMBER(xystr,int,x), BOOST_MULTI_INDEX_MEMBER(xystr,int,y) > ckey_t3; ckey_t3 ck6; typedef composite_key_hash< boost::hash, boost::hash, boost::hash > ckey_hash_t; ckey_hash_t ch1; ckey_hash_t ch2(ch1); ckey_hash_t ch3( boost::make_tuple( boost::hash(), boost::hash(), boost::hash())); ckey_hash_t ch4(get<0>(ch1.key_hash_functions())); ch2=ch3; /* prevent unused var */ ch3=ch4; /* prevent unused var */ ch4=ch2; /* prevent unused var */ BOOST_TEST( ch1(ck6(xystr(0,0,"hello")))== ch1(TupleMaker::create(std::string("hello"),0,0))); BOOST_TEST( ch1(ck6(xystr(4,5,"world")))== ch1(TupleMaker::create(std::string("world"),4,5))); typedef boost::hash > ckeyres_hash_t; ckeyres_hash_t crh; BOOST_TEST( ch1(ck6(xystr(0,0,"hello")))==crh(ck6(xystr(0,0,"hello")))); BOOST_TEST( ch1(ck6(xystr(4,5,"world")))==crh(ck6(xystr(4,5,"world")))); } void test_composite_key() { test_composite_key_template(); #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) test_composite_key_template(); #endif }