Add Boost.Test karmic valgrind suppressions
[senf.git] / boost / multi_index / composite_key.hpp
1 /* Copyright 2003-2007 Joaquín M López Muñoz.
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)&&(_MSC_VER>=1200)
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.hpp>
18 #include <boost/multi_index/detail/access_specifier.hpp>
19 #include <boost/multi_index/detail/prevent_eti.hpp>
20 #include <boost/mpl/eval_if.hpp>
21 #include <boost/mpl/identity.hpp>
22 #include <boost/mpl/if.hpp>
23 #include <boost/mpl/or.hpp>
24 #include <boost/mpl/aux_/nttp_decl.hpp>
25 #include <boost/preprocessor/cat.hpp>
26 #include <boost/preprocessor/control/expr_if.hpp>
27 #include <boost/preprocessor/list/at.hpp>
28 #include <boost/preprocessor/repetition/enum.hpp>
29 #include <boost/preprocessor/repetition/enum_params.hpp> 
30 #include <boost/static_assert.hpp>
31 #include <boost/tuple/tuple.hpp>
32 #include <boost/type_traits/is_same.hpp>
33 #include <boost/utility/enable_if.hpp>
34 #include <functional>
35
36 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
37 #include <boost/ref.hpp>
38 #endif
39
40 #if !defined(BOOST_NO_SFINAE)
41 #include <boost/type_traits/is_convertible.hpp>
42 #endif
43
44 /* A composite key stores n key extractors and "computes" the
45  * result on a given value as a packed reference to the value and
46  * the composite key itself. Actual invocations to the component
47  * key extractors are lazily performed when executing an operation
48  * on composite_key results (equality, comparison, hashing.)
49  * As the other key extractors in Boost.MultiIndex, composite_key<T,...>
50  * is  overloaded to work on chained pointers to T and reference_wrappers
51  * of T.
52  */
53
54 /* This user_definable macro limits the number of elements of a composite
55  * key; useful for shortening resulting symbol names (MSVC++ 6.0, for
56  * instance has problems coping with very long symbol names.)
57  * NB: This cannot exceed the maximum number of arguments of
58  * boost::tuple. In Boost 1.32, the limit is 10.
59  */
60
61 #if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
62 #if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
63 #define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 5
64 #else
65 #define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
66 #endif
67 #endif
68
69 /* maximum number of key extractors in a composite key */
70
71 #if BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE<10 /* max length of a tuple */
72 #define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE \
73   BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE
74 #else
75 #define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE 10
76 #endif
77
78 /* BOOST_PP_ENUM of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
79
80 #define BOOST_MULTI_INDEX_CK_ENUM(macro,data)                                \
81   BOOST_PP_ENUM(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,macro,data)
82
83 /* BOOST_PP_ENUM_PARAMS of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
84
85 #define BOOST_MULTI_INDEX_CK_ENUM_PARAMS(param)                              \
86   BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,param)
87
88 /* if n==0 ->   text0
89  * otherwise -> textn=tuples::null_type
90  */
91
92 #define BOOST_MULTI_INDEX_CK_TEMPLATE_PARM(z,n,text)                         \
93   typename BOOST_PP_CAT(text,n) BOOST_PP_EXPR_IF(n,=tuples::null_type)
94
95 /* const textn& kn=textn() */
96
97 #define BOOST_MULTI_INDEX_CK_CTOR_ARG(z,n,text)                              \
98   const BOOST_PP_CAT(text,n)& BOOST_PP_CAT(k,n) = BOOST_PP_CAT(text,n)()
99
100 /* typename list(0)<list(1),n>::type */
101
102 #define BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N(z,n,list)                  \
103   BOOST_DEDUCED_TYPENAME BOOST_PP_LIST_AT(list,0)<                           \
104     BOOST_PP_LIST_AT(list,1),n                                               \
105   >::type
106
107 namespace boost{
108
109 template<class T> class reference_wrapper; /* fwd decl. */
110
111 namespace multi_index{
112
113 namespace detail{
114
115 /* n-th key extractor of a composite key */
116
117 template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>
118 struct nth_key_from_value
119 {
120   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
121   typedef typename prevent_eti<
122     tuples::element<N,key_extractor_tuple>,
123     typename mpl::eval_if_c<
124       N<tuples::length<key_extractor_tuple>::value,
125       tuples::element<N,key_extractor_tuple>,
126       mpl::identity<tuples::null_type>
127     >::type
128   >::type                                            type;
129 };
130
131 /* nth_composite_key_##name<CompositeKey,N>::type yields
132  * functor<nth_key_from_value<CompositeKey,N> >, or tuples::null_type
133  * if N exceeds the length of the composite key.
134  */
135
136 #define BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(name,functor)         \
137 template<typename KeyFromValue>                                              \
138 struct BOOST_PP_CAT(key_,name)                                               \
139 {                                                                            \
140   typedef functor<typename KeyFromValue::result_type> type;                  \
141 };                                                                           \
142                                                                              \
143 template<>                                                                   \
144 struct BOOST_PP_CAT(key_,name)<tuples::null_type>                            \
145 {                                                                            \
146   typedef tuples::null_type type;                                            \
147 };                                                                           \
148                                                                              \
149 template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>              \
150 struct BOOST_PP_CAT(nth_composite_key_,name)                                 \
151 {                                                                            \
152   typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;  \
153   typedef typename BOOST_PP_CAT(key_,name)<key_from_value>::type type;       \
154 };
155
156 /* nth_composite_key_equal_to
157  * nth_composite_key_less
158  * nth_composite_key_greater
159  * nth_composite_key_hash
160  */
161
162 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(equal_to,std::equal_to)
163 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(less,std::less)
164 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(greater,std::greater)
165 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(hash,boost::hash)
166
167 /* used for defining equality and comparison ops of composite_key_result */
168
169 #define BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO(z,n,text) text
170
171 struct generic_operator_equal
172 {
173   template<typename T,typename Q>
174   bool operator()(const T& x,const Q& y)const{return x==y;}
175 };
176
177 typedef tuple<
178   BOOST_MULTI_INDEX_CK_ENUM(
179     BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
180     detail::generic_operator_equal)>          generic_operator_equal_tuple;
181
182 struct generic_operator_less
183 {
184   template<typename T,typename Q>
185   bool operator()(const T& x,const Q& y)const{return x<y;}
186 };
187
188 typedef tuple<
189   BOOST_MULTI_INDEX_CK_ENUM(
190     BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
191     detail::generic_operator_less)>           generic_operator_less_tuple;
192
193 /* Metaprogramming machinery for implementing equality, comparison and
194  * hashing operations of composite_key_result.
195  *
196  * equal_* checks for equality between composite_key_results and
197  * between those and tuples, accepting a tuple of basic equality functors.
198  * compare_* does lexicographical comparison.
199  * hash_* computes a combination of elementwise hash values.
200  */
201
202 template
203 <
204   typename KeyCons1,typename Value1,
205   typename KeyCons2, typename Value2,
206   typename EqualCons
207 >
208 struct equal_ckey_ckey; /* fwd decl. */
209
210 template
211 <
212   typename KeyCons1,typename Value1,
213   typename KeyCons2, typename Value2,
214   typename EqualCons
215 >
216 struct equal_ckey_ckey_terminal
217 {
218   static bool compare(
219     const KeyCons1&,const Value1&,
220     const KeyCons2&,const Value2&,
221     const EqualCons&)
222   {
223     return true;
224   }
225 };
226
227 template
228 <
229   typename KeyCons1,typename Value1,
230   typename KeyCons2, typename Value2,
231   typename EqualCons
232 >
233 struct equal_ckey_ckey_normal
234 {
235   static bool compare(
236     const KeyCons1& c0,const Value1& v0,
237     const KeyCons2& c1,const Value2& v1,
238     const EqualCons& eq)
239   {
240     if(!eq.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return false;
241     return equal_ckey_ckey<
242       BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
243       BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
244       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
245     >::compare(c0.get_tail(),v0,c1.get_tail(),v1,eq.get_tail());
246   }
247 };
248
249 template
250 <
251   typename KeyCons1,typename Value1,
252   typename KeyCons2, typename Value2,
253   typename EqualCons
254 >
255 struct equal_ckey_ckey:
256   mpl::if_<
257     mpl::or_<
258       is_same<KeyCons1,tuples::null_type>,
259       is_same<KeyCons2,tuples::null_type>
260     >,
261     equal_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>,
262     equal_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>
263   >::type
264 {
265 };
266
267 template
268 <
269   typename KeyCons,typename Value,
270   typename ValCons,typename EqualCons
271 >
272 struct equal_ckey_cval; /* fwd decl. */
273
274 template
275 <
276   typename KeyCons,typename Value,
277   typename ValCons,typename EqualCons
278 >
279 struct equal_ckey_cval_terminal
280 {
281   static bool compare(
282     const KeyCons&,const Value&,const ValCons&,const EqualCons&)
283   {
284     return true;
285   }
286
287   static bool compare(
288     const ValCons&,const KeyCons&,const Value&,const EqualCons&)
289   {
290     return true;
291   }
292 };
293
294 template
295 <
296   typename KeyCons,typename Value,
297   typename ValCons,typename EqualCons
298 >
299 struct equal_ckey_cval_normal
300 {
301   static bool compare(
302     const KeyCons& c,const Value& v,const ValCons& vc,
303     const EqualCons& eq)
304   {
305     if(!eq.get_head()(c.get_head()(v),vc.get_head()))return false;
306     return equal_ckey_cval<
307       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
308       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
309       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
310     >::compare(c.get_tail(),v,vc.get_tail(),eq.get_tail());
311   }
312
313   static bool compare(
314     const ValCons& vc,const KeyCons& c,const Value& v,
315     const EqualCons& eq)
316   {
317     if(!eq.get_head()(vc.get_head(),c.get_head()(v)))return false;
318     return equal_ckey_cval<
319       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
320       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
321       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
322     >::compare(vc.get_tail(),c.get_tail(),v,eq.get_tail());
323   }
324 };
325
326 template
327 <
328   typename KeyCons,typename Value,
329   typename ValCons,typename EqualCons
330 >
331 struct equal_ckey_cval:
332   mpl::if_<
333     mpl::or_<
334       is_same<KeyCons,tuples::null_type>,
335       is_same<ValCons,tuples::null_type>
336     >,
337     equal_ckey_cval_terminal<KeyCons,Value,ValCons,EqualCons>,
338     equal_ckey_cval_normal<KeyCons,Value,ValCons,EqualCons>
339   >::type
340 {
341 };
342
343 template
344 <
345   typename KeyCons1,typename Value1,
346   typename KeyCons2, typename Value2,
347   typename CompareCons
348 >
349 struct compare_ckey_ckey; /* fwd decl. */
350
351 template
352 <
353   typename KeyCons1,typename Value1,
354   typename KeyCons2, typename Value2,
355   typename CompareCons
356 >
357 struct compare_ckey_ckey_terminal
358 {
359   static bool compare(
360     const KeyCons1&,const Value1&,
361     const KeyCons2&,const Value2&,
362     const CompareCons&)
363   {
364     return false;
365   }
366 };
367
368 template
369 <
370   typename KeyCons1,typename Value1,
371   typename KeyCons2, typename Value2,
372   typename CompareCons
373 >
374 struct compare_ckey_ckey_normal
375 {
376   static bool compare(
377     const KeyCons1& c0,const Value1& v0,
378     const KeyCons2& c1,const Value2& v1,
379     const CompareCons& comp)
380   {
381     if(comp.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return true;
382     if(comp.get_head()(c1.get_head()(v1),c0.get_head()(v0)))return false;
383     return compare_ckey_ckey<
384       BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
385       BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
386       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
387     >::compare(c0.get_tail(),v0,c1.get_tail(),v1,comp.get_tail());
388   }
389 };
390
391 template
392 <
393   typename KeyCons1,typename Value1,
394   typename KeyCons2, typename Value2,
395   typename CompareCons
396 >
397 struct compare_ckey_ckey:
398   mpl::if_<
399     mpl::or_<
400       is_same<KeyCons1,tuples::null_type>,
401       is_same<KeyCons2,tuples::null_type>
402     >,
403     compare_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>,
404     compare_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>
405   >::type
406 {
407 };
408
409 template
410 <
411   typename KeyCons,typename Value,
412   typename ValCons,typename CompareCons
413 >
414 struct compare_ckey_cval; /* fwd decl. */
415
416 template
417 <
418   typename KeyCons,typename Value,
419   typename ValCons,typename CompareCons
420 >
421 struct compare_ckey_cval_terminal
422 {
423   static bool compare(
424     const KeyCons&,const Value&,const ValCons&,const CompareCons&)
425   {
426     return false;
427   }
428
429   static bool compare(
430     const ValCons&,const KeyCons&,const Value&,const CompareCons&)
431   {
432     return false;
433   }
434 };
435
436 template
437 <
438   typename KeyCons,typename Value,
439   typename ValCons,typename CompareCons
440 >
441 struct compare_ckey_cval_normal
442 {
443   static bool compare(
444     const KeyCons& c,const Value& v,const ValCons& vc,
445     const CompareCons& comp)
446   {
447     if(comp.get_head()(c.get_head()(v),vc.get_head()))return true;
448     if(comp.get_head()(vc.get_head(),c.get_head()(v)))return false;
449     return compare_ckey_cval<
450       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
451       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
452       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
453     >::compare(c.get_tail(),v,vc.get_tail(),comp.get_tail());
454   }
455
456   static bool compare(
457     const ValCons& vc,const KeyCons& c,const Value& v,
458     const CompareCons& comp)
459   {
460     if(comp.get_head()(vc.get_head(),c.get_head()(v)))return true;
461     if(comp.get_head()(c.get_head()(v),vc.get_head()))return false;
462     return compare_ckey_cval<
463       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
464       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
465       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
466     >::compare(vc.get_tail(),c.get_tail(),v,comp.get_tail());
467   }
468 };
469
470 template
471 <
472   typename KeyCons,typename Value,
473   typename ValCons,typename CompareCons
474 >
475 struct compare_ckey_cval:
476   mpl::if_<
477     mpl::or_<
478       is_same<KeyCons,tuples::null_type>,
479       is_same<ValCons,tuples::null_type>
480     >,
481     compare_ckey_cval_terminal<KeyCons,Value,ValCons,CompareCons>,
482     compare_ckey_cval_normal<KeyCons,Value,ValCons,CompareCons>
483   >::type
484 {
485 };
486
487 template<typename KeyCons,typename Value,typename HashCons>
488 struct hash_ckey; /* fwd decl. */
489
490 template<typename KeyCons,typename Value,typename HashCons>
491 struct hash_ckey_terminal
492 {
493   static std::size_t hash(
494     const KeyCons&,const Value&,const HashCons&,std::size_t carry)
495   {
496     return carry;
497   }
498 };
499
500 template<typename KeyCons,typename Value,typename HashCons>
501 struct hash_ckey_normal
502 {
503   static std::size_t hash(
504     const KeyCons& c,const Value& v,const HashCons& h,std::size_t carry=0)
505   {
506     /* same hashing formula as boost::hash_combine */
507
508     carry^=h.get_head()(c.get_head()(v))+0x9e3779b9+(carry<<6)+(carry>>2);
509     return hash_ckey<
510       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
511       BOOST_DEDUCED_TYPENAME HashCons::tail_type
512     >::hash(c.get_tail(),v,h.get_tail(),carry);
513   }
514 };
515
516 template<typename KeyCons,typename Value,typename HashCons>
517 struct hash_ckey:
518   mpl::if_<
519     is_same<KeyCons,tuples::null_type>,
520     hash_ckey_terminal<KeyCons,Value,HashCons>,
521     hash_ckey_normal<KeyCons,Value,HashCons>
522   >::type
523 {
524 };
525
526 template<typename ValCons,typename HashCons>
527 struct hash_cval; /* fwd decl. */
528
529 template<typename ValCons,typename HashCons>
530 struct hash_cval_terminal
531 {
532   static std::size_t hash(const ValCons&,const HashCons&,std::size_t carry)
533   {
534     return carry;
535   }
536 };
537
538 template<typename ValCons,typename HashCons>
539 struct hash_cval_normal
540 {
541   static std::size_t hash(
542     const ValCons& vc,const HashCons& h,std::size_t carry=0)
543   {
544     carry^=h.get_head()(vc.get_head())+0x9e3779b9+(carry<<6)+(carry>>2);
545     return hash_cval<
546       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
547       BOOST_DEDUCED_TYPENAME HashCons::tail_type
548     >::hash(vc.get_tail(),h.get_tail(),carry);
549   }
550 };
551
552 template<typename ValCons,typename HashCons>
553 struct hash_cval:
554   mpl::if_<
555     is_same<ValCons,tuples::null_type>,
556     hash_cval_terminal<ValCons,HashCons>,
557     hash_cval_normal<ValCons,HashCons>
558   >::type
559 {
560 };
561
562 } /* namespace multi_index::detail */
563
564 /* composite_key_result */
565
566 template<typename CompositeKey>
567 struct composite_key_result
568 {
569   typedef CompositeKey                            composite_key_type;
570   typedef typename composite_key_type::value_type value_type;
571
572   composite_key_result(
573     const composite_key_type& composite_key_,const value_type& value_):
574     composite_key(composite_key_),value(value_)
575   {}
576
577   const composite_key_type& composite_key;
578   const value_type&         value;
579 };
580
581 /* composite_key */
582
583 /* NB. Some overloads of operator() have an extra dummy parameter int=0.
584  * This disambiguator serves several purposes:
585  *  - Without it, MSVC++ 6.0 incorrectly regards some overloads as
586  *    specializations of a previous member function template.
587  *  - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
588  *    as if they have the same signature.
589  *  - If remove_const is broken due to lack of PTS, int=0 avoids the
590  *    declaration of memfuns with identical signature.
591  */
592
593 template<
594   typename Value,
595   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,KeyFromValue)
596 >
597 struct composite_key:
598   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)>
599 {
600 private:
601   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)> super;
602
603 public:
604   typedef super                               key_extractor_tuple;
605   typedef Value                               value_type;
606   typedef composite_key_result<composite_key> result_type;
607
608   composite_key(
609     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,KeyFromValue)):
610     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
611   {}
612
613   composite_key(const key_extractor_tuple& x):super(x){}
614
615   const key_extractor_tuple& key_extractors()const{return *this;}
616   key_extractor_tuple&       key_extractors(){return *this;}
617
618   template<typename ChainedPtr>
619
620 #if !defined(BOOST_NO_SFINAE)
621   typename disable_if<
622     is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
623 #else
624   result_type
625 #endif
626
627   operator()(const ChainedPtr& x)const
628   {
629     return operator()(*x);
630   }
631
632   result_type operator()(const value_type& x)const
633   {
634     return result_type(*this,x);
635   }
636
637   result_type operator()(const reference_wrapper<const value_type>& x)const
638   {
639     return result_type(*this,x.get());
640   }
641
642   result_type operator()(const reference_wrapper<value_type>& x,int=0)const
643   {
644     return result_type(*this,x.get());
645   }
646 };
647
648 /* comparison operators */
649
650 /* == */
651
652 template<typename CompositeKey1,typename CompositeKey2>
653 inline bool operator==(
654   const composite_key_result<CompositeKey1>& x,
655   const composite_key_result<CompositeKey2>& y)
656 {
657   typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
658   typedef typename CompositeKey1::value_type          value_type1;
659   typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
660   typedef typename CompositeKey2::value_type          value_type2;
661
662   BOOST_STATIC_ASSERT(
663     tuples::length<key_extractor_tuple1>::value==
664     tuples::length<key_extractor_tuple2>::value);
665
666   return detail::equal_ckey_ckey<
667     key_extractor_tuple1,value_type1,
668     key_extractor_tuple2,value_type2,
669     detail::generic_operator_equal_tuple
670   >::compare(
671     x.composite_key.key_extractors(),x.value,
672     y.composite_key.key_extractors(),y.value,
673     detail::generic_operator_equal_tuple());
674 }
675
676 template<
677   typename CompositeKey,
678   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
679 >
680 inline bool operator==(
681   const composite_key_result<CompositeKey>& x,
682   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
683 {
684   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
685   typedef typename CompositeKey::value_type              value_type;
686   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
687   
688   BOOST_STATIC_ASSERT(
689     tuples::length<key_extractor_tuple>::value==
690     tuples::length<key_tuple>::value);
691
692   return detail::equal_ckey_cval<
693     key_extractor_tuple,value_type,
694     key_tuple,detail::generic_operator_equal_tuple
695   >::compare(
696     x.composite_key.key_extractors(),x.value,
697     y,detail::generic_operator_equal_tuple());
698 }
699
700 template
701 <
702   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
703   typename CompositeKey
704 >
705 inline bool operator==(
706   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
707   const composite_key_result<CompositeKey>& y)
708 {
709   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
710   typedef typename CompositeKey::value_type              value_type;
711   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
712   
713   BOOST_STATIC_ASSERT(
714     tuples::length<key_extractor_tuple>::value==
715     tuples::length<key_tuple>::value);
716
717   return detail::equal_ckey_cval<
718     key_extractor_tuple,value_type,
719     key_tuple,detail::generic_operator_equal_tuple
720   >::compare(
721     x,y.composite_key.key_extractors(),
722     y.value,detail::generic_operator_equal_tuple());
723 }
724
725 /* < */
726
727 template<typename CompositeKey1,typename CompositeKey2>
728 inline bool operator<(
729   const composite_key_result<CompositeKey1>& x,
730   const composite_key_result<CompositeKey2>& y)
731 {
732   typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
733   typedef typename CompositeKey1::value_type          value_type1;
734   typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
735   typedef typename CompositeKey2::value_type          value_type2;
736
737   return detail::compare_ckey_ckey<
738    key_extractor_tuple1,value_type1,
739    key_extractor_tuple2,value_type2,
740    detail::generic_operator_less_tuple
741   >::compare(
742     x.composite_key.key_extractors(),x.value,
743     y.composite_key.key_extractors(),y.value,
744     detail::generic_operator_less_tuple());
745 }
746
747 template
748 <
749   typename CompositeKey,
750   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
751 >
752 inline bool operator<(
753   const composite_key_result<CompositeKey>& x,
754   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
755 {
756   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
757   typedef typename CompositeKey::value_type              value_type;
758   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
759   
760   return detail::compare_ckey_cval<
761     key_extractor_tuple,value_type,
762     key_tuple,detail::generic_operator_less_tuple
763   >::compare(
764     x.composite_key.key_extractors(),x.value,
765     y,detail::generic_operator_less_tuple());
766 }
767
768 template
769 <
770   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
771   typename CompositeKey
772 >
773 inline bool operator<(
774   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
775   const composite_key_result<CompositeKey>& y)
776 {
777   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
778   typedef typename CompositeKey::value_type              value_type;
779   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
780   
781   return detail::compare_ckey_cval<
782     key_extractor_tuple,value_type,
783     key_tuple,detail::generic_operator_less_tuple
784   >::compare(
785     x,y.composite_key.key_extractors(),
786     y.value,detail::generic_operator_less_tuple());
787 }
788
789 /* rest of comparison operators */
790
791 #define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2)                  \
792 template<t1,t2> inline bool operator!=(const a1& x,const a2& y)              \
793 {                                                                            \
794   return !(x==y);                                                            \
795 }                                                                            \
796                                                                              \
797 template<t1,t2> inline bool operator>(const a1& x,const a2& y)               \
798 {                                                                            \
799   return y<x;                                                                \
800 }                                                                            \
801                                                                              \
802 template<t1,t2> inline bool operator>=(const a1& x,const a2& y)              \
803 {                                                                            \
804   return !(x<y);                                                             \
805 }                                                                            \
806                                                                              \
807 template<t1,t2> inline bool operator<=(const a1& x,const a2& y)              \
808 {                                                                            \
809   return !(y<x);                                                             \
810 }
811
812 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
813   typename CompositeKey1,
814   typename CompositeKey2,
815   composite_key_result<CompositeKey1>,
816   composite_key_result<CompositeKey2>
817 )
818
819 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
820   typename CompositeKey,
821   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
822   composite_key_result<CompositeKey>,
823   tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>
824 )
825
826 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
827   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
828   typename CompositeKey,
829   tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>,
830   composite_key_result<CompositeKey>
831 )
832
833 /* composite_key_equal_to */
834
835 template
836 <
837   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Pred)
838 >
839 struct composite_key_equal_to:
840   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)>
841 {
842 private:
843   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)> super;
844
845 public:
846   typedef super key_eq_tuple;
847
848   composite_key_equal_to(
849     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Pred)):
850     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
851   {}
852
853   composite_key_equal_to(const key_eq_tuple& x):super(x){}
854
855   const key_eq_tuple& key_eqs()const{return *this;}
856   key_eq_tuple&       key_eqs(){return *this;}
857
858   template<typename CompositeKey1,typename CompositeKey2>
859   bool operator()(
860     const composite_key_result<CompositeKey1> & x,
861     const composite_key_result<CompositeKey2> & y)const
862   {
863     typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
864     typedef typename CompositeKey1::value_type          value_type1;
865     typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
866     typedef typename CompositeKey2::value_type          value_type2;
867
868     BOOST_STATIC_ASSERT(
869       tuples::length<key_extractor_tuple1>::value<=
870       tuples::length<key_eq_tuple>::value&&
871       tuples::length<key_extractor_tuple1>::value==
872       tuples::length<key_extractor_tuple2>::value);
873
874     return detail::equal_ckey_ckey<
875       key_extractor_tuple1,value_type1,
876       key_extractor_tuple2,value_type2,
877       key_eq_tuple
878     >::compare(
879       x.composite_key.key_extractors(),x.value,
880       y.composite_key.key_extractors(),y.value,
881       key_eqs());
882   }
883   
884   template
885   <
886     typename CompositeKey,
887     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
888   >
889   bool operator()(
890     const composite_key_result<CompositeKey>& x,
891     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
892   {
893     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
894     typedef typename CompositeKey::value_type              value_type;
895     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
896
897     BOOST_STATIC_ASSERT(
898       tuples::length<key_extractor_tuple>::value<=
899       tuples::length<key_eq_tuple>::value&&
900       tuples::length<key_extractor_tuple>::value==
901       tuples::length<key_tuple>::value);
902
903     return detail::equal_ckey_cval<
904       key_extractor_tuple,value_type,
905       key_tuple,key_eq_tuple
906     >::compare(x.composite_key.key_extractors(),x.value,y,key_eqs());
907   }
908
909   template
910   <
911     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
912     typename CompositeKey
913   >
914   bool operator()(
915     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
916     const composite_key_result<CompositeKey>& y)const
917   {
918     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
919     typedef typename CompositeKey::value_type              value_type;
920     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
921
922     BOOST_STATIC_ASSERT(
923       tuples::length<key_tuple>::value<=
924       tuples::length<key_eq_tuple>::value&&
925       tuples::length<key_tuple>::value==
926       tuples::length<key_extractor_tuple>::value);
927
928     return detail::equal_ckey_cval<
929       key_extractor_tuple,value_type,
930       key_tuple,key_eq_tuple
931     >::compare(x,y.composite_key.key_extractors(),y.value,key_eqs());
932   }
933 };
934
935 /* composite_key_compare */
936
937 template
938 <
939   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Compare)
940 >
941 struct composite_key_compare:
942   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)>
943 {
944 private:
945   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)> super;
946
947 public:
948   typedef super key_comp_tuple;
949
950   composite_key_compare(
951     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Compare)):
952     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
953   {}
954
955   composite_key_compare(const key_comp_tuple& x):super(x){}
956
957   const key_comp_tuple& key_comps()const{return *this;}
958   key_comp_tuple&       key_comps(){return *this;}
959
960   template<typename CompositeKey1,typename CompositeKey2>
961   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_comp_tuple>::value||
973       tuples::length<key_extractor_tuple2>::value<=
974       tuples::length<key_comp_tuple>::value);
975
976     return detail::compare_ckey_ckey<
977       key_extractor_tuple1,value_type1,
978       key_extractor_tuple2,value_type2,
979       key_comp_tuple
980     >::compare(
981       x.composite_key.key_extractors(),x.value,
982       y.composite_key.key_extractors(),y.value,
983       key_comps());
984   }
985   
986 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
987   template<typename CompositeKey,typename Value>
988   bool operator()(
989     const composite_key_result<CompositeKey>& x,
990     const Value& y)const
991   {
992     return operator()(x,make_tuple(cref(y)));
993   }
994 #endif
995
996   template
997   <
998     typename CompositeKey,
999     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
1000   >
1001   bool operator()(
1002     const composite_key_result<CompositeKey>& x,
1003     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
1004   {
1005     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
1006     typedef typename CompositeKey::value_type              value_type;
1007     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1008
1009     BOOST_STATIC_ASSERT(
1010       tuples::length<key_extractor_tuple>::value<=
1011       tuples::length<key_comp_tuple>::value||
1012       tuples::length<key_tuple>::value<=
1013       tuples::length<key_comp_tuple>::value);
1014
1015     return detail::compare_ckey_cval<
1016       key_extractor_tuple,value_type,
1017       key_tuple,key_comp_tuple
1018     >::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
1019   }
1020
1021 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
1022   template<typename Value,typename CompositeKey>
1023   bool operator()(
1024     const Value& x,
1025     const composite_key_result<CompositeKey>& y)const
1026   {
1027     return operator()(make_tuple(cref(x)),y);
1028   }
1029 #endif
1030
1031   template
1032   <
1033     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
1034     typename CompositeKey
1035   >
1036   bool operator()(
1037     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
1038     const composite_key_result<CompositeKey>& y)const
1039   {
1040     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
1041     typedef typename CompositeKey::value_type              value_type;
1042     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1043
1044     BOOST_STATIC_ASSERT(
1045       tuples::length<key_tuple>::value<=
1046       tuples::length<key_comp_tuple>::value||
1047       tuples::length<key_extractor_tuple>::value<=
1048       tuples::length<key_comp_tuple>::value);
1049
1050     return detail::compare_ckey_cval<
1051       key_extractor_tuple,value_type,
1052       key_tuple,key_comp_tuple
1053     >::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
1054   }
1055 };
1056
1057 /* composite_key_hash */
1058
1059 template
1060 <
1061   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Hash)
1062 >
1063 struct composite_key_hash:
1064   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)>
1065 {
1066 private:
1067   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)> super;
1068
1069 public:
1070   typedef super key_hasher_tuple;
1071
1072   composite_key_hash(
1073     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Hash)):
1074     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
1075   {}
1076
1077   composite_key_hash(const key_hasher_tuple& x):super(x){}
1078
1079   const key_hasher_tuple& key_hash_functions()const{return *this;}
1080   key_hasher_tuple&       key_hash_functions(){return *this;}
1081
1082   template<typename CompositeKey>
1083   std::size_t operator()(const composite_key_result<CompositeKey> & x)const
1084   {
1085     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1086     typedef typename CompositeKey::value_type          value_type;
1087
1088     BOOST_STATIC_ASSERT(
1089       tuples::length<key_extractor_tuple>::value==
1090       tuples::length<key_hasher_tuple>::value);
1091
1092     return detail::hash_ckey<
1093       key_extractor_tuple,value_type,
1094       key_hasher_tuple
1095     >::hash(x.composite_key.key_extractors(),x.value,key_hash_functions());
1096   }
1097   
1098   template<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)>
1099   std::size_t operator()(
1100     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x)const
1101   {
1102     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1103
1104     BOOST_STATIC_ASSERT(
1105       tuples::length<key_tuple>::value==
1106       tuples::length<key_hasher_tuple>::value);
1107
1108     return detail::hash_cval<
1109       key_tuple,key_hasher_tuple
1110     >::hash(x,key_hash_functions());
1111   }
1112 };
1113
1114 /* Instantiations of the former functors with "natural" basic components:
1115  * composite_key_result_equal_to uses std::equal_to of the values.
1116  * composite_key_result_less     uses std::less.
1117  * composite_key_result_greater  uses std::greater.
1118  * composite_key_result_hash     uses boost::hash.
1119  */
1120
1121 #define BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER                           \
1122 composite_key_equal_to<                                                      \
1123     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1124       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1125       /* the argument is a PP list */                                        \
1126       (detail::nth_composite_key_equal_to,                                   \
1127         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1128           BOOST_PP_NIL)))                                                    \
1129   >
1130
1131 template<typename CompositeKeyResult>
1132 struct composite_key_result_equal_to:
1133 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1134 BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
1135 {
1136 private:
1137   typedef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER super;
1138
1139 public:
1140   typedef CompositeKeyResult  first_argument_type;
1141   typedef first_argument_type second_argument_type;
1142   typedef bool                result_type;
1143
1144   using super::operator();
1145 };
1146
1147 #define BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER                               \
1148 composite_key_compare<                                                       \
1149     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1150       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1151       /* the argument is a PP list */                                        \
1152       (detail::nth_composite_key_less,                                       \
1153         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1154           BOOST_PP_NIL)))                                                    \
1155   >
1156
1157 template<typename CompositeKeyResult>
1158 struct composite_key_result_less:
1159 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1160 BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
1161 {
1162 private:
1163   typedef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER super;
1164
1165 public:
1166   typedef CompositeKeyResult  first_argument_type;
1167   typedef first_argument_type second_argument_type;
1168   typedef bool                result_type;
1169
1170   using super::operator();
1171 };
1172
1173 #define BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER                            \
1174 composite_key_compare<                                                       \
1175     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1176       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1177       /* the argument is a PP list */                                        \
1178       (detail::nth_composite_key_greater,                                    \
1179         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1180           BOOST_PP_NIL)))                                                    \
1181   >
1182
1183 template<typename CompositeKeyResult>
1184 struct composite_key_result_greater:
1185 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1186 BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
1187 {
1188 private:
1189   typedef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER super;
1190
1191 public:
1192   typedef CompositeKeyResult  first_argument_type;
1193   typedef first_argument_type second_argument_type;
1194   typedef bool                result_type;
1195
1196   using super::operator();
1197 };
1198
1199 #define BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER                               \
1200 composite_key_hash<                                                          \
1201     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1202       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1203       /* the argument is a PP list */                                        \
1204       (detail::nth_composite_key_hash,                                       \
1205         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1206           BOOST_PP_NIL)))                                                    \
1207   >
1208
1209 template<typename CompositeKeyResult>
1210 struct composite_key_result_hash:
1211 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1212 BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
1213 {
1214 private:
1215   typedef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER super;
1216
1217 public:
1218   typedef CompositeKeyResult argument_type;
1219   typedef std::size_t        result_type;
1220
1221   using super::operator();
1222 };
1223
1224 } /* namespace multi_index */
1225
1226 } /* namespace boost */
1227
1228 /* Specializations of std::equal_to, std::less, std::greater and boost::hash
1229  * for composite_key_results enabling interoperation with tuples of values.
1230  */
1231
1232 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
1233 namespace std{
1234
1235 template<typename CompositeKey>
1236 struct equal_to<boost::multi_index::composite_key_result<CompositeKey> >:
1237   boost::multi_index::composite_key_result_equal_to<
1238     boost::multi_index::composite_key_result<CompositeKey>
1239   >
1240 {
1241 };
1242
1243 template<typename CompositeKey>
1244 struct less<boost::multi_index::composite_key_result<CompositeKey> >:
1245   boost::multi_index::composite_key_result_less<
1246     boost::multi_index::composite_key_result<CompositeKey>
1247   >
1248 {
1249 };
1250
1251 template<typename CompositeKey>
1252 struct greater<boost::multi_index::composite_key_result<CompositeKey> >:
1253   boost::multi_index::composite_key_result_greater<
1254     boost::multi_index::composite_key_result<CompositeKey>
1255   >
1256 {
1257 };
1258
1259 } /* namespace std */
1260
1261 namespace boost{
1262
1263 template<typename CompositeKey>
1264 struct hash<boost::multi_index::composite_key_result<CompositeKey> >:
1265   boost::multi_index::composite_key_result_hash<
1266     boost::multi_index::composite_key_result<CompositeKey>
1267   >
1268 {
1269 };
1270
1271 } /* namespace boost */
1272 #else
1273 /* Lacking template partial specialization, std::equal_to, std::less and
1274  * std::greater will still work for composite_key_results although without
1275  * tuple interoperability. To achieve the same graceful degrading with
1276  * boost::hash, we define the appropriate hash_value overload.
1277  */
1278
1279 namespace boost{
1280
1281 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1282 namespace multi_index{
1283 #endif
1284
1285 template<typename CompositeKey>
1286 inline std::size_t hash_value(
1287   const boost::multi_index::composite_key_result<CompositeKey>& x)
1288 {
1289   boost::multi_index::composite_key_result_hash<
1290     boost::multi_index::composite_key_result<CompositeKey> > h;
1291   return h(x);
1292 }
1293
1294 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1295 } /* namespace multi_index */
1296 #endif
1297
1298 } /* namespace boost */
1299 #endif
1300
1301 #undef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
1302 #undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
1303 #undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
1304 #undef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
1305 #undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
1306 #undef BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO
1307 #undef BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR
1308 #undef BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N
1309 #undef BOOST_MULTI_INDEX_CK_CTOR_ARG
1310 #undef BOOST_MULTI_INDEX_CK_TEMPLATE_PARM
1311 #undef BOOST_MULTI_INDEX_CK_ENUM_PARAMS
1312 #undef BOOST_MULTI_INDEX_CK_ENUM
1313 #undef BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE
1314
1315 #endif