source: NonGTP/Boost/boost/multi_index/composite_key.hpp @ 857

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