1 /* Copyright 2003-2015 Joaquin M Lopez Munoz.
2  * Distributed under the Boost Software License, Version 1.0.
3  * (See accompanying file LICENSE_1_0.txt or copy at
4  * http://www.boost.org/LICENSE_1_0.txt)
5  *
6  * See http://www.boost.org/libs/multi_index for library home page.
7  */
8 
9 #ifndef BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
10 #define BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
11 
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15 
16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
17 #include <boost/functional/hash_fwd.hpp>
18 #include <boost/multi_index/detail/access_specifier.hpp>
19 #include <boost/mpl/eval_if.hpp>
20 #include <boost/mpl/identity.hpp>
21 #include <boost/mpl/if.hpp>
22 #include <boost/mpl/or.hpp>
23 #include <boost/preprocessor/cat.hpp>
24 #include <boost/preprocessor/control/expr_if.hpp>
25 #include <boost/preprocessor/list/at.hpp>
26 #include <boost/preprocessor/repetition/enum.hpp>
27 #include <boost/preprocessor/repetition/enum_params.hpp>
28 #include <boost/static_assert.hpp>
29 #include <boost/tuple/tuple.hpp>
30 #include <boost/type_traits/is_same.hpp>
31 #include <boost/utility/enable_if.hpp>
32 #include <functional>
33 
34 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
35 #include <boost/ref.hpp>
36 #endif
37 
38 #if !defined(BOOST_NO_SFINAE)
39 #include <boost/type_traits/is_convertible.hpp>
40 #endif
41 
42 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
43     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
44 #include <boost/multi_index/detail/cons_stdtuple.hpp>
45 #endif
46 
47 /* A composite key stores n key extractors and "computes" the
48  * result on a given value as a packed reference to the value and
49  * the composite key itself. Actual invocations to the component
50  * key extractors are lazily performed when executing an operation
51  * on composite_key results (equality, comparison, hashing.)
52  * As the other key extractors in Boost.MultiIndex, composite_key<T,...>
53  * is  overloaded to work on chained pointers to T and reference_wrappers
54  * of T.
55  */
56 
57 /* This user_definable macro limits the number of elements of a composite
58  * key; useful for shortening resulting symbol names (MSVC++ 6.0, for
59  * instance has problems coping with very long symbol names.)
60  * NB: This cannot exceed the maximum number of arguments of
61  * boost::tuple. In Boost 1.32, the limit is 10.
62  */
63 
64 #if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
65 #define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
66 #endif
67 
68 /* maximum number of key extractors in a composite key */
69 
70 #if BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE<10 /* max length of a tuple */
71 #define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE \
72   BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE
73 #else
74 #define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE 10
75 #endif
76 
77 /* BOOST_PP_ENUM of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
78 
79 #define BOOST_MULTI_INDEX_CK_ENUM(macro,data)                                \
80   BOOST_PP_ENUM(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,macro,data)
81 
82 /* BOOST_PP_ENUM_PARAMS of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
83 
84 #define BOOST_MULTI_INDEX_CK_ENUM_PARAMS(param)                              \
85   BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,param)
86 
87 /* if n==0 ->   text0
88  * otherwise -> textn=tuples::null_type
89  */
90 
91 #define BOOST_MULTI_INDEX_CK_TEMPLATE_PARM(z,n,text)                         \
92   typename BOOST_PP_CAT(text,n) BOOST_PP_EXPR_IF(n,=tuples::null_type)
93 
94 /* const textn& kn=textn() */
95 
96 #define BOOST_MULTI_INDEX_CK_CTOR_ARG(z,n,text)                              \
97   const BOOST_PP_CAT(text,n)& BOOST_PP_CAT(k,n) = BOOST_PP_CAT(text,n)()
98 
99 /* typename list(0)<list(1),n>::type */
100 
101 #define BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N(z,n,list)                  \
102   BOOST_DEDUCED_TYPENAME BOOST_PP_LIST_AT(list,0)<                           \
103     BOOST_PP_LIST_AT(list,1),n                                               \
104   >::type
105 
106 namespace boost{
107 
108 template<class T> class reference_wrapper; /* fwd decl. */
109 
110 namespace multi_index{
111 
112 namespace detail{
113 
114 /* n-th key extractor of a composite key */
115 
116 template<typename CompositeKey,int N>
117 struct nth_key_from_value
118 {
119   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
120   typedef typename mpl::eval_if_c<
121     N<tuples::length<key_extractor_tuple>::value,
122     tuples::element<N,key_extractor_tuple>,
123     mpl::identity<tuples::null_type>
124   >::type                                            type;
125 };
126 
127 /* nth_composite_key_##name<CompositeKey,N>::type yields
128  * functor<nth_key_from_value<CompositeKey,N> >, or tuples::null_type
129  * if N exceeds the length of the composite key.
130  */
131 
132 #define BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(name,functor)         \
133 template<typename KeyFromValue>                                              \
134 struct BOOST_PP_CAT(key_,name)                                               \
135 {                                                                            \
136   typedef functor<typename KeyFromValue::result_type> type;                  \
137 };                                                                           \
138                                                                              \
139 template<>                                                                   \
140 struct BOOST_PP_CAT(key_,name)<tuples::null_type>                            \
141 {                                                                            \
142   typedef tuples::null_type type;                                            \
143 };                                                                           \
144                                                                              \
145 template<typename CompositeKey,int  N>                                       \
146 struct BOOST_PP_CAT(nth_composite_key_,name)                                 \
147 {                                                                            \
148   typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;  \
149   typedef typename BOOST_PP_CAT(key_,name)<key_from_value>::type type;       \
150 };
151 
152 /* nth_composite_key_equal_to
153  * nth_composite_key_less
154  * nth_composite_key_greater
155  * nth_composite_key_hash
156  */
157 
158 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(equal_to,std::equal_to)
159 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(less,std::less)
160 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(greater,std::greater)
161 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(hash,boost::hash)
162 
163 /* used for defining equality and comparison ops of composite_key_result */
164 
165 #define BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO(z,n,text) text
166 
167 struct generic_operator_equal
168 {
169   template<typename T,typename Q>
operator ()boost::multi_index::detail::generic_operator_equal170   bool operator()(const T& x,const Q& y)const{return x==y;}
171 };
172 
173 typedef tuple<
174   BOOST_MULTI_INDEX_CK_ENUM(
175     BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
176     detail::generic_operator_equal)>          generic_operator_equal_tuple;
177 
178 struct generic_operator_less
179 {
180   template<typename T,typename Q>
operator ()boost::multi_index::detail::generic_operator_less181   bool operator()(const T& x,const Q& y)const{return x<y;}
182 };
183 
184 typedef tuple<
185   BOOST_MULTI_INDEX_CK_ENUM(
186     BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
187     detail::generic_operator_less)>           generic_operator_less_tuple;
188 
189 /* Metaprogramming machinery for implementing equality, comparison and
190  * hashing operations of composite_key_result.
191  *
192  * equal_* checks for equality between composite_key_results and
193  * between those and tuples, accepting a tuple of basic equality functors.
194  * compare_* does lexicographical comparison.
195  * hash_* computes a combination of elementwise hash values.
196  */
197 
198 template
199 <
200   typename KeyCons1,typename Value1,
201   typename KeyCons2, typename Value2,
202   typename EqualCons
203 >
204 struct equal_ckey_ckey; /* fwd decl. */
205 
206 template
207 <
208   typename KeyCons1,typename Value1,
209   typename KeyCons2, typename Value2,
210   typename EqualCons
211 >
212 struct equal_ckey_ckey_terminal
213 {
compareboost::multi_index::detail::equal_ckey_ckey_terminal214   static bool compare(
215     const KeyCons1&,const Value1&,
216     const KeyCons2&,const Value2&,
217     const EqualCons&)
218   {
219     return true;
220   }
221 };
222 
223 template
224 <
225   typename KeyCons1,typename Value1,
226   typename KeyCons2, typename Value2,
227   typename EqualCons
228 >
229 struct equal_ckey_ckey_normal
230 {
compareboost::multi_index::detail::equal_ckey_ckey_normal231   static bool compare(
232     const KeyCons1& c0,const Value1& v0,
233     const KeyCons2& c1,const Value2& v1,
234     const EqualCons& eq)
235   {
236     if(!eq.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return false;
237     return equal_ckey_ckey<
238       BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
239       BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
240       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
241     >::compare(c0.get_tail(),v0,c1.get_tail(),v1,eq.get_tail());
242   }
243 };
244 
245 template
246 <
247   typename KeyCons1,typename Value1,
248   typename KeyCons2, typename Value2,
249   typename EqualCons
250 >
251 struct equal_ckey_ckey:
252   mpl::if_<
253     mpl::or_<
254       is_same<KeyCons1,tuples::null_type>,
255       is_same<KeyCons2,tuples::null_type>
256     >,
257     equal_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>,
258     equal_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>
259   >::type
260 {
261 };
262 
263 template
264 <
265   typename KeyCons,typename Value,
266   typename ValCons,typename EqualCons
267 >
268 struct equal_ckey_cval; /* fwd decl. */
269 
270 template
271 <
272   typename KeyCons,typename Value,
273   typename ValCons,typename EqualCons
274 >
275 struct equal_ckey_cval_terminal
276 {
compareboost::multi_index::detail::equal_ckey_cval_terminal277   static bool compare(
278     const KeyCons&,const Value&,const ValCons&,const EqualCons&)
279   {
280     return true;
281   }
282 
compareboost::multi_index::detail::equal_ckey_cval_terminal283   static bool compare(
284     const ValCons&,const KeyCons&,const Value&,const EqualCons&)
285   {
286     return true;
287   }
288 };
289 
290 template
291 <
292   typename KeyCons,typename Value,
293   typename ValCons,typename EqualCons
294 >
295 struct equal_ckey_cval_normal
296 {
compareboost::multi_index::detail::equal_ckey_cval_normal297   static bool compare(
298     const KeyCons& c,const Value& v,const ValCons& vc,
299     const EqualCons& eq)
300   {
301     if(!eq.get_head()(c.get_head()(v),vc.get_head()))return false;
302     return equal_ckey_cval<
303       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
304       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
305       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
306     >::compare(c.get_tail(),v,vc.get_tail(),eq.get_tail());
307   }
308 
compareboost::multi_index::detail::equal_ckey_cval_normal309   static bool compare(
310     const ValCons& vc,const KeyCons& c,const Value& v,
311     const EqualCons& eq)
312   {
313     if(!eq.get_head()(vc.get_head(),c.get_head()(v)))return false;
314     return equal_ckey_cval<
315       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
316       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
317       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
318     >::compare(vc.get_tail(),c.get_tail(),v,eq.get_tail());
319   }
320 };
321 
322 template
323 <
324   typename KeyCons,typename Value,
325   typename ValCons,typename EqualCons
326 >
327 struct equal_ckey_cval:
328   mpl::if_<
329     mpl::or_<
330       is_same<KeyCons,tuples::null_type>,
331       is_same<ValCons,tuples::null_type>
332     >,
333     equal_ckey_cval_terminal<KeyCons,Value,ValCons,EqualCons>,
334     equal_ckey_cval_normal<KeyCons,Value,ValCons,EqualCons>
335   >::type
336 {
337 };
338 
339 template
340 <
341   typename KeyCons1,typename Value1,
342   typename KeyCons2, typename Value2,
343   typename CompareCons
344 >
345 struct compare_ckey_ckey; /* fwd decl. */
346 
347 template
348 <
349   typename KeyCons1,typename Value1,
350   typename KeyCons2, typename Value2,
351   typename CompareCons
352 >
353 struct compare_ckey_ckey_terminal
354 {
compareboost::multi_index::detail::compare_ckey_ckey_terminal355   static bool compare(
356     const KeyCons1&,const Value1&,
357     const KeyCons2&,const Value2&,
358     const CompareCons&)
359   {
360     return false;
361   }
362 };
363 
364 template
365 <
366   typename KeyCons1,typename Value1,
367   typename KeyCons2, typename Value2,
368   typename CompareCons
369 >
370 struct compare_ckey_ckey_normal
371 {
compareboost::multi_index::detail::compare_ckey_ckey_normal372   static bool compare(
373     const KeyCons1& c0,const Value1& v0,
374     const KeyCons2& c1,const Value2& v1,
375     const CompareCons& comp)
376   {
377     if(comp.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return true;
378     if(comp.get_head()(c1.get_head()(v1),c0.get_head()(v0)))return false;
379     return compare_ckey_ckey<
380       BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
381       BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
382       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
383     >::compare(c0.get_tail(),v0,c1.get_tail(),v1,comp.get_tail());
384   }
385 };
386 
387 template
388 <
389   typename KeyCons1,typename Value1,
390   typename KeyCons2, typename Value2,
391   typename CompareCons
392 >
393 struct compare_ckey_ckey:
394   mpl::if_<
395     mpl::or_<
396       is_same<KeyCons1,tuples::null_type>,
397       is_same<KeyCons2,tuples::null_type>
398     >,
399     compare_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>,
400     compare_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>
401   >::type
402 {
403 };
404 
405 template
406 <
407   typename KeyCons,typename Value,
408   typename ValCons,typename CompareCons
409 >
410 struct compare_ckey_cval; /* fwd decl. */
411 
412 template
413 <
414   typename KeyCons,typename Value,
415   typename ValCons,typename CompareCons
416 >
417 struct compare_ckey_cval_terminal
418 {
compareboost::multi_index::detail::compare_ckey_cval_terminal419   static bool compare(
420     const KeyCons&,const Value&,const ValCons&,const CompareCons&)
421   {
422     return false;
423   }
424 
compareboost::multi_index::detail::compare_ckey_cval_terminal425   static bool compare(
426     const ValCons&,const KeyCons&,const Value&,const CompareCons&)
427   {
428     return false;
429   }
430 };
431 
432 template
433 <
434   typename KeyCons,typename Value,
435   typename ValCons,typename CompareCons
436 >
437 struct compare_ckey_cval_normal
438 {
compareboost::multi_index::detail::compare_ckey_cval_normal439   static bool compare(
440     const KeyCons& c,const Value& v,const ValCons& vc,
441     const CompareCons& comp)
442   {
443     if(comp.get_head()(c.get_head()(v),vc.get_head()))return true;
444     if(comp.get_head()(vc.get_head(),c.get_head()(v)))return false;
445     return compare_ckey_cval<
446       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
447       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
448       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
449     >::compare(c.get_tail(),v,vc.get_tail(),comp.get_tail());
450   }
451 
compareboost::multi_index::detail::compare_ckey_cval_normal452   static bool compare(
453     const ValCons& vc,const KeyCons& c,const Value& v,
454     const CompareCons& comp)
455   {
456     if(comp.get_head()(vc.get_head(),c.get_head()(v)))return true;
457     if(comp.get_head()(c.get_head()(v),vc.get_head()))return false;
458     return compare_ckey_cval<
459       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
460       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
461       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
462     >::compare(vc.get_tail(),c.get_tail(),v,comp.get_tail());
463   }
464 };
465 
466 template
467 <
468   typename KeyCons,typename Value,
469   typename ValCons,typename CompareCons
470 >
471 struct compare_ckey_cval:
472   mpl::if_<
473     mpl::or_<
474       is_same<KeyCons,tuples::null_type>,
475       is_same<ValCons,tuples::null_type>
476     >,
477     compare_ckey_cval_terminal<KeyCons,Value,ValCons,CompareCons>,
478     compare_ckey_cval_normal<KeyCons,Value,ValCons,CompareCons>
479   >::type
480 {
481 };
482 
483 template<typename KeyCons,typename Value,typename HashCons>
484 struct hash_ckey; /* fwd decl. */
485 
486 template<typename KeyCons,typename Value,typename HashCons>
487 struct hash_ckey_terminal
488 {
hashboost::multi_index::detail::hash_ckey_terminal489   static std::size_t hash(
490     const KeyCons&,const Value&,const HashCons&,std::size_t carry)
491   {
492     return carry;
493   }
494 };
495 
496 template<typename KeyCons,typename Value,typename HashCons>
497 struct hash_ckey_normal
498 {
hashboost::multi_index::detail::hash_ckey_normal499   static std::size_t hash(
500     const KeyCons& c,const Value& v,const HashCons& h,std::size_t carry=0)
501   {
502     /* same hashing formula as boost::hash_combine */
503 
504     carry^=h.get_head()(c.get_head()(v))+0x9e3779b9+(carry<<6)+(carry>>2);
505     return hash_ckey<
506       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
507       BOOST_DEDUCED_TYPENAME HashCons::tail_type
508     >::hash(c.get_tail(),v,h.get_tail(),carry);
509   }
510 };
511 
512 template<typename KeyCons,typename Value,typename HashCons>
513 struct hash_ckey:
514   mpl::if_<
515     is_same<KeyCons,tuples::null_type>,
516     hash_ckey_terminal<KeyCons,Value,HashCons>,
517     hash_ckey_normal<KeyCons,Value,HashCons>
518   >::type
519 {
520 };
521 
522 template<typename ValCons,typename HashCons>
523 struct hash_cval; /* fwd decl. */
524 
525 template<typename ValCons,typename HashCons>
526 struct hash_cval_terminal
527 {
hashboost::multi_index::detail::hash_cval_terminal528   static std::size_t hash(const ValCons&,const HashCons&,std::size_t carry)
529   {
530     return carry;
531   }
532 };
533 
534 template<typename ValCons,typename HashCons>
535 struct hash_cval_normal
536 {
hashboost::multi_index::detail::hash_cval_normal537   static std::size_t hash(
538     const ValCons& vc,const HashCons& h,std::size_t carry=0)
539   {
540     carry^=h.get_head()(vc.get_head())+0x9e3779b9+(carry<<6)+(carry>>2);
541     return hash_cval<
542       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
543       BOOST_DEDUCED_TYPENAME HashCons::tail_type
544     >::hash(vc.get_tail(),h.get_tail(),carry);
545   }
546 };
547 
548 template<typename ValCons,typename HashCons>
549 struct hash_cval:
550   mpl::if_<
551     is_same<ValCons,tuples::null_type>,
552     hash_cval_terminal<ValCons,HashCons>,
553     hash_cval_normal<ValCons,HashCons>
554   >::type
555 {
556 };
557 
558 } /* namespace multi_index::detail */
559 
560 /* composite_key_result */
561 
562 #if defined(BOOST_MSVC)
563 #pragma warning(push)
564 #pragma warning(disable:4512)
565 #endif
566 
567 template<typename CompositeKey>
568 struct composite_key_result
569 {
570   typedef CompositeKey                            composite_key_type;
571   typedef typename composite_key_type::value_type value_type;
572 
composite_key_resultboost::multi_index::composite_key_result573   composite_key_result(
574     const composite_key_type& composite_key_,const value_type& value_):
575     composite_key(composite_key_),value(value_)
576   {}
577 
578   const composite_key_type& composite_key;
579   const value_type&         value;
580 };
581 
582 #if defined(BOOST_MSVC)
583 #pragma warning(pop)
584 #endif
585 
586 /* composite_key */
587 
588 template<
589   typename Value,
590   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,KeyFromValue)
591 >
592 struct composite_key:
593   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)>
594 {
595 private:
596   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)> super;
597 
598 public:
599   typedef super                               key_extractor_tuple;
600   typedef Value                               value_type;
601   typedef composite_key_result<composite_key> result_type;
602 
composite_keyboost::multi_index::composite_key603   composite_key(
604     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,KeyFromValue)):
605     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
606   {}
607 
composite_keyboost::multi_index::composite_key608   composite_key(const key_extractor_tuple& x):super(x){}
609 
key_extractorsboost::multi_index::composite_key610   const key_extractor_tuple& key_extractors()const{return *this;}
key_extractorsboost::multi_index::composite_key611   key_extractor_tuple&       key_extractors(){return *this;}
612 
613   template<typename ChainedPtr>
614 
615 #if !defined(BOOST_NO_SFINAE)
616   typename disable_if<
617     is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
618 #else
619   result_type
620 #endif
621 
operator ()boost::multi_index::composite_key622   operator()(const ChainedPtr& x)const
623   {
624     return operator()(*x);
625   }
626 
operator ()boost::multi_index::composite_key627   result_type operator()(const value_type& x)const
628   {
629     return result_type(*this,x);
630   }
631 
operator ()boost::multi_index::composite_key632   result_type operator()(const reference_wrapper<const value_type>& x)const
633   {
634     return result_type(*this,x.get());
635   }
636 
operator ()boost::multi_index::composite_key637   result_type operator()(const reference_wrapper<value_type>& x)const
638   {
639     return result_type(*this,x.get());
640   }
641 };
642 
643 /* comparison operators */
644 
645 /* == */
646 
647 template<typename CompositeKey1,typename CompositeKey2>
operator ==(const composite_key_result<CompositeKey1> & x,const composite_key_result<CompositeKey2> & y)648 inline bool operator==(
649   const composite_key_result<CompositeKey1>& x,
650   const composite_key_result<CompositeKey2>& y)
651 {
652   typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
653   typedef typename CompositeKey1::value_type          value_type1;
654   typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
655   typedef typename CompositeKey2::value_type          value_type2;
656 
657   BOOST_STATIC_ASSERT(
658     tuples::length<key_extractor_tuple1>::value==
659     tuples::length<key_extractor_tuple2>::value);
660 
661   return detail::equal_ckey_ckey<
662     key_extractor_tuple1,value_type1,
663     key_extractor_tuple2,value_type2,
664     detail::generic_operator_equal_tuple
665   >::compare(
666     x.composite_key.key_extractors(),x.value,
667     y.composite_key.key_extractors(),y.value,
668     detail::generic_operator_equal_tuple());
669 }
670 
671 template<
672   typename CompositeKey,
673   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
674 >
operator ==(const composite_key_result<CompositeKey> & x,const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS (Value)> & y)675 inline bool operator==(
676   const composite_key_result<CompositeKey>& x,
677   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
678 {
679   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
680   typedef typename CompositeKey::value_type              value_type;
681   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
682 
683   BOOST_STATIC_ASSERT(
684     tuples::length<key_extractor_tuple>::value==
685     tuples::length<key_tuple>::value);
686 
687   return detail::equal_ckey_cval<
688     key_extractor_tuple,value_type,
689     key_tuple,detail::generic_operator_equal_tuple
690   >::compare(
691     x.composite_key.key_extractors(),x.value,
692     y,detail::generic_operator_equal_tuple());
693 }
694 
695 template
696 <
697   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
698   typename CompositeKey
699 >
operator ==(const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS (Value)> & x,const composite_key_result<CompositeKey> & y)700 inline bool operator==(
701   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
702   const composite_key_result<CompositeKey>& y)
703 {
704   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
705   typedef typename CompositeKey::value_type              value_type;
706   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
707 
708   BOOST_STATIC_ASSERT(
709     tuples::length<key_extractor_tuple>::value==
710     tuples::length<key_tuple>::value);
711 
712   return detail::equal_ckey_cval<
713     key_extractor_tuple,value_type,
714     key_tuple,detail::generic_operator_equal_tuple
715   >::compare(
716     x,y.composite_key.key_extractors(),
717     y.value,detail::generic_operator_equal_tuple());
718 }
719 
720 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
721     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
722 template<typename CompositeKey,typename... Values>
operator ==(const composite_key_result<CompositeKey> & x,const std::tuple<Values...> & y)723 inline bool operator==(
724   const composite_key_result<CompositeKey>& x,
725   const std::tuple<Values...>& y)
726 {
727   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
728   typedef typename CompositeKey::value_type          value_type;
729   typedef std::tuple<Values...>                      key_tuple;
730   typedef typename detail::cons_stdtuple_ctor<
731     key_tuple>::result_type                          cons_key_tuple;
732 
733   BOOST_STATIC_ASSERT(
734     static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
735     std::tuple_size<key_tuple>::value);
736 
737   return detail::equal_ckey_cval<
738     key_extractor_tuple,value_type,
739     cons_key_tuple,detail::generic_operator_equal_tuple
740   >::compare(
741     x.composite_key.key_extractors(),x.value,
742     detail::make_cons_stdtuple(y),detail::generic_operator_equal_tuple());
743 }
744 
745 template<typename CompositeKey,typename... Values>
operator ==(const std::tuple<Values...> & x,const composite_key_result<CompositeKey> & y)746 inline bool operator==(
747   const std::tuple<Values...>& x,
748   const composite_key_result<CompositeKey>& y)
749 {
750   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
751   typedef typename CompositeKey::value_type          value_type;
752   typedef std::tuple<Values...>                      key_tuple;
753   typedef typename detail::cons_stdtuple_ctor<
754     key_tuple>::result_type                          cons_key_tuple;
755 
756   BOOST_STATIC_ASSERT(
757     static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
758     std::tuple_size<key_tuple>::value);
759 
760   return detail::equal_ckey_cval<
761     key_extractor_tuple,value_type,
762     cons_key_tuple,detail::generic_operator_equal_tuple
763   >::compare(
764     detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
765     y.value,detail::generic_operator_equal_tuple());
766 }
767 #endif
768 
769 /* < */
770 
771 template<typename CompositeKey1,typename CompositeKey2>
operator <(const composite_key_result<CompositeKey1> & x,const composite_key_result<CompositeKey2> & y)772 inline bool operator<(
773   const composite_key_result<CompositeKey1>& x,
774   const composite_key_result<CompositeKey2>& y)
775 {
776   typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
777   typedef typename CompositeKey1::value_type          value_type1;
778   typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
779   typedef typename CompositeKey2::value_type          value_type2;
780 
781   return detail::compare_ckey_ckey<
782    key_extractor_tuple1,value_type1,
783    key_extractor_tuple2,value_type2,
784    detail::generic_operator_less_tuple
785   >::compare(
786     x.composite_key.key_extractors(),x.value,
787     y.composite_key.key_extractors(),y.value,
788     detail::generic_operator_less_tuple());
789 }
790 
791 template
792 <
793   typename CompositeKey,
794   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
795 >
operator <(const composite_key_result<CompositeKey> & x,const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS (Value)> & y)796 inline bool operator<(
797   const composite_key_result<CompositeKey>& x,
798   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
799 {
800   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
801   typedef typename CompositeKey::value_type              value_type;
802   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
803 
804   return detail::compare_ckey_cval<
805     key_extractor_tuple,value_type,
806     key_tuple,detail::generic_operator_less_tuple
807   >::compare(
808     x.composite_key.key_extractors(),x.value,
809     y,detail::generic_operator_less_tuple());
810 }
811 
812 template
813 <
814   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
815   typename CompositeKey
816 >
operator <(const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS (Value)> & x,const composite_key_result<CompositeKey> & y)817 inline bool operator<(
818   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
819   const composite_key_result<CompositeKey>& y)
820 {
821   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
822   typedef typename CompositeKey::value_type              value_type;
823   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
824 
825   return detail::compare_ckey_cval<
826     key_extractor_tuple,value_type,
827     key_tuple,detail::generic_operator_less_tuple
828   >::compare(
829     x,y.composite_key.key_extractors(),
830     y.value,detail::generic_operator_less_tuple());
831 }
832 
833 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
834     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
835 template<typename CompositeKey,typename... Values>
operator <(const composite_key_result<CompositeKey> & x,const std::tuple<Values...> & y)836 inline bool operator<(
837   const composite_key_result<CompositeKey>& x,
838   const std::tuple<Values...>& y)
839 {
840   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
841   typedef typename CompositeKey::value_type          value_type;
842   typedef std::tuple<Values...>                      key_tuple;
843   typedef typename detail::cons_stdtuple_ctor<
844     key_tuple>::result_type                          cons_key_tuple;
845 
846   return detail::compare_ckey_cval<
847     key_extractor_tuple,value_type,
848     cons_key_tuple,detail::generic_operator_less_tuple
849   >::compare(
850     x.composite_key.key_extractors(),x.value,
851     detail::make_cons_stdtuple(y),detail::generic_operator_less_tuple());
852 }
853 
854 template<typename CompositeKey,typename... Values>
operator <(const std::tuple<Values...> & x,const composite_key_result<CompositeKey> & y)855 inline bool operator<(
856   const std::tuple<Values...>& x,
857   const composite_key_result<CompositeKey>& y)
858 {
859   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
860   typedef typename CompositeKey::value_type          value_type;
861   typedef std::tuple<Values...>                      key_tuple;
862   typedef typename detail::cons_stdtuple_ctor<
863     key_tuple>::result_type                          cons_key_tuple;
864 
865   return detail::compare_ckey_cval<
866     key_extractor_tuple,value_type,
867     cons_key_tuple,detail::generic_operator_less_tuple
868   >::compare(
869     detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
870     y.value,detail::generic_operator_less_tuple());
871 }
872 #endif
873 
874 /* rest of comparison operators */
875 
876 #define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2)                  \
877 template<t1,t2> inline bool operator!=(const a1& x,const a2& y)              \
878 {                                                                            \
879   return !(x==y);                                                            \
880 }                                                                            \
881                                                                              \
882 template<t1,t2> inline bool operator>(const a1& x,const a2& y)               \
883 {                                                                            \
884   return y<x;                                                                \
885 }                                                                            \
886                                                                              \
887 template<t1,t2> inline bool operator>=(const a1& x,const a2& y)              \
888 {                                                                            \
889   return !(x<y);                                                             \
890 }                                                                            \
891                                                                              \
892 template<t1,t2> inline bool operator<=(const a1& x,const a2& y)              \
893 {                                                                            \
894   return !(y<x);                                                             \
895 }
896 
897 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
898   typename CompositeKey1,
899   typename CompositeKey2,
900   composite_key_result<CompositeKey1>,
901   composite_key_result<CompositeKey2>
902 )
903 
904 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
905   typename CompositeKey,
906   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
907   composite_key_result<CompositeKey>,
908   tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>
909 )
910 
911 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
912   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
913   typename CompositeKey,
914   tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>,
915   composite_key_result<CompositeKey>
916 )
917 
918 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
919     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
920 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
921   typename CompositeKey,
922   typename... Values,
923   composite_key_result<CompositeKey>,
924   std::tuple<Values...>
925 )
926 
927 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
928   typename CompositeKey,
929   typename... Values,
930   std::tuple<Values...>,
931   composite_key_result<CompositeKey>
932 )
933 #endif
934 
935 /* composite_key_equal_to */
936 
937 template
938 <
939   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Pred)
940 >
941 struct composite_key_equal_to:
942   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)>
943 {
944 private:
945   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)> super;
946 
947 public:
948   typedef super key_eq_tuple;
949 
composite_key_equal_toboost::multi_index::composite_key_equal_to950   composite_key_equal_to(
951     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Pred)):
952     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
953   {}
954 
composite_key_equal_toboost::multi_index::composite_key_equal_to955   composite_key_equal_to(const key_eq_tuple& x):super(x){}
956 
key_eqsboost::multi_index::composite_key_equal_to957   const key_eq_tuple& key_eqs()const{return *this;}
key_eqsboost::multi_index::composite_key_equal_to958   key_eq_tuple&       key_eqs(){return *this;}
959 
960   template<typename CompositeKey1,typename CompositeKey2>
operator ()boost::multi_index::composite_key_equal_to961   bool operator()(
962     const composite_key_result<CompositeKey1> & x,
963     const composite_key_result<CompositeKey2> & y)const
964   {
965     typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
966     typedef typename CompositeKey1::value_type          value_type1;
967     typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
968     typedef typename CompositeKey2::value_type          value_type2;
969 
970     BOOST_STATIC_ASSERT(
971       tuples::length<key_extractor_tuple1>::value<=
972       tuples::length<key_eq_tuple>::value&&
973       tuples::length<key_extractor_tuple1>::value==
974       tuples::length<key_extractor_tuple2>::value);
975 
976     return detail::equal_ckey_ckey<
977       key_extractor_tuple1,value_type1,
978       key_extractor_tuple2,value_type2,
979       key_eq_tuple
980     >::compare(
981       x.composite_key.key_extractors(),x.value,
982       y.composite_key.key_extractors(),y.value,
983       key_eqs());
984   }
985 
986   template
987   <
988     typename CompositeKey,
989     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
990   >
operator ()boost::multi_index::composite_key_equal_to991   bool operator()(
992     const composite_key_result<CompositeKey>& x,
993     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
994   {
995     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
996     typedef typename CompositeKey::value_type              value_type;
997     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
998 
999     BOOST_STATIC_ASSERT(
1000       tuples::length<key_extractor_tuple>::value<=
1001       tuples::length<key_eq_tuple>::value&&
1002       tuples::length<key_extractor_tuple>::value==
1003       tuples::length<key_tuple>::value);
1004 
1005     return detail::equal_ckey_cval<
1006       key_extractor_tuple,value_type,
1007       key_tuple,key_eq_tuple
1008     >::compare(x.composite_key.key_extractors(),x.value,y,key_eqs());
1009   }
1010 
1011   template
1012   <
1013     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
1014     typename CompositeKey
1015   >
operator ()boost::multi_index::composite_key_equal_to1016   bool operator()(
1017     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
1018     const composite_key_result<CompositeKey>& y)const
1019   {
1020     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
1021     typedef typename CompositeKey::value_type              value_type;
1022     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1023 
1024     BOOST_STATIC_ASSERT(
1025       tuples::length<key_tuple>::value<=
1026       tuples::length<key_eq_tuple>::value&&
1027       tuples::length<key_tuple>::value==
1028       tuples::length<key_extractor_tuple>::value);
1029 
1030     return detail::equal_ckey_cval<
1031       key_extractor_tuple,value_type,
1032       key_tuple,key_eq_tuple
1033     >::compare(x,y.composite_key.key_extractors(),y.value,key_eqs());
1034   }
1035 
1036 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
1037     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1038   template<typename CompositeKey,typename... Values>
operator ()boost::multi_index::composite_key_equal_to1039   bool operator()(
1040     const composite_key_result<CompositeKey>& x,
1041     const std::tuple<Values...>& y)const
1042   {
1043     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1044     typedef typename CompositeKey::value_type          value_type;
1045     typedef std::tuple<Values...>                      key_tuple;
1046     typedef typename detail::cons_stdtuple_ctor<
1047       key_tuple>::result_type                          cons_key_tuple;
1048 
1049     BOOST_STATIC_ASSERT(
1050       tuples::length<key_extractor_tuple>::value<=
1051       tuples::length<key_eq_tuple>::value&&
1052       static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
1053       std::tuple_size<key_tuple>::value);
1054 
1055     return detail::equal_ckey_cval<
1056       key_extractor_tuple,value_type,
1057       cons_key_tuple,key_eq_tuple
1058     >::compare(
1059       x.composite_key.key_extractors(),x.value,
1060       detail::make_cons_stdtuple(y),key_eqs());
1061   }
1062 
1063   template<typename CompositeKey,typename... Values>
operator ()boost::multi_index::composite_key_equal_to1064   bool operator()(
1065     const std::tuple<Values...>& x,
1066     const composite_key_result<CompositeKey>& y)const
1067   {
1068     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1069     typedef typename CompositeKey::value_type          value_type;
1070     typedef std::tuple<Values...>                      key_tuple;
1071     typedef typename detail::cons_stdtuple_ctor<
1072       key_tuple>::result_type                          cons_key_tuple;
1073 
1074     BOOST_STATIC_ASSERT(
1075       std::tuple_size<key_tuple>::value<=
1076       static_cast<std::size_t>(tuples::length<key_eq_tuple>::value)&&
1077       std::tuple_size<key_tuple>::value==
1078       static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value));
1079 
1080     return detail::equal_ckey_cval<
1081       key_extractor_tuple,value_type,
1082       cons_key_tuple,key_eq_tuple
1083     >::compare(
1084       detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
1085       y.value,key_eqs());
1086   }
1087 #endif
1088 };
1089 
1090 /* composite_key_compare */
1091 
1092 template
1093 <
1094   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Compare)
1095 >
1096 struct composite_key_compare:
1097   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)>
1098 {
1099 private:
1100   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)> super;
1101 
1102 public:
1103   typedef super key_comp_tuple;
1104 
composite_key_compareboost::multi_index::composite_key_compare1105   composite_key_compare(
1106     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Compare)):
1107     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
1108   {}
1109 
composite_key_compareboost::multi_index::composite_key_compare1110   composite_key_compare(const key_comp_tuple& x):super(x){}
1111 
key_compsboost::multi_index::composite_key_compare1112   const key_comp_tuple& key_comps()const{return *this;}
key_compsboost::multi_index::composite_key_compare1113   key_comp_tuple&       key_comps(){return *this;}
1114 
1115   template<typename CompositeKey1,typename CompositeKey2>
operator ()boost::multi_index::composite_key_compare1116   bool operator()(
1117     const composite_key_result<CompositeKey1> & x,
1118     const composite_key_result<CompositeKey2> & y)const
1119   {
1120     typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
1121     typedef typename CompositeKey1::value_type          value_type1;
1122     typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
1123     typedef typename CompositeKey2::value_type          value_type2;
1124 
1125     BOOST_STATIC_ASSERT(
1126       tuples::length<key_extractor_tuple1>::value<=
1127       tuples::length<key_comp_tuple>::value||
1128       tuples::length<key_extractor_tuple2>::value<=
1129       tuples::length<key_comp_tuple>::value);
1130 
1131     return detail::compare_ckey_ckey<
1132       key_extractor_tuple1,value_type1,
1133       key_extractor_tuple2,value_type2,
1134       key_comp_tuple
1135     >::compare(
1136       x.composite_key.key_extractors(),x.value,
1137       y.composite_key.key_extractors(),y.value,
1138       key_comps());
1139   }
1140 
1141 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
1142   template<typename CompositeKey,typename Value>
operator ()boost::multi_index::composite_key_compare1143   bool operator()(
1144     const composite_key_result<CompositeKey>& x,
1145     const Value& y)const
1146   {
1147     return operator()(x,boost::make_tuple(boost::cref(y)));
1148   }
1149 #endif
1150 
1151   template
1152   <
1153     typename CompositeKey,
1154     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
1155   >
operator ()boost::multi_index::composite_key_compare1156   bool operator()(
1157     const composite_key_result<CompositeKey>& x,
1158     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
1159   {
1160     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
1161     typedef typename CompositeKey::value_type              value_type;
1162     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1163 
1164     BOOST_STATIC_ASSERT(
1165       tuples::length<key_extractor_tuple>::value<=
1166       tuples::length<key_comp_tuple>::value||
1167       tuples::length<key_tuple>::value<=
1168       tuples::length<key_comp_tuple>::value);
1169 
1170     return detail::compare_ckey_cval<
1171       key_extractor_tuple,value_type,
1172       key_tuple,key_comp_tuple
1173     >::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
1174   }
1175 
1176 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
1177   template<typename Value,typename CompositeKey>
operator ()boost::multi_index::composite_key_compare1178   bool operator()(
1179     const Value& x,
1180     const composite_key_result<CompositeKey>& y)const
1181   {
1182     return operator()(boost::make_tuple(boost::cref(x)),y);
1183   }
1184 #endif
1185 
1186   template
1187   <
1188     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
1189     typename CompositeKey
1190   >
operator ()boost::multi_index::composite_key_compare1191   bool operator()(
1192     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
1193     const composite_key_result<CompositeKey>& y)const
1194   {
1195     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
1196     typedef typename CompositeKey::value_type              value_type;
1197     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1198 
1199     BOOST_STATIC_ASSERT(
1200       tuples::length<key_tuple>::value<=
1201       tuples::length<key_comp_tuple>::value||
1202       tuples::length<key_extractor_tuple>::value<=
1203       tuples::length<key_comp_tuple>::value);
1204 
1205     return detail::compare_ckey_cval<
1206       key_extractor_tuple,value_type,
1207       key_tuple,key_comp_tuple
1208     >::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
1209   }
1210 
1211 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
1212     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1213   template<typename CompositeKey,typename... Values>
operator ()boost::multi_index::composite_key_compare1214   bool operator()(
1215     const composite_key_result<CompositeKey>& x,
1216     const std::tuple<Values...>& y)const
1217   {
1218     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1219     typedef typename CompositeKey::value_type          value_type;
1220     typedef std::tuple<Values...>                      key_tuple;
1221     typedef typename detail::cons_stdtuple_ctor<
1222       key_tuple>::result_type                          cons_key_tuple;
1223 
1224     BOOST_STATIC_ASSERT(
1225       tuples::length<key_extractor_tuple>::value<=
1226       tuples::length<key_comp_tuple>::value||
1227       std::tuple_size<key_tuple>::value<=
1228       static_cast<std::size_t>(tuples::length<key_comp_tuple>::value));
1229 
1230     return detail::compare_ckey_cval<
1231       key_extractor_tuple,value_type,
1232       cons_key_tuple,key_comp_tuple
1233     >::compare(
1234       x.composite_key.key_extractors(),x.value,
1235       detail::make_cons_stdtuple(y),key_comps());
1236   }
1237 
1238   template<typename CompositeKey,typename... Values>
operator ()boost::multi_index::composite_key_compare1239   bool operator()(
1240     const std::tuple<Values...>& x,
1241     const composite_key_result<CompositeKey>& y)const
1242   {
1243     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1244     typedef typename CompositeKey::value_type          value_type;
1245     typedef std::tuple<Values...>                      key_tuple;
1246     typedef typename detail::cons_stdtuple_ctor<
1247       key_tuple>::result_type                          cons_key_tuple;
1248 
1249     BOOST_STATIC_ASSERT(
1250       std::tuple_size<key_tuple>::value<=
1251       static_cast<std::size_t>(tuples::length<key_comp_tuple>::value)||
1252       tuples::length<key_extractor_tuple>::value<=
1253       tuples::length<key_comp_tuple>::value);
1254 
1255     return detail::compare_ckey_cval<
1256       key_extractor_tuple,value_type,
1257       cons_key_tuple,key_comp_tuple
1258     >::compare(
1259       detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
1260       y.value,key_comps());
1261   }
1262 #endif
1263 };
1264 
1265 /* composite_key_hash */
1266 
1267 template
1268 <
1269   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Hash)
1270 >
1271 struct composite_key_hash:
1272   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)>
1273 {
1274 private:
1275   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)> super;
1276 
1277 public:
1278   typedef super key_hasher_tuple;
1279 
composite_key_hashboost::multi_index::composite_key_hash1280   composite_key_hash(
1281     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Hash)):
1282     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
1283   {}
1284 
composite_key_hashboost::multi_index::composite_key_hash1285   composite_key_hash(const key_hasher_tuple& x):super(x){}
1286 
key_hash_functionsboost::multi_index::composite_key_hash1287   const key_hasher_tuple& key_hash_functions()const{return *this;}
key_hash_functionsboost::multi_index::composite_key_hash1288   key_hasher_tuple&       key_hash_functions(){return *this;}
1289 
1290   template<typename CompositeKey>
operator ()boost::multi_index::composite_key_hash1291   std::size_t operator()(const composite_key_result<CompositeKey> & x)const
1292   {
1293     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1294     typedef typename CompositeKey::value_type          value_type;
1295 
1296     BOOST_STATIC_ASSERT(
1297       tuples::length<key_extractor_tuple>::value==
1298       tuples::length<key_hasher_tuple>::value);
1299 
1300     return detail::hash_ckey<
1301       key_extractor_tuple,value_type,
1302       key_hasher_tuple
1303     >::hash(x.composite_key.key_extractors(),x.value,key_hash_functions());
1304   }
1305 
1306   template<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)>
operator ()boost::multi_index::composite_key_hash1307   std::size_t operator()(
1308     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x)const
1309   {
1310     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1311 
1312     BOOST_STATIC_ASSERT(
1313       tuples::length<key_tuple>::value==
1314       tuples::length<key_hasher_tuple>::value);
1315 
1316     return detail::hash_cval<
1317       key_tuple,key_hasher_tuple
1318     >::hash(x,key_hash_functions());
1319   }
1320 
1321 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
1322     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1323   template<typename... Values>
operator ()boost::multi_index::composite_key_hash1324   std::size_t operator()(const std::tuple<Values...>& x)const
1325   {
1326     typedef std::tuple<Values...>                key_tuple;
1327     typedef typename detail::cons_stdtuple_ctor<
1328       key_tuple>::result_type                    cons_key_tuple;
1329 
1330     BOOST_STATIC_ASSERT(
1331       std::tuple_size<key_tuple>::value==
1332       static_cast<std::size_t>(tuples::length<key_hasher_tuple>::value));
1333 
1334     return detail::hash_cval<
1335       cons_key_tuple,key_hasher_tuple
1336     >::hash(detail::make_cons_stdtuple(x),key_hash_functions());
1337   }
1338 #endif
1339 };
1340 
1341 /* Instantiations of the former functors with "natural" basic components:
1342  * composite_key_result_equal_to uses std::equal_to of the values.
1343  * composite_key_result_less     uses std::less.
1344  * composite_key_result_greater  uses std::greater.
1345  * composite_key_result_hash     uses boost::hash.
1346  */
1347 
1348 #define BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER                           \
1349 composite_key_equal_to<                                                      \
1350     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1351       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1352       /* the argument is a PP list */                                        \
1353       (detail::nth_composite_key_equal_to,                                   \
1354         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1355           BOOST_PP_NIL)))                                                    \
1356   >
1357 
1358 template<typename CompositeKeyResult>
1359 struct composite_key_result_equal_to:
1360 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1361 BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
1362 {
1363 private:
1364   typedef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER super;
1365 
1366 public:
1367   typedef CompositeKeyResult  first_argument_type;
1368   typedef first_argument_type second_argument_type;
1369   typedef bool                result_type;
1370 
1371   using super::operator();
1372 };
1373 
1374 #define BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER                               \
1375 composite_key_compare<                                                       \
1376     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1377       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1378       /* the argument is a PP list */                                        \
1379       (detail::nth_composite_key_less,                                       \
1380         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1381           BOOST_PP_NIL)))                                                    \
1382   >
1383 
1384 template<typename CompositeKeyResult>
1385 struct composite_key_result_less:
1386 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1387 BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
1388 {
1389 private:
1390   typedef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER super;
1391 
1392 public:
1393   typedef CompositeKeyResult  first_argument_type;
1394   typedef first_argument_type second_argument_type;
1395   typedef bool                result_type;
1396 
1397   using super::operator();
1398 };
1399 
1400 #define BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER                            \
1401 composite_key_compare<                                                       \
1402     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1403       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1404       /* the argument is a PP list */                                        \
1405       (detail::nth_composite_key_greater,                                    \
1406         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1407           BOOST_PP_NIL)))                                                    \
1408   >
1409 
1410 template<typename CompositeKeyResult>
1411 struct composite_key_result_greater:
1412 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1413 BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
1414 {
1415 private:
1416   typedef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER super;
1417 
1418 public:
1419   typedef CompositeKeyResult  first_argument_type;
1420   typedef first_argument_type second_argument_type;
1421   typedef bool                result_type;
1422 
1423   using super::operator();
1424 };
1425 
1426 #define BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER                               \
1427 composite_key_hash<                                                          \
1428     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1429       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1430       /* the argument is a PP list */                                        \
1431       (detail::nth_composite_key_hash,                                       \
1432         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1433           BOOST_PP_NIL)))                                                    \
1434   >
1435 
1436 template<typename CompositeKeyResult>
1437 struct composite_key_result_hash:
1438 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1439 BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
1440 {
1441 private:
1442   typedef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER super;
1443 
1444 public:
1445   typedef CompositeKeyResult argument_type;
1446   typedef std::size_t        result_type;
1447 
1448   using super::operator();
1449 };
1450 
1451 } /* namespace multi_index */
1452 
1453 } /* namespace boost */
1454 
1455 /* Specializations of std::equal_to, std::less, std::greater and boost::hash
1456  * for composite_key_results enabling interoperation with tuples of values.
1457  */
1458 
1459 namespace std{
1460 
1461 template<typename CompositeKey>
1462 struct equal_to<boost::multi_index::composite_key_result<CompositeKey> >:
1463   boost::multi_index::composite_key_result_equal_to<
1464     boost::multi_index::composite_key_result<CompositeKey>
1465   >
1466 {
1467 };
1468 
1469 template<typename CompositeKey>
1470 struct less<boost::multi_index::composite_key_result<CompositeKey> >:
1471   boost::multi_index::composite_key_result_less<
1472     boost::multi_index::composite_key_result<CompositeKey>
1473   >
1474 {
1475 };
1476 
1477 template<typename CompositeKey>
1478 struct greater<boost::multi_index::composite_key_result<CompositeKey> >:
1479   boost::multi_index::composite_key_result_greater<
1480     boost::multi_index::composite_key_result<CompositeKey>
1481   >
1482 {
1483 };
1484 
1485 } /* namespace std */
1486 
1487 namespace boost{
1488 
1489 template<typename CompositeKey>
1490 struct hash<boost::multi_index::composite_key_result<CompositeKey> >:
1491   boost::multi_index::composite_key_result_hash<
1492     boost::multi_index::composite_key_result<CompositeKey>
1493   >
1494 {
1495 };
1496 
1497 } /* namespace boost */
1498 
1499 #undef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
1500 #undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
1501 #undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
1502 #undef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
1503 #undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
1504 #undef BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO
1505 #undef BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR
1506 #undef BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N
1507 #undef BOOST_MULTI_INDEX_CK_CTOR_ARG
1508 #undef BOOST_MULTI_INDEX_CK_TEMPLATE_PARM
1509 #undef BOOST_MULTI_INDEX_CK_ENUM_PARAMS
1510 #undef BOOST_MULTI_INDEX_CK_ENUM
1511 #undef BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE
1512 
1513 #endif
1514