1 /* Boost.MultiIndex test for composite_key.
2  *
3  * Copyright 2003-2018 Joaquin M Lopez Munoz.
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  * See http://www.boost.org/libs/multi_index for library home page.
9  */
10 
11 #include "test_composite_key.hpp"
12 
13 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
14 #include <boost/detail/lightweight_test.hpp>
15 #include "pre_multi_index.hpp"
16 #include <boost/multi_index_container.hpp>
17 #include <boost/multi_index/composite_key.hpp>
18 #include <boost/multi_index/hashed_index.hpp>
19 #include <boost/multi_index/member.hpp>
20 #include <boost/multi_index/ordered_index.hpp>
21 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
22 #include <boost/preprocessor/repetition/enum_params.hpp>
23 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
24 
25 using namespace boost::multi_index;
26 using namespace boost::tuples;
27 
28 struct is_composite_key_result_helper
29 {
30   typedef char yes;
31   struct no{char m[2];};
32 
33   static no test(void*);
34 
35   template<typename CompositeKey>
36   static yes test(composite_key_result<CompositeKey>*);
37 };
38 
39 template<typename T>
40 struct is_composite_key_result
41 {
42   typedef is_composite_key_result_helper helper;
43 
44   BOOST_STATIC_CONSTANT(bool,
45     value=(
46       sizeof(helper::test((T*)0))==
47       sizeof(typename helper::yes)));
48 };
49 
50 template<typename CompositeKeyResult>
51 struct composite_key_result_length
52 {
53   BOOST_STATIC_CONSTANT(int,
54     value=boost::tuples::length<
55       BOOST_DEDUCED_TYPENAME
56       CompositeKeyResult::composite_key_type::key_extractor_tuple
57     >::value);
58 };
59 
60 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
61     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
62 struct is_boost_tuple_helper
63 {
64   typedef char yes;
65   struct no{char m[2];};
66 
67   static no test(void*);
68 
69   template<BOOST_PP_ENUM_PARAMS(10,typename T)>
70   static yes test(boost::tuple<BOOST_PP_ENUM_PARAMS(10,T)>*);
71 };
72 
73 template<typename T>
74 struct is_boost_tuple
75 {
76   typedef is_boost_tuple_helper helper;
77 
78   BOOST_STATIC_CONSTANT(bool,
79     value=(
80       sizeof(helper::test((T*)0))==
81       sizeof(typename helper::yes)));
82 };
83 
84 template<typename T>
85 struct composite_object_length
86 {
87   typedef typename boost::mpl::if_c<
88     is_composite_key_result<T>::value,
89     composite_key_result_length<T>,
90     typename boost::mpl::if_c<
91       is_boost_tuple<T>::value,
92       boost::tuples::length<T>,
93       std::tuple_size<T>
94     >::type
95   >::type type;
96 
97   BOOST_STATIC_CONSTANT(int,value=type::value);
98 };
99 #else
100 template<typename T>
101 struct composite_object_length
102 {
103   typedef typename boost::mpl::if_c<
104     is_composite_key_result<T>::value,
105     composite_key_result_length<T>,
106     boost::tuples::length<T>
107   >::type type;
108 
109   BOOST_STATIC_CONSTANT(int,value=type::value);
110 };
111 #endif
112 
113 template<typename CompositeKeyResult,typename T2>
114 struct comparison_equal_length
115 {
is_lesscomparison_equal_length116   static bool is_less(const CompositeKeyResult& x,const T2& y)
117   {
118     composite_key_result_equal_to<CompositeKeyResult> eq;
119     composite_key_result_less<CompositeKeyResult>     lt;
120     composite_key_result_greater<CompositeKeyResult>  gt;
121     std::equal_to<CompositeKeyResult>                 std_eq;
122     std::less<CompositeKeyResult>                     std_lt;
123     std::greater<CompositeKeyResult>                  std_gt;
124 
125     return  (x< y) && !(y< x)&&
126            !(x==y) && !(y==x)&&
127             (x!=y) &&  (y!=x)&&
128            !(x> y) &&  (y> x)&&
129            !(x>=y) &&  (y>=x)&&
130             (x<=y) && !(y<=x)&&
131           !eq(x,y) && !eq(y,x)&&
132            lt(x,y) && !lt(y,x)&&
133           !gt(x,y) &&  gt(y,x)&&
134       !std_eq(x,y) && !std_eq(y,x)&&
135        std_lt(x,y) && !std_lt(y,x)&&
136       !std_gt(x,y) &&  std_gt(y,x);
137   }
138 
is_greatercomparison_equal_length139   static bool is_greater(const CompositeKeyResult& x,const T2& y)
140   {
141     composite_key_result_equal_to<CompositeKeyResult> eq;
142     composite_key_result_less<CompositeKeyResult>     lt;
143     composite_key_result_greater<CompositeKeyResult>  gt;
144     std::equal_to<CompositeKeyResult>                 std_eq;
145     std::less<CompositeKeyResult>                     std_lt;
146     std::greater<CompositeKeyResult>                  std_gt;
147 
148     return !(x< y) &&  (y< x)&&
149            !(x==y) && !(y==x)&&
150             (x!=y) &&  (y!=x)&&
151             (x> y) && !(y> x)&&
152             (x>=y) && !(y>=x)&&
153            !(x<=y) &&  (y<=x)&&
154           !eq(x,y) && !eq(y,x)&&
155           !lt(x,y) &&  lt(y,x)&&
156            gt(x,y) && !gt(y,x)&&
157       !std_eq(x,y) && !std_eq(y,x)&&
158       !std_lt(x,y) &&  std_lt(y,x)&&
159        std_gt(x,y) && !std_gt(y,x);
160   }
161 
is_equivcomparison_equal_length162   static bool is_equiv(const CompositeKeyResult& x,const T2& y)
163   {
164     composite_key_result_equal_to<CompositeKeyResult> eq;
165     composite_key_result_less<CompositeKeyResult>     lt;
166     composite_key_result_greater<CompositeKeyResult>  gt;
167     std::equal_to<CompositeKeyResult>                 std_eq;
168     std::less<CompositeKeyResult>                     std_lt;
169     std::greater<CompositeKeyResult>                  std_gt;
170 
171     return !(x< y) && !(y< x)&&
172             (x==y) &&  (y==x)&&
173            !(x!=y) && !(y!=x)&&
174            !(x> y) && !(y> x)&&
175             (x>=y) &&  (y>=x)&&
176             (x<=y) &&  (y<=x)&&
177            eq(x,y) &&  eq(y,x)&&
178           !lt(x,y) && !lt(y,x)&&
179           !gt(x,y) && !gt(y,x)&&
180        std_eq(x,y) &&  std_eq(y,x)&&
181       !std_lt(x,y) && !std_lt(y,x)&&
182       !std_gt(x,y) && !std_gt(y,x);
183   }
184 };
185 
186 template<typename CompositeKeyResult,typename T2>
187 struct comparison_different_length
188 {
is_lesscomparison_different_length189   static bool is_less(const CompositeKeyResult& x,const T2& y)
190   {
191     composite_key_result_less<CompositeKeyResult>    lt;
192     composite_key_result_greater<CompositeKeyResult> gt;
193     std::less<CompositeKeyResult>                    std_lt;
194     std::greater<CompositeKeyResult>                 std_gt;
195 
196     return  (x< y) && !(y< x)&&
197            !(x> y) &&  (y> x)&&
198            !(x>=y) &&  (y>=x)&&
199             (x<=y) && !(y<=x)&&
200            lt(x,y) && !lt(y,x)&&
201           !gt(x,y) &&  gt(y,x)&&
202        std_lt(x,y) && !std_lt(y,x)&&
203       !std_gt(x,y) &&  std_gt(y,x);
204   }
205 
is_greatercomparison_different_length206   static bool is_greater(const CompositeKeyResult& x,const T2& y)
207   {
208     composite_key_result_less<CompositeKeyResult>    lt;
209     composite_key_result_greater<CompositeKeyResult> gt;
210     std::less<CompositeKeyResult>                    std_lt;
211     std::greater<CompositeKeyResult>                 std_gt;
212 
213     return !(x< y) &&  (y< x)&&
214             (x> y) && !(y> x)&&
215             (x>=y) && !(y>=x)&&
216            !(x<=y) &&  (y<=x)&&
217           !lt(x,y) &&  lt(y,x)&&
218            gt(x,y) && !gt(y,x)&&
219       !std_lt(x,y) && std_lt(y,x)&&
220        std_gt(x,y) && !std_gt(y,x);
221   }
222 
is_equivcomparison_different_length223   static bool is_equiv(const CompositeKeyResult& x,const T2& y)
224   {
225     composite_key_result_less<CompositeKeyResult>    lt;
226     composite_key_result_greater<CompositeKeyResult> gt;
227     std::less<CompositeKeyResult>                    std_lt;
228     std::greater<CompositeKeyResult>                 std_gt;
229 
230     return !(x< y) && !(y< x)&&
231            !(x> y) && !(y> x)&&
232             (x>=y) &&  (y>=x)&&
233             (x<=y) &&  (y<=x)&&
234           !lt(x,y) && !lt(y,x)&&
235           !gt(x,y) && !gt(y,x)&&
236       !std_lt(x,y) && !std_lt(y,x)&&
237       !std_gt(x,y) && !std_gt(y,x);
238   }
239 };
240 
241 template<typename CompositeKeyResult,typename T2>
242 struct comparison_helper:
243   boost::mpl::if_c<
244     composite_key_result_length<CompositeKeyResult>::value==
245       composite_object_length<T2>::value,
246     comparison_equal_length<CompositeKeyResult,T2>,
247     comparison_different_length<CompositeKeyResult,T2>
248   >::type
249 {
250 };
251 
252 template<typename CompositeKeyResult,typename T2>
is_less(const CompositeKeyResult & x,const T2 & y)253 static bool is_less(const CompositeKeyResult& x,const T2& y)
254 {
255   return comparison_helper<CompositeKeyResult,T2>::is_less(x,y);
256 }
257 
258 template<typename CompositeKeyResult,typename T2>
is_greater(const CompositeKeyResult & x,const T2 & y)259 static bool is_greater(const CompositeKeyResult& x,const T2& y)
260 {
261   return comparison_helper<CompositeKeyResult,T2>::is_greater(x,y);
262 }
263 
264 template<typename CompositeKeyResult,typename T2>
is_equiv(const CompositeKeyResult & x,const T2 & y)265 static bool is_equiv(const CompositeKeyResult& x,const T2& y)
266 {
267   return comparison_helper<CompositeKeyResult,T2>::is_equiv(x,y);
268 }
269 
270 template<typename T1,typename T2,typename Compare>
is_less(const T1 & x,const T2 & y,const Compare & c)271 static bool is_less(const T1& x,const T2& y,const Compare& c)
272 {
273   return c(x,y)&&!c(y,x);
274 }
275 
276 template<typename T1,typename T2,typename Compare>
is_greater(const T1 & x,const T2 & y,const Compare & c)277 static bool is_greater(const T1& x,const T2& y,const Compare& c)
278 {
279   return c(y,x)&&!c(x,y);
280 }
281 
282 template<typename T1,typename T2,typename Compare>
is_equiv(const T1 & x,const T2 & y,const Compare & c)283 static bool is_equiv(const T1& x,const T2& y,const Compare& c)
284 {
285   return !c(x,y)&&!c(y,x);
286 }
287 
288 template<typename T1,typename T2,typename Compare,typename Equiv>
is_less(const T1 & x,const T2 & y,const Compare & c,const Equiv & eq)289 static bool is_less(
290   const T1& x,const T2& y,const Compare& c,const Equiv& eq)
291 {
292   return c(x,y)&&!c(y,x)&&!eq(x,y)&&!eq(y,x);
293 }
294 
295 template<typename T1,typename T2,typename Compare,typename Equiv>
is_greater(const T1 & x,const T2 & y,const Compare & c,const Equiv & eq)296 static bool is_greater(
297   const T1& x,const T2& y,const Compare& c,const Equiv& eq)
298 {
299   return c(y,x)&&!c(x,y)&&!eq(x,y)&&!eq(y,x);
300 }
301 
302 template<typename T1,typename T2,typename Compare,typename Equiv>
is_equiv(const T1 & x,const T2 & y,const Compare & c,const Equiv & eq)303 static bool is_equiv(
304   const T1& x,const T2& y,const Compare& c,const Equiv& eq)
305 {
306   return !c(x,y)&&!c(y,x)&&eq(x,y)&&eq(y,x);
307 }
308 
309 struct xyz
310 {
xyzxyz311   xyz(int x_=0,int y_=0,int z_=0):x(x_),y(y_),z(z_){}
312 
313   int  x;
314   int  y;
315   int  z;
316 };
317 
318 struct modulo_equal
319 {
modulo_equalmodulo_equal320   modulo_equal(int i):i_(i){}
operator ()modulo_equal321   bool operator ()(int x,int y)const{return (x%i_)==(y%i_);}
322 
323 private:
324   int i_;
325 };
326 
327 struct xystr
328 {
xystrxystr329   xystr(int x_=0,int y_=0,std::string str_=0):x(x_),y(y_),str(str_){}
330 
331   int         x;
332   int         y;
333   std::string str;
334 };
335 
336 #define TUPLE_MAKER_CREATE(z,n,tuple)                   \
337 template<BOOST_PP_ENUM_PARAMS(n,typename T)>            \
338 static tuple<BOOST_PP_ENUM_PARAMS(n,T)>                 \
339 create(BOOST_PP_ENUM_BINARY_PARAMS(n,const T,& t)){     \
340   return tuple<BOOST_PP_ENUM_PARAMS(n,T)>(              \
341    BOOST_PP_ENUM_PARAMS(n,t));                          \
342 }
343 
344 #define DEFINE_TUPLE_MAKER(name,tuple)                  \
345 struct name                                             \
346 {                                                       \
347   static tuple<> create(){return tuple<>();}            \
348   BOOST_PP_REPEAT_FROM_TO(1,5,TUPLE_MAKER_CREATE,tuple) \
349 };
350 
DEFINE_TUPLE_MAKER(boost_tuple_maker,boost::tuple)351 DEFINE_TUPLE_MAKER(boost_tuple_maker,boost::tuple)
352 
353 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
354     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
355 DEFINE_TUPLE_MAKER(std_tuple_maker,std::tuple)
356 #endif
357 
358 #undef DEFINE_TUPLE_MAKER
359 #undef TUPLE_MAKER_CREATE
360 
361 template<typename TupleMaker>
362 void test_composite_key_template()
363 {
364   typedef composite_key<
365     xyz,
366     BOOST_MULTI_INDEX_MEMBER(xyz,int,x),
367     BOOST_MULTI_INDEX_MEMBER(xyz,int,y),
368     BOOST_MULTI_INDEX_MEMBER(xyz,int,z)
369   > ckey_t1;
370 
371   typedef multi_index_container<
372     xyz,
373     indexed_by<
374       ordered_unique<ckey_t1>
375     >
376   > indexed_t1;
377 
378   indexed_t1 mc1;
379   mc1.insert(xyz(0,0,0));
380   mc1.insert(xyz(0,0,1));
381   mc1.insert(xyz(0,1,0));
382   mc1.insert(xyz(0,1,1));
383   mc1.insert(xyz(1,0,0));
384   mc1.insert(xyz(1,0,1));
385   mc1.insert(xyz(1,1,0));
386   mc1.insert(xyz(1,1,1));
387 
388   BOOST_TEST(mc1.size()==8);
389   BOOST_TEST(
390     std::distance(
391       mc1.find(mc1.key_extractor()(xyz(0,0,0))),
392       mc1.find(mc1.key_extractor()(xyz(1,0,0))))==4);
393   BOOST_TEST(
394     std::distance(
395       mc1.find(TupleMaker::create(0,0,0)),
396       mc1.find(TupleMaker::create(1,0,0)))==4);
397   BOOST_TEST(
398     std::distance(
399       mc1.lower_bound(TupleMaker::create(0,0)),
400       mc1.upper_bound(TupleMaker::create(1,0)))==6);
401 
402 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
403   BOOST_TEST(
404     std::distance(
405       mc1.lower_bound(1),
406       mc1.upper_bound(1))==4);
407 #endif
408 
409   ckey_t1 ck1;
410   ckey_t1 ck2(ck1);
411   ckey_t1 ck3(
412     boost::make_tuple(
413       BOOST_MULTI_INDEX_MEMBER(xyz,int,x)(),
414       BOOST_MULTI_INDEX_MEMBER(xyz,int,y)(),
415       BOOST_MULTI_INDEX_MEMBER(xyz,int,z)()));
416   ckey_t1 ck4(get<0>(ck1.key_extractors()));
417 
418   (void)ck3; /* prevent unused var */
419 
420   get<2>(ck4.key_extractors())=
421     get<2>(ck2.key_extractors());
422 
423   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),ck2(xyz(0,0,0))));
424   BOOST_TEST(is_less   (ck1(xyz(0,0,1)),ck2(xyz(0,1,0))));
425   BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0))));
426 
427   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0)));
428   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(1)));
429   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1)));
430   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0)));
431   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(0,1)));
432   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,-1)));
433   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0)));
434   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1)));
435   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1)));
436   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0,1)));
437 
438   typedef composite_key_result_less<ckey_t1::result_type>     ckey_comp_t1;
439   typedef composite_key_result_equal_to<ckey_t1::result_type> ckey_eq_t1;
440 
441   ckey_comp_t1 cp1;
442   ckey_eq_t1   eq1;
443 
444   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp1,eq1));
445   BOOST_TEST(is_less   (ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp1,eq1));
446   BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp1,eq1));
447 
448   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0),cp1));
449   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(1),cp1));
450   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1),cp1));
451 
452 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
453   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),0,cp1));
454   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),1,cp1));
455   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),-1,cp1));
456 #endif
457 
458   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp1));
459   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp1));
460   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp1));
461   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp1,eq1));
462   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp1,eq1));
463   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp1,eq1));
464 
465   typedef composite_key_result_greater<ckey_t1::result_type> ckey_comp_t2;
466 
467   ckey_comp_t2 cp2;
468 
469   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp2));
470   BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp2));
471   BOOST_TEST(is_less   (ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp2));
472 
473   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0),cp2));
474   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(1),cp2));
475   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(-1),cp2));
476   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp2));
477   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp2));
478   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp2));
479   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp2));
480   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp2));
481   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp2));
482 
483   typedef composite_key_equal_to<
484     modulo_equal,
485     modulo_equal,
486     std::equal_to<int>,
487     std::equal_to<int>
488   > ckey_eq_t2;
489 
490   ckey_eq_t2 eq2(
491     boost::make_tuple(
492       modulo_equal(2),
493       modulo_equal(3),
494       std::equal_to<int>(),
495       std::equal_to<int>()));
496   ckey_eq_t2 eq3(eq2);
497   ckey_eq_t2 eq4(
498     get<0>(eq3.key_eqs()),
499     get<1>(eq3.key_eqs()));
500 
501   eq3=eq4; /* prevent unused var */
502   eq4=eq3; /* prevent unused var */
503 
504   BOOST_TEST( eq2(ck1(xyz(0,0,0)),ck1(xyz(0,0,0))));
505   BOOST_TEST(!eq2(ck1(xyz(0,1,0)),ck1(xyz(0,0,0))));
506   BOOST_TEST(!eq2(ck1(xyz(0,2,0)),ck1(xyz(0,0,0))));
507   BOOST_TEST( eq2(ck1(xyz(0,3,0)),ck1(xyz(0,0,0))));
508   BOOST_TEST(!eq2(ck1(xyz(1,0,0)),ck1(xyz(0,0,0))));
509   BOOST_TEST(!eq2(ck1(xyz(1,1,0)),ck1(xyz(0,0,0))));
510   BOOST_TEST(!eq2(ck1(xyz(1,2,0)),ck1(xyz(0,0,0))));
511   BOOST_TEST(!eq2(ck1(xyz(1,3,0)),ck1(xyz(0,0,0))));
512   BOOST_TEST( eq2(ck1(xyz(2,0,0)),ck1(xyz(0,0,0))));
513   BOOST_TEST(!eq2(ck1(xyz(2,1,0)),ck1(xyz(0,0,0))));
514   BOOST_TEST(!eq2(ck1(xyz(2,2,0)),ck1(xyz(0,0,0))));
515   BOOST_TEST( eq2(ck1(xyz(2,3,0)),ck1(xyz(0,0,0))));
516 
517   BOOST_TEST( eq2(TupleMaker::create(0,0,0),ck1(xyz(0,0,0))));
518   BOOST_TEST(!eq2(ck1(xyz(0,1,0))          ,TupleMaker::create(0,0,0)));
519   BOOST_TEST(!eq2(TupleMaker::create(0,2,0),ck1(xyz(0,0,0))));
520   BOOST_TEST( eq2(ck1(xyz(0,3,0))          ,TupleMaker::create(0,0,0)));
521   BOOST_TEST(!eq2(TupleMaker::create(1,0,0),ck1(xyz(0,0,0))));
522   BOOST_TEST(!eq2(ck1(xyz(1,1,0))          ,TupleMaker::create(0,0,0)));
523   BOOST_TEST(!eq2(TupleMaker::create(1,2,0),ck1(xyz(0,0,0))));
524   BOOST_TEST(!eq2(ck1(xyz(1,3,0))          ,TupleMaker::create(0,0,0)));
525   BOOST_TEST( eq2(TupleMaker::create(2,0,0),ck1(xyz(0,0,0))));
526   BOOST_TEST(!eq2(ck1(xyz(2,1,0))          ,TupleMaker::create(0,0,0)));
527   BOOST_TEST(!eq2(TupleMaker::create(2,2,0),ck1(xyz(0,0,0))));
528   BOOST_TEST( eq2(ck1(xyz(2,3,0))          ,TupleMaker::create(0,0,0)));
529 
530   typedef composite_key_compare<
531     std::less<int>,
532     std::greater<int>, /* order reversed */
533     std::less<int>
534   > ckey_comp_t3;
535 
536   ckey_comp_t3 cp3;
537   ckey_comp_t3 cp4(cp3);
538   ckey_comp_t3 cp5(
539     boost::make_tuple(
540       std::less<int>(),
541       std::greater<int>(),
542       std::less<int>()));
543   ckey_comp_t3 cp6(get<0>(cp3.key_comps()));
544 
545   cp4=cp5; /* prevent unused var */
546   cp5=cp6; /* prevent unused var */
547   cp6=cp4; /* prevent unused var */
548 
549   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp3));
550   BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp3));
551   BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp3));
552 
553   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0),cp3));
554   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(1),cp3));
555   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1),cp3));
556   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp3));
557   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp3));
558   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp3));
559   BOOST_TEST(is_equiv  (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp3));
560   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp3));
561   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp3));
562 
563   typedef composite_key<
564     xyz,
565     BOOST_MULTI_INDEX_MEMBER(xyz,int,y), /* members reversed */
566     BOOST_MULTI_INDEX_MEMBER(xyz,int,x)
567   > ckey_t2;
568 
569   ckey_t2 ck5;
570 
571   BOOST_TEST(is_equiv  (ck1(xyz(0,0,1)),ck5(xyz(0,0,0))));
572   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0))));
573   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0))));
574 
575   BOOST_TEST(is_equiv  (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp1));
576   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp1));
577   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp1));
578 
579   BOOST_TEST(is_equiv  (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp2));
580   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp2));
581   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp2));
582 
583   BOOST_TEST(is_equiv  (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp3));
584   BOOST_TEST(is_less   (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp3));
585   BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp3));
586 
587   typedef multi_index_container<
588     xyz,
589     indexed_by<
590       hashed_unique<ckey_t1>
591     >
592   > indexed_t2;
593 
594   indexed_t2 mc2;
595   mc2.insert(xyz(0,0,0));
596   mc2.insert(xyz(0,0,1));
597   mc2.insert(xyz(0,1,0));
598   mc2.insert(xyz(0,1,1));
599   mc2.insert(xyz(1,0,0));
600   mc2.insert(xyz(1,0,1));
601   mc2.insert(xyz(1,1,0));
602   mc2.insert(xyz(1,1,1));
603   mc2.insert(xyz(0,0,0));
604   mc2.insert(xyz(0,0,1));
605   mc2.insert(xyz(0,1,0));
606   mc2.insert(xyz(0,1,1));
607   mc2.insert(xyz(1,0,0));
608   mc2.insert(xyz(1,0,1));
609   mc2.insert(xyz(1,1,0));
610   mc2.insert(xyz(1,1,1));
611 
612   BOOST_TEST(mc2.size()==8);
613   BOOST_TEST(mc2.find(TupleMaker::create(0,0,1))->z==1);
614   BOOST_TEST(ck1(*(mc2.find(TupleMaker::create(1,0,1))))==
615              TupleMaker::create(1,0,1));
616 
617   typedef composite_key<
618     xystr,
619     BOOST_MULTI_INDEX_MEMBER(xystr,std::string,str),
620     BOOST_MULTI_INDEX_MEMBER(xystr,int,x),
621     BOOST_MULTI_INDEX_MEMBER(xystr,int,y)
622   > ckey_t3;
623 
624   ckey_t3 ck6;
625 
626   typedef composite_key_hash<
627     boost::hash<std::string>,
628     boost::hash<int>,
629     boost::hash<int>
630   > ckey_hash_t;
631 
632   ckey_hash_t ch1;
633   ckey_hash_t ch2(ch1);
634   ckey_hash_t ch3(
635     boost::make_tuple(
636       boost::hash<std::string>(),
637       boost::hash<int>(),
638       boost::hash<int>()));
639   ckey_hash_t ch4(get<0>(ch1.key_hash_functions()));
640 
641   ch2=ch3; /* prevent unused var */
642   ch3=ch4; /* prevent unused var */
643   ch4=ch2; /* prevent unused var */
644 
645   BOOST_TEST(
646     ch1(ck6(xystr(0,0,"hello")))==
647     ch1(TupleMaker::create(std::string("hello"),0,0)));
648   BOOST_TEST(
649     ch1(ck6(xystr(4,5,"world")))==
650     ch1(TupleMaker::create(std::string("world"),4,5)));
651 
652   typedef boost::hash<composite_key_result<ckey_t3> > ckeyres_hash_t;
653 
654   ckeyres_hash_t crh;
655 
656   BOOST_TEST(
657     ch1(ck6(xystr(0,0,"hello")))==crh(ck6(xystr(0,0,"hello"))));
658   BOOST_TEST(
659     ch1(ck6(xystr(4,5,"world")))==crh(ck6(xystr(4,5,"world"))));
660 }
661 
test_composite_key()662 void test_composite_key()
663 {
664   test_composite_key_template<boost_tuple_maker>();
665 
666 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
667     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
668   test_composite_key_template<std_tuple_maker>();
669 #endif
670 }
671