epoc32/include/stdapis/boost/multi_index/composite_key.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     1 /* Copyright 2003-2006 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 <boost/utility/enable_if.hpp>
    33 #include <functional>
    34 
    35 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
    36 #include <boost/ref.hpp>
    37 #endif
    38 
    39 #if !defined(BOOST_NO_SFINAE)
    40 #include <boost/type_traits/is_convertible.hpp>
    41 #endif
    42 
    43 /* A composite key stores n key extractors and "computes" the
    44  * result on a given value as a packed reference to the value and
    45  * the composite key itself. Actual invocations to the component
    46  * key extractors are lazily performed when executing an operation
    47  * on composite_key results (equality, comparison, hashing.)
    48  * As the other key extractors in Boost.MultiIndex, composite_key<T,...>
    49  * is  overloaded to work on chained pointers to T and reference_wrappers
    50  * of T.
    51  */
    52 
    53 /* This user_definable macro limits the number of elements of a composite
    54  * key; useful for shortening resulting symbol names (MSVC++ 6.0, for
    55  * instance has problems coping with very long symbol names.)
    56  * NB: This cannot exceed the maximum number of arguments of
    57  * boost::tuple. In Boost 1.32, the limit is 10.
    58  */
    59 
    60 #if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
    61 #if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
    62 #define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 5
    63 #else
    64 #define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
    65 #endif
    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 template<class T> struct hash; /* 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