1 /* Boost.MultiIndex test for key extractors.
2  *
3  * Copyright 2003-2015 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_key_extractors.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/key_extractors.hpp>
17 #include <boost/ref.hpp>
18 #include <boost/scoped_ptr.hpp>
19 #include <list>
20 
21 using namespace boost::multi_index;
22 using namespace boost::tuples;
23 
24 struct test_class
25 {
26   int       int_member;
27   const int int_cmember;
28 
bool_mem_fun_consttest_class29   bool bool_mem_fun_const()const{return true;}
bool_mem_funtest_class30   bool bool_mem_fun(){return false;}
31 
bool_global_funtest_class32   static bool bool_global_fun(test_class){return true;}
bool_global_fun_const_reftest_class33   static bool bool_global_fun_const_ref(const test_class&){return false;}
bool_global_fun_reftest_class34   static bool bool_global_fun_ref(test_class&){return true;}
35 
test_classtest_class36   test_class(int i=0):int_member(i),int_cmember(i){}
test_classtest_class37   test_class(int i,int j):int_member(i),int_cmember(j){}
38 
operator =test_class39   test_class& operator=(const test_class& x)
40   {
41     int_member=x.int_member;
42     return *this;
43   }
44 
operator <test_class45   bool operator<(const test_class& x)const
46   {
47     if(int_member<x.int_member)return true;
48     if(x.int_member<int_member)return false;
49     return int_cmember<x.int_cmember;
50   }
51 
operator ==test_class52   bool operator==(const test_class& x)const
53   {
54     return int_member==x.int_member&&int_cmember==x.int_cmember;
55   }
56 };
57 
58 struct test_derived_class:test_class
59 {
test_derived_classtest_derived_class60   test_derived_class(int i=0):test_class(i){}
test_derived_classtest_derived_class61   test_derived_class(int i,int j):test_class(i,j){}
62 };
63 
64 typedef identity<test_class>                                       idn;
65 typedef identity<const test_class>                                 cidn;
66 typedef BOOST_MULTI_INDEX_MEMBER(test_class,int,int_member)        key_m;
67 typedef BOOST_MULTI_INDEX_MEMBER(test_class,const int,int_member)  ckey_m;
68 typedef BOOST_MULTI_INDEX_MEMBER(test_class,const int,int_cmember) key_cm;
69 typedef BOOST_MULTI_INDEX_CONST_MEM_FUN(
70           test_class,bool,bool_mem_fun_const)                      key_cmf;
71 typedef BOOST_MULTI_INDEX_MEM_FUN(test_class,bool,bool_mem_fun)    key_mf;
72 typedef global_fun<test_class,bool,&test_class::bool_global_fun>   key_gf;
73 typedef global_fun<
74           const test_class&,bool,
75           &test_class::bool_global_fun_const_ref
76         >                                                          key_gcrf;
77 typedef global_fun<
78           test_class&,bool,
79           &test_class::bool_global_fun_ref
80         >                                                          key_grf;
81 typedef composite_key<
82           test_class,
83           idn,
84           key_m,
85           key_cm,
86           key_cmf
87         >                                                          compkey;
88 typedef composite_key<
89           test_class,
90           cidn,
91           ckey_m
92         >                                                          ccompkey;
93 typedef composite_key<
94           boost::reference_wrapper<test_class>,
95           key_mf
96         >                                                          ccompw_key;
97 
98 #if !defined(BOOST_NO_SFINAE)
99 /* testcases for problems with non-copyable classes reported at
100  * http://lists.boost.org/Archives/boost/2006/04/103065.php
101  */
102 
103 struct test_nc_class
104 {
105   int       int_member;
106   const int int_cmember;
107 
bool_mem_fun_consttest_nc_class108   bool bool_mem_fun_const()const{return true;}
bool_mem_funtest_nc_class109   bool bool_mem_fun(){return false;}
110 
bool_global_fun_const_reftest_nc_class111   static bool bool_global_fun_const_ref(const test_nc_class&){return false;}
bool_global_fun_reftest_nc_class112   static bool bool_global_fun_ref(test_nc_class&){return true;}
113 
test_nc_classtest_nc_class114   test_nc_class(int i=0):int_member(i),int_cmember(i){}
test_nc_classtest_nc_class115   test_nc_class(int i,int j):int_member(i),int_cmember(j){}
116 
operator ==test_nc_class117   bool operator==(const test_nc_class& x)const
118   {
119     return int_member==x.int_member&&int_cmember==x.int_cmember;
120   }
121 
122 private:
123   test_nc_class(const test_nc_class&);
124   test_nc_class& operator=(const test_nc_class&);
125 };
126 
127 struct test_nc_derived_class:test_nc_class
128 {
test_nc_derived_classtest_nc_derived_class129   test_nc_derived_class(int i=0):test_nc_class(i){}
test_nc_derived_classtest_nc_derived_class130   test_nc_derived_class(int i,int j):test_nc_class(i,j){}
131 };
132 
133 typedef identity<test_nc_class>                                nc_idn;
134 typedef identity<const test_nc_class>                          nc_cidn;
135 typedef BOOST_MULTI_INDEX_MEMBER(test_nc_class,int,int_member) nc_key_m;
136 typedef BOOST_MULTI_INDEX_MEMBER(
137           test_nc_class,const int,int_member)                  nc_ckey_m;
138 typedef BOOST_MULTI_INDEX_CONST_MEM_FUN(
139           test_nc_class,bool,bool_mem_fun_const)               nc_key_cmf;
140 typedef BOOST_MULTI_INDEX_MEM_FUN(
141           test_nc_class,bool,bool_mem_fun)                     nc_key_mf;
142 typedef global_fun<
143           const test_nc_class&,bool,
144           &test_nc_class::bool_global_fun_const_ref
145         >                                                      nc_key_gcrf;
146 typedef global_fun<
147           test_nc_class&,bool,
148           &test_nc_class::bool_global_fun_ref
149         >                                                      nc_key_grf;
150 typedef composite_key<
151           test_nc_class,
152           nc_idn,
153           nc_key_m,
154           nc_ckey_m,
155           nc_key_cmf
156         >                                                      nc_compkey;
157 #endif
158 
test_key_extractors()159 void test_key_extractors()
160 {
161   idn        id;
162   cidn       cid;
163   key_m      k_m;
164   ckey_m     ck_m;
165   key_cm     k_cm;
166   key_cmf    k_cmf;
167   key_mf     k_mf;
168   key_gf     k_gf;
169   key_gcrf   k_gcrf;
170   key_grf    k_grf;
171   compkey    cmpk;
172   ccompkey   ccmpk;
173   ccompw_key ccmpk_w;
174 
175   test_derived_class                         td(-1,0);
176   const test_derived_class&                  ctdr=td;
177 
178   test_class&                                tr=td;
179   const test_class&                          ctr=tr;
180 
181   test_derived_class*                        tdp=&td;
182   const test_derived_class*                  ctdp=&ctdr;
183 
184   test_class*                                tp=&tr;
185   const test_class*                          ctp=&tr;
186 
187   test_class**                               tpp=&tp;
188   const test_class**                         ctpp=&ctp;
189 
190   boost::scoped_ptr<test_class*>             tap(new test_class*(tp));
191   boost::scoped_ptr<const test_class*>       ctap(new const test_class*(ctp));
192 
193   boost::reference_wrapper<test_class>       tw(tr);
194   boost::reference_wrapper<const test_class> ctw(tr);
195 
196   id(tr).int_member=0;
197   BOOST_TEST(id(tr).int_member==0);
198   BOOST_TEST(cid(tr).int_member==0);
199   BOOST_TEST(k_m(tr)==0);
200   BOOST_TEST(ck_m(tr)==0);
201   BOOST_TEST(cmpk(tr)==make_tuple(test_class(0,0),0,0,true));
202   BOOST_TEST(ccmpk(tr)==make_tuple(test_class(0,0),0));
203   BOOST_TEST(id(ctr).int_member==0);
204   BOOST_TEST(cid(ctr).int_member==0);
205   BOOST_TEST(k_m(ctr)==0);
206   BOOST_TEST(ck_m(ctr)==0);
207   BOOST_TEST(cmpk(ctr)==make_tuple(test_class(0,0),0,0,true));
208   BOOST_TEST(ccmpk(ctr)==make_tuple(test_class(0,0),0));
209 
210 #if !defined(BOOST_NO_SFINAE)
211   BOOST_TEST(id(td).int_member==0);
212   BOOST_TEST(cid(td).int_member==0);
213   BOOST_TEST(k_m(td)==0);
214   BOOST_TEST(ck_m(td)==0);
215   BOOST_TEST(cmpk(td)==make_tuple(test_class(0,0),0,0,true));
216   BOOST_TEST(ccmpk(td)==make_tuple(test_class(0,0),0));
217   BOOST_TEST(id(ctdr).int_member==0);
218   BOOST_TEST(cid(ctdr).int_member==0);
219   BOOST_TEST(k_m(ctdr)==0);
220   BOOST_TEST(ck_m(ctdr)==0);
221   BOOST_TEST(cmpk(ctdr)==make_tuple(test_class(0,0),0,0,true));
222   BOOST_TEST(ccmpk(ctdr)==make_tuple(test_class(0,0),0));
223 #endif
224 
225   k_m(tr)=1;
226   BOOST_TEST(id(tp).int_member==1);
227   BOOST_TEST(cid(tp).int_member==1);
228   BOOST_TEST(k_m(tp)==1);
229   BOOST_TEST(ck_m(tp)==1);
230   BOOST_TEST(cmpk(tp)==make_tuple(test_class(1,0),1,0,true));
231   BOOST_TEST(ccmpk(tp)==make_tuple(test_class(1,0),1));
232   BOOST_TEST(cid(ctp).int_member==1);
233   BOOST_TEST(ck_m(ctp)==1);
234   BOOST_TEST(cmpk(ctp)==make_tuple(test_class(1,0),1,0,true));
235   BOOST_TEST(ccmpk(ctp)==make_tuple(test_class(1,0),1));
236 
237 #if !defined(BOOST_NO_SFINAE)
238   BOOST_TEST(id(tdp).int_member==1);
239   BOOST_TEST(cid(tdp).int_member==1);
240   BOOST_TEST(k_m(tdp)==1);
241   BOOST_TEST(ck_m(tdp)==1);
242   BOOST_TEST(cmpk(tdp)==make_tuple(test_class(1,0),1,0,true));
243   BOOST_TEST(ccmpk(tdp)==make_tuple(test_class(1,0),1));
244   BOOST_TEST(cid(ctdp).int_member==1);
245   BOOST_TEST(ck_m(ctdp)==1);
246   BOOST_TEST(cmpk(ctdp)==make_tuple(test_class(1,0),1,0,true));
247   BOOST_TEST(ccmpk(ctdp)==make_tuple(test_class(1,0),1));
248 #endif
249 
250   k_m(tp)=2;
251   BOOST_TEST(id(tpp).int_member==2);
252   BOOST_TEST(cid(tpp).int_member==2);
253   BOOST_TEST(k_m(tpp)==2);
254   BOOST_TEST(ck_m(tpp)==2);
255   BOOST_TEST(cmpk(tpp)==make_tuple(test_class(2,0),2,0,true));
256   BOOST_TEST(ccmpk(tpp)==make_tuple(test_class(2,0),2));
257   BOOST_TEST(cid(ctpp).int_member==2);
258   BOOST_TEST(ck_m(ctpp)==2);
259   BOOST_TEST(cmpk(ctpp)==make_tuple(test_class(2,0),2,0,true));
260   BOOST_TEST(ccmpk(ctpp)==make_tuple(test_class(2,0),2));
261 
262   k_m(tpp)=3;
263   BOOST_TEST(id(tap).int_member==3);
264   BOOST_TEST(cid(tap).int_member==3);
265   BOOST_TEST(k_m(tap)==3);
266   BOOST_TEST(ck_m(tap)==3);
267   BOOST_TEST(cmpk(tap)==make_tuple(test_class(3,0),3,0,true));
268   BOOST_TEST(ccmpk(tap)==make_tuple(test_class(3,0),3));
269   BOOST_TEST(cid(ctap).int_member==3);
270   BOOST_TEST(ck_m(ctap)==3);
271   BOOST_TEST(cmpk(ctap)==make_tuple(test_class(3,0),3,0,true));
272   BOOST_TEST(ccmpk(ctap)==make_tuple(test_class(3,0),3));
273 
274   k_m(tap)=4;
275   BOOST_TEST(id(tw).int_member==4);
276   BOOST_TEST(cid(tw).int_member==4);
277   BOOST_TEST(k_m(tw)==4);
278   BOOST_TEST(ck_m(tw)==4);
279   BOOST_TEST(cmpk(tw)==make_tuple(test_class(4,0),4,0,true));
280   BOOST_TEST(ccmpk(tw)==make_tuple(test_class(4,0),4));
281 
282   k_m(tw)=5;
283   BOOST_TEST(id(ctw).int_member==5);
284   BOOST_TEST(cid(ctw).int_member==5);
285   BOOST_TEST(k_m(ctw)==5);
286   BOOST_TEST(ck_m(ctw)==5);
287   BOOST_TEST(cmpk(ctw)==make_tuple(test_class(5,0),5,0,true));
288   BOOST_TEST(ccmpk(ctw)==make_tuple(test_class(5,0),5));
289 
290   BOOST_TEST(k_cm(tr)==0);
291   BOOST_TEST(k_cm(ctr)==0);
292 
293 #if !defined(BOOST_NO_SFINAE)
294   BOOST_TEST(k_cm(td)==0);
295   BOOST_TEST(k_cm(ctdr)==0);
296 #endif
297 
298   BOOST_TEST(k_cm(tp)==0);
299   BOOST_TEST(k_cm(ctp)==0);
300 
301 #if !defined(BOOST_NO_SFINAE)
302   BOOST_TEST(k_cm(tdp)==0);
303   BOOST_TEST(k_cm(ctdp)==0);
304 #endif
305 
306   BOOST_TEST(k_cm(tpp)==0);
307   BOOST_TEST(k_cm(ctpp)==0);
308   BOOST_TEST(k_cm(tap)==0);
309   BOOST_TEST(k_cm(ctap)==0);
310 
311   BOOST_TEST(k_cm(tw)==0);
312   BOOST_TEST(k_cm(ctw)==0);
313 
314   BOOST_TEST(k_cmf(tr));
315   BOOST_TEST(k_cmf(ctr));
316 
317 #if !defined(BOOST_NO_SFINAE)
318   BOOST_TEST(k_cmf(td));
319   BOOST_TEST(k_cmf(ctdr));
320 #endif
321 
322   BOOST_TEST(k_cmf(tp));
323   BOOST_TEST(k_cmf(ctp));
324 
325 #if !defined(BOOST_NO_SFINAE)
326   BOOST_TEST(k_cmf(tdp));
327   BOOST_TEST(k_cmf(ctdp));
328 #endif
329 
330   BOOST_TEST(k_cmf(tpp));
331   BOOST_TEST(k_cmf(ctpp));
332   BOOST_TEST(k_cmf(tap));
333   BOOST_TEST(k_cmf(ctap));
334 
335   BOOST_TEST(k_cmf(tw));
336   BOOST_TEST(k_cmf(ctw));
337 
338   BOOST_TEST(!k_mf(tr));
339 
340 #if !defined(BOOST_NO_SFINAE)
341   BOOST_TEST(!k_mf(td));
342 #endif
343 
344   BOOST_TEST(!k_mf(tp));
345 
346 #if !defined(BOOST_NO_SFINAE)
347   BOOST_TEST(!k_mf(tdp));
348 #endif
349 
350   BOOST_TEST(!k_mf(tpp));
351   BOOST_TEST(!k_mf(tap));
352   BOOST_TEST(!k_mf(tw));
353 
354   BOOST_TEST(k_gf(tr));
355   BOOST_TEST(k_gf(ctr));
356 
357 #if !defined(BOOST_NO_SFINAE)
358   BOOST_TEST(k_gf(td));
359   BOOST_TEST(k_gf(ctdr));
360 #endif
361 
362   BOOST_TEST(k_gf(tp));
363   BOOST_TEST(k_gf(ctp));
364 
365 #if !defined(BOOST_NO_SFINAE)
366   BOOST_TEST(k_gf(tdp));
367   BOOST_TEST(k_gf(ctdp));
368 #endif
369 
370   BOOST_TEST(k_gf(tpp));
371   BOOST_TEST(k_gf(ctpp));
372   BOOST_TEST(k_gf(tap));
373   BOOST_TEST(k_gf(ctap));
374 
375   BOOST_TEST(k_gf(tw));
376   BOOST_TEST(k_gf(ctw));
377 
378   BOOST_TEST(!k_gcrf(tr));
379   BOOST_TEST(!k_gcrf(ctr));
380 
381 #if !defined(BOOST_NO_SFINAE)
382   BOOST_TEST(!k_gcrf(td));
383   BOOST_TEST(!k_gcrf(ctdr));
384 #endif
385 
386   BOOST_TEST(!k_gcrf(tp));
387   BOOST_TEST(!k_gcrf(ctp));
388 
389 #if !defined(BOOST_NO_SFINAE)
390   BOOST_TEST(!k_gcrf(tdp));
391   BOOST_TEST(!k_gcrf(ctdp));
392 #endif
393 
394   BOOST_TEST(!k_gcrf(tpp));
395   BOOST_TEST(!k_gcrf(ctpp));
396   BOOST_TEST(!k_gcrf(tap));
397   BOOST_TEST(!k_gcrf(ctap));
398 
399   BOOST_TEST(!k_gcrf(tw));
400   BOOST_TEST(!k_gcrf(ctw));
401 
402   BOOST_TEST(k_grf(tr));
403 
404 #if !defined(BOOST_NO_SFINAE)
405   BOOST_TEST(k_grf(td));
406 #endif
407 
408   BOOST_TEST(k_grf(tp));
409 
410 #if !defined(BOOST_NO_SFINAE)
411   BOOST_TEST(k_grf(tdp));
412 #endif
413 
414   BOOST_TEST(k_grf(tpp));
415   BOOST_TEST(k_grf(tap));
416   BOOST_TEST(k_grf(tw));
417 
418   BOOST_TEST(ccmpk_w(tw)==make_tuple(false));
419 
420 #if !defined(BOOST_NO_SFINAE)
421 /* testcases for problems with non-copyable classes reported at
422  * http://lists.boost.org/Archives/boost/2006/04/103065.php
423  */
424 
425   nc_idn        nc_id;
426   nc_cidn       nc_cid;
427   nc_key_m      nc_k_m;
428   nc_ckey_m     nc_ck_m;
429   nc_key_cmf    nc_k_cmf;
430   nc_key_mf     nc_k_mf;
431   nc_key_gcrf   nc_k_gcrf;
432   nc_key_grf    nc_k_grf;
433   nc_compkey    nc_cmpk;
434 
435   test_nc_derived_class nc_td(-1,0);
436 
437   nc_id(nc_td).int_member=0;
438   BOOST_TEST(nc_id(nc_td).int_member==0);
439   BOOST_TEST(nc_cid(nc_td).int_member==0);
440 
441   nc_k_m(&nc_td)=1;
442   BOOST_TEST(nc_k_m(&nc_td)==1);
443   BOOST_TEST(nc_ck_m(&nc_td)==1);
444 
445   BOOST_TEST(nc_k_cmf(nc_td));
446   BOOST_TEST(!nc_k_mf(nc_td));
447 
448   BOOST_TEST(!nc_k_gcrf(nc_td));
449   BOOST_TEST(nc_k_grf(nc_td));
450 
451   test_nc_class nc_t(1,0);
452   BOOST_TEST(nc_cmpk(nc_td)==make_tuple(boost::cref(nc_t),1,1,true));
453 #endif
454 
455   std::list<test_class> tl;
456   for(int i=0;i<20;++i)tl.push_back(test_class(i));
457 
458   int j=0;
459   for(std::list<test_class>::iterator it=tl.begin();it!=tl.end();++it){
460     BOOST_TEST(k_m(it)==j);
461     BOOST_TEST(k_cm(it)==j);
462     BOOST_TEST(k_cmf(it));
463     BOOST_TEST(!k_mf(it));
464     BOOST_TEST(k_gf(it));
465     BOOST_TEST(!k_gcrf(it));
466     BOOST_TEST(k_grf(it));
467     BOOST_TEST(cmpk(it)==make_tuple(test_class(j),j,j,true));
468     BOOST_TEST(ccmpk(it)==make_tuple(test_class(j),j));
469     ++j;
470   }
471 }
472