Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / multi_index / test / test_composite_key.cpp
1 /* Boost.MultiIndex test for composite_key.
2  *
3  * Copyright 2003-2014 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 {
116   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
139   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
162   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 {
189   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
206   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
223   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>
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>
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>
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>
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>
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>
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>
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>
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>
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 {
311   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 {
320   modulo_equal(int i):i_(i){}
321   bool operator ()(int x,int y)const{return (x%i_)==(y%i_);}
322
323 private:
324   int i_;
325 };
326
327 struct xystr
328 {
329   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
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   ck3=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
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 }