Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:10

0001 /* Copyright 2003-2022 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/multi_index for library home page.
0007  */
0008 
0009 #ifndef BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
0010 #define BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0017 #include <boost/container_hash/hash_fwd.hpp>
0018 #include <boost/core/enable_if.hpp>
0019 #include <boost/multi_index/detail/access_specifier.hpp>
0020 #include <boost/mpl/eval_if.hpp>
0021 #include <boost/mpl/identity.hpp>
0022 #include <boost/mpl/if.hpp>
0023 #include <boost/mpl/or.hpp>
0024 #include <boost/preprocessor/cat.hpp>
0025 #include <boost/preprocessor/control/expr_if.hpp>
0026 #include <boost/preprocessor/list/at.hpp>
0027 #include <boost/preprocessor/repetition/enum.hpp>
0028 #include <boost/preprocessor/repetition/enum_params.hpp> 
0029 #include <boost/static_assert.hpp>
0030 #include <boost/tuple/tuple.hpp>
0031 #include <boost/type_traits/is_same.hpp>
0032 #include <functional>
0033 
0034 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
0035 #include <boost/core/ref.hpp>
0036 #endif
0037 
0038 #if !defined(BOOST_NO_SFINAE)
0039 #include <boost/type_traits/is_convertible.hpp>
0040 #endif
0041 
0042 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
0043     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0044 #include <boost/multi_index/detail/cons_stdtuple.hpp>
0045 #endif
0046 
0047 /* A composite key stores n key extractors and "computes" the
0048  * result on a given value as a packed reference to the value and
0049  * the composite key itself. Actual invocations to the component
0050  * key extractors are lazily performed when executing an operation
0051  * on composite_key results (equality, comparison, hashing.)
0052  * As the other key extractors in Boost.MultiIndex, composite_key<T,...>
0053  * is  overloaded to work on chained pointers to T and reference_wrappers
0054  * of T.
0055  */
0056 
0057 /* This user_definable macro limits the number of elements of a composite
0058  * key; useful for shortening resulting symbol names (MSVC++ 6.0, for
0059  * instance has problems coping with very long symbol names.)
0060  * NB: This cannot exceed the maximum number of arguments of
0061  * boost::tuple. In Boost 1.32, the limit is 10.
0062  */
0063 
0064 #if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
0065 #define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
0066 #endif
0067 
0068 /* maximum number of key extractors in a composite key */
0069 
0070 #if BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE<10 /* max length of a tuple */
0071 #define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE \
0072   BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE
0073 #else
0074 #define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE 10
0075 #endif
0076 
0077 /* BOOST_PP_ENUM of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
0078 
0079 #define BOOST_MULTI_INDEX_CK_ENUM(macro,data)                                \
0080   BOOST_PP_ENUM(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,macro,data)
0081 
0082 /* BOOST_PP_ENUM_PARAMS of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
0083 
0084 #define BOOST_MULTI_INDEX_CK_ENUM_PARAMS(param)                              \
0085   BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,param)
0086 
0087 /* if n==0 ->   text0
0088  * otherwise -> textn=tuples::null_type
0089  */
0090 
0091 #define BOOST_MULTI_INDEX_CK_TEMPLATE_PARM(z,n,text)                         \
0092   typename BOOST_PP_CAT(text,n) BOOST_PP_EXPR_IF(n,=tuples::null_type)
0093 
0094 /* const textn& kn=textn() */
0095 
0096 #define BOOST_MULTI_INDEX_CK_CTOR_ARG(z,n,text)                              \
0097   const BOOST_PP_CAT(text,n)& BOOST_PP_CAT(k,n) = BOOST_PP_CAT(text,n)()
0098 
0099 /* typename list(0)<list(1),n>::type */
0100 
0101 #define BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N(z,n,list)                  \
0102   BOOST_DEDUCED_TYPENAME BOOST_PP_LIST_AT(list,0)<                           \
0103     BOOST_PP_LIST_AT(list,1),n                                               \
0104   >::type
0105 
0106 namespace boost{
0107 
0108 template<class T> class reference_wrapper; /* fwd decl. */
0109 
0110 namespace multi_index{
0111 
0112 namespace detail{
0113 
0114 /* n-th key extractor of a composite key */
0115 
0116 template<typename CompositeKey,int N>
0117 struct nth_key_from_value
0118 {
0119   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
0120   typedef typename mpl::eval_if_c<
0121     N<tuples::length<key_extractor_tuple>::value,
0122     tuples::element<N,key_extractor_tuple>,
0123     mpl::identity<tuples::null_type>
0124   >::type                                            type;
0125 };
0126 
0127 /* nth_composite_key_##name<CompositeKey,N>::type yields
0128  * functor<nth_key_from_value<CompositeKey,N> >, or tuples::null_type
0129  * if N exceeds the length of the composite key.
0130  */
0131 
0132 #define BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(name,functor)         \
0133 template<typename KeyFromValue>                                              \
0134 struct BOOST_PP_CAT(key_,name)                                               \
0135 {                                                                            \
0136   typedef functor<typename KeyFromValue::result_type> type;                  \
0137 };                                                                           \
0138                                                                              \
0139 template<>                                                                   \
0140 struct BOOST_PP_CAT(key_,name)<tuples::null_type>                            \
0141 {                                                                            \
0142   typedef tuples::null_type type;                                            \
0143 };                                                                           \
0144                                                                              \
0145 template<typename CompositeKey,int  N>                                       \
0146 struct BOOST_PP_CAT(nth_composite_key_,name)                                 \
0147 {                                                                            \
0148   typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;  \
0149   typedef typename BOOST_PP_CAT(key_,name)<key_from_value>::type type;       \
0150 };
0151 
0152 /* nth_composite_key_equal_to
0153  * nth_composite_key_less
0154  * nth_composite_key_greater
0155  * nth_composite_key_hash
0156  */
0157 
0158 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(equal_to,std::equal_to)
0159 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(less,std::less)
0160 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(greater,std::greater)
0161 BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(hash,boost::hash)
0162 
0163 /* used for defining equality and comparison ops of composite_key_result */
0164 
0165 #define BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO(z,n,text) text
0166 
0167 struct generic_operator_equal
0168 {
0169   template<typename T,typename Q>
0170   bool operator()(const T& x,const Q& y)const{return x==y;}
0171 };
0172 
0173 typedef tuple<
0174   BOOST_MULTI_INDEX_CK_ENUM(
0175     BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
0176     detail::generic_operator_equal)>          generic_operator_equal_tuple;
0177 
0178 struct generic_operator_less
0179 {
0180   template<typename T,typename Q>
0181   bool operator()(const T& x,const Q& y)const{return x<y;}
0182 };
0183 
0184 typedef tuple<
0185   BOOST_MULTI_INDEX_CK_ENUM(
0186     BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
0187     detail::generic_operator_less)>           generic_operator_less_tuple;
0188 
0189 /* Metaprogramming machinery for implementing equality, comparison and
0190  * hashing operations of composite_key_result.
0191  *
0192  * equal_* checks for equality between composite_key_results and
0193  * between those and tuples, accepting a tuple of basic equality functors.
0194  * compare_* does lexicographical comparison.
0195  * hash_* computes a combination of elementwise hash values.
0196  */
0197 
0198 template
0199 <
0200   typename KeyCons1,typename Value1,
0201   typename KeyCons2, typename Value2,
0202   typename EqualCons
0203 >
0204 struct equal_ckey_ckey; /* fwd decl. */
0205 
0206 template
0207 <
0208   typename KeyCons1,typename Value1,
0209   typename KeyCons2, typename Value2,
0210   typename EqualCons
0211 >
0212 struct equal_ckey_ckey_terminal
0213 {
0214   static bool compare(
0215     const KeyCons1&,const Value1&,
0216     const KeyCons2&,const Value2&,
0217     const EqualCons&)
0218   {
0219     return true;
0220   }
0221 };
0222 
0223 template
0224 <
0225   typename KeyCons1,typename Value1,
0226   typename KeyCons2, typename Value2,
0227   typename EqualCons
0228 >
0229 struct equal_ckey_ckey_normal
0230 {
0231   static bool compare(
0232     const KeyCons1& c0,const Value1& v0,
0233     const KeyCons2& c1,const Value2& v1,
0234     const EqualCons& eq)
0235   {
0236     if(!eq.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return false;
0237     return equal_ckey_ckey<
0238       BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
0239       BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
0240       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
0241     >::compare(c0.get_tail(),v0,c1.get_tail(),v1,eq.get_tail());
0242   }
0243 };
0244 
0245 template
0246 <
0247   typename KeyCons1,typename Value1,
0248   typename KeyCons2, typename Value2,
0249   typename EqualCons
0250 >
0251 struct equal_ckey_ckey:
0252   mpl::if_<
0253     mpl::or_<
0254       is_same<KeyCons1,tuples::null_type>,
0255       is_same<KeyCons2,tuples::null_type>
0256     >,
0257     equal_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>,
0258     equal_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>
0259   >::type
0260 {
0261 };
0262 
0263 template
0264 <
0265   typename KeyCons,typename Value,
0266   typename ValCons,typename EqualCons
0267 >
0268 struct equal_ckey_cval; /* fwd decl. */
0269 
0270 template
0271 <
0272   typename KeyCons,typename Value,
0273   typename ValCons,typename EqualCons
0274 >
0275 struct equal_ckey_cval_terminal
0276 {
0277   static bool compare(
0278     const KeyCons&,const Value&,const ValCons&,const EqualCons&)
0279   {
0280     return true;
0281   }
0282 
0283   static bool compare(
0284     const ValCons&,const KeyCons&,const Value&,const EqualCons&)
0285   {
0286     return true;
0287   }
0288 };
0289 
0290 template
0291 <
0292   typename KeyCons,typename Value,
0293   typename ValCons,typename EqualCons
0294 >
0295 struct equal_ckey_cval_normal
0296 {
0297   static bool compare(
0298     const KeyCons& c,const Value& v,const ValCons& vc,
0299     const EqualCons& eq)
0300   {
0301     if(!eq.get_head()(c.get_head()(v),vc.get_head()))return false;
0302     return equal_ckey_cval<
0303       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
0304       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
0305       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
0306     >::compare(c.get_tail(),v,vc.get_tail(),eq.get_tail());
0307   }
0308 
0309   static bool compare(
0310     const ValCons& vc,const KeyCons& c,const Value& v,
0311     const EqualCons& eq)
0312   {
0313     if(!eq.get_head()(vc.get_head(),c.get_head()(v)))return false;
0314     return equal_ckey_cval<
0315       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
0316       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
0317       BOOST_DEDUCED_TYPENAME EqualCons::tail_type
0318     >::compare(vc.get_tail(),c.get_tail(),v,eq.get_tail());
0319   }
0320 };
0321 
0322 template
0323 <
0324   typename KeyCons,typename Value,
0325   typename ValCons,typename EqualCons
0326 >
0327 struct equal_ckey_cval:
0328   mpl::if_<
0329     mpl::or_<
0330       is_same<KeyCons,tuples::null_type>,
0331       is_same<ValCons,tuples::null_type>
0332     >,
0333     equal_ckey_cval_terminal<KeyCons,Value,ValCons,EqualCons>,
0334     equal_ckey_cval_normal<KeyCons,Value,ValCons,EqualCons>
0335   >::type
0336 {
0337 };
0338 
0339 template
0340 <
0341   typename KeyCons1,typename Value1,
0342   typename KeyCons2, typename Value2,
0343   typename CompareCons
0344 >
0345 struct compare_ckey_ckey; /* fwd decl. */
0346 
0347 template
0348 <
0349   typename KeyCons1,typename Value1,
0350   typename KeyCons2, typename Value2,
0351   typename CompareCons
0352 >
0353 struct compare_ckey_ckey_terminal
0354 {
0355   static bool compare(
0356     const KeyCons1&,const Value1&,
0357     const KeyCons2&,const Value2&,
0358     const CompareCons&)
0359   {
0360     return false;
0361   }
0362 };
0363 
0364 template
0365 <
0366   typename KeyCons1,typename Value1,
0367   typename KeyCons2, typename Value2,
0368   typename CompareCons
0369 >
0370 struct compare_ckey_ckey_normal
0371 {
0372   static bool compare(
0373     const KeyCons1& c0,const Value1& v0,
0374     const KeyCons2& c1,const Value2& v1,
0375     const CompareCons& comp)
0376   {
0377     if(comp.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return true;
0378     if(comp.get_head()(c1.get_head()(v1),c0.get_head()(v0)))return false;
0379     return compare_ckey_ckey<
0380       BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
0381       BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
0382       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
0383     >::compare(c0.get_tail(),v0,c1.get_tail(),v1,comp.get_tail());
0384   }
0385 };
0386 
0387 template
0388 <
0389   typename KeyCons1,typename Value1,
0390   typename KeyCons2, typename Value2,
0391   typename CompareCons
0392 >
0393 struct compare_ckey_ckey:
0394   mpl::if_<
0395     mpl::or_<
0396       is_same<KeyCons1,tuples::null_type>,
0397       is_same<KeyCons2,tuples::null_type>
0398     >,
0399     compare_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>,
0400     compare_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>
0401   >::type
0402 {
0403 };
0404 
0405 template
0406 <
0407   typename KeyCons,typename Value,
0408   typename ValCons,typename CompareCons
0409 >
0410 struct compare_ckey_cval; /* fwd decl. */
0411 
0412 template
0413 <
0414   typename KeyCons,typename Value,
0415   typename ValCons,typename CompareCons
0416 >
0417 struct compare_ckey_cval_terminal
0418 {
0419   static bool compare(
0420     const KeyCons&,const Value&,const ValCons&,const CompareCons&)
0421   {
0422     return false;
0423   }
0424 
0425   static bool compare(
0426     const ValCons&,const KeyCons&,const Value&,const CompareCons&)
0427   {
0428     return false;
0429   }
0430 };
0431 
0432 template
0433 <
0434   typename KeyCons,typename Value,
0435   typename ValCons,typename CompareCons
0436 >
0437 struct compare_ckey_cval_normal
0438 {
0439   static bool compare(
0440     const KeyCons& c,const Value& v,const ValCons& vc,
0441     const CompareCons& comp)
0442   {
0443     if(comp.get_head()(c.get_head()(v),vc.get_head()))return true;
0444     if(comp.get_head()(vc.get_head(),c.get_head()(v)))return false;
0445     return compare_ckey_cval<
0446       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
0447       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
0448       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
0449     >::compare(c.get_tail(),v,vc.get_tail(),comp.get_tail());
0450   }
0451 
0452   static bool compare(
0453     const ValCons& vc,const KeyCons& c,const Value& v,
0454     const CompareCons& comp)
0455   {
0456     if(comp.get_head()(vc.get_head(),c.get_head()(v)))return true;
0457     if(comp.get_head()(c.get_head()(v),vc.get_head()))return false;
0458     return compare_ckey_cval<
0459       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
0460       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
0461       BOOST_DEDUCED_TYPENAME CompareCons::tail_type
0462     >::compare(vc.get_tail(),c.get_tail(),v,comp.get_tail());
0463   }
0464 };
0465 
0466 template
0467 <
0468   typename KeyCons,typename Value,
0469   typename ValCons,typename CompareCons
0470 >
0471 struct compare_ckey_cval:
0472   mpl::if_<
0473     mpl::or_<
0474       is_same<KeyCons,tuples::null_type>,
0475       is_same<ValCons,tuples::null_type>
0476     >,
0477     compare_ckey_cval_terminal<KeyCons,Value,ValCons,CompareCons>,
0478     compare_ckey_cval_normal<KeyCons,Value,ValCons,CompareCons>
0479   >::type
0480 {
0481 };
0482 
0483 template<typename KeyCons,typename Value,typename HashCons>
0484 struct hash_ckey; /* fwd decl. */
0485 
0486 template<typename KeyCons,typename Value,typename HashCons>
0487 struct hash_ckey_terminal
0488 {
0489   static std::size_t hash(
0490     const KeyCons&,const Value&,const HashCons&,std::size_t carry)
0491   {
0492     return carry;
0493   }
0494 };
0495 
0496 template<typename KeyCons,typename Value,typename HashCons>
0497 struct hash_ckey_normal
0498 {
0499   static std::size_t hash(
0500     const KeyCons& c,const Value& v,const HashCons& h,std::size_t carry=0)
0501   {
0502     /* same hashing formula as boost::hash_combine */
0503 
0504     carry^=h.get_head()(c.get_head()(v))+0x9e3779b9+(carry<<6)+(carry>>2);
0505     return hash_ckey<
0506       BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
0507       BOOST_DEDUCED_TYPENAME HashCons::tail_type
0508     >::hash(c.get_tail(),v,h.get_tail(),carry);
0509   }
0510 };
0511 
0512 template<typename KeyCons,typename Value,typename HashCons>
0513 struct hash_ckey:
0514   mpl::if_<
0515     is_same<KeyCons,tuples::null_type>,
0516     hash_ckey_terminal<KeyCons,Value,HashCons>,
0517     hash_ckey_normal<KeyCons,Value,HashCons>
0518   >::type
0519 {
0520 };
0521 
0522 template<typename ValCons,typename HashCons>
0523 struct hash_cval; /* fwd decl. */
0524 
0525 template<typename ValCons,typename HashCons>
0526 struct hash_cval_terminal
0527 {
0528   static std::size_t hash(const ValCons&,const HashCons&,std::size_t carry)
0529   {
0530     return carry;
0531   }
0532 };
0533 
0534 template<typename ValCons,typename HashCons>
0535 struct hash_cval_normal
0536 {
0537   static std::size_t hash(
0538     const ValCons& vc,const HashCons& h,std::size_t carry=0)
0539   {
0540     carry^=h.get_head()(vc.get_head())+0x9e3779b9+(carry<<6)+(carry>>2);
0541     return hash_cval<
0542       BOOST_DEDUCED_TYPENAME ValCons::tail_type,
0543       BOOST_DEDUCED_TYPENAME HashCons::tail_type
0544     >::hash(vc.get_tail(),h.get_tail(),carry);
0545   }
0546 };
0547 
0548 template<typename ValCons,typename HashCons>
0549 struct hash_cval:
0550   mpl::if_<
0551     is_same<ValCons,tuples::null_type>,
0552     hash_cval_terminal<ValCons,HashCons>,
0553     hash_cval_normal<ValCons,HashCons>
0554   >::type
0555 {
0556 };
0557 
0558 } /* namespace multi_index::detail */
0559 
0560 /* composite_key_result */
0561 
0562 #if defined(BOOST_MSVC)
0563 #pragma warning(push)
0564 #pragma warning(disable:4512)
0565 #endif
0566 
0567 template<typename CompositeKey>
0568 struct composite_key_result
0569 {
0570   typedef CompositeKey                            composite_key_type;
0571   typedef typename composite_key_type::value_type value_type;
0572 
0573   composite_key_result(
0574     const composite_key_type& composite_key_,const value_type& value_):
0575     composite_key(composite_key_),value(value_)
0576   {}
0577 
0578   const composite_key_type& composite_key;
0579   const value_type&         value;
0580 };
0581 
0582 #if defined(BOOST_MSVC)
0583 #pragma warning(pop)
0584 #endif
0585 
0586 /* composite_key */
0587 
0588 template<
0589   typename Value,
0590   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,KeyFromValue)
0591 >
0592 struct composite_key:
0593   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)>
0594 {
0595 private:
0596   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)> super;
0597 
0598 public:
0599   typedef super                               key_extractor_tuple;
0600   typedef Value                               value_type;
0601   typedef composite_key_result<composite_key> result_type;
0602 
0603   composite_key(
0604     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,KeyFromValue)):
0605     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
0606   {}
0607 
0608   composite_key(const key_extractor_tuple& x):super(x){}
0609 
0610   const key_extractor_tuple& key_extractors()const{return *this;}
0611   key_extractor_tuple&       key_extractors(){return *this;}
0612 
0613   template<typename ChainedPtr>
0614 
0615 #if !defined(BOOST_NO_SFINAE)
0616   typename disable_if<
0617     is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
0618 #else
0619   result_type
0620 #endif
0621 
0622   operator()(const ChainedPtr& x)const
0623   {
0624     return operator()(*x);
0625   }
0626 
0627   result_type operator()(const value_type& x)const
0628   {
0629     return result_type(*this,x);
0630   }
0631 
0632   result_type operator()(const reference_wrapper<const value_type>& x)const
0633   {
0634     return result_type(*this,x.get());
0635   }
0636 
0637   result_type operator()(const reference_wrapper<value_type>& x)const
0638   {
0639     return result_type(*this,x.get());
0640   }
0641 };
0642 
0643 /* comparison operators */
0644 
0645 /* == */
0646 
0647 template<typename CompositeKey1,typename CompositeKey2>
0648 inline bool operator==(
0649   const composite_key_result<CompositeKey1>& x,
0650   const composite_key_result<CompositeKey2>& y)
0651 {
0652   typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
0653   typedef typename CompositeKey1::value_type          value_type1;
0654   typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
0655   typedef typename CompositeKey2::value_type          value_type2;
0656 
0657   BOOST_STATIC_ASSERT(
0658     tuples::length<key_extractor_tuple1>::value==
0659     tuples::length<key_extractor_tuple2>::value);
0660 
0661   return detail::equal_ckey_ckey<
0662     key_extractor_tuple1,value_type1,
0663     key_extractor_tuple2,value_type2,
0664     detail::generic_operator_equal_tuple
0665   >::compare(
0666     x.composite_key.key_extractors(),x.value,
0667     y.composite_key.key_extractors(),y.value,
0668     detail::generic_operator_equal_tuple());
0669 }
0670 
0671 template<
0672   typename CompositeKey,
0673   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
0674 >
0675 inline bool operator==(
0676   const composite_key_result<CompositeKey>& x,
0677   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
0678 {
0679   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
0680   typedef typename CompositeKey::value_type              value_type;
0681   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
0682   
0683   BOOST_STATIC_ASSERT(
0684     tuples::length<key_extractor_tuple>::value==
0685     tuples::length<key_tuple>::value);
0686 
0687   return detail::equal_ckey_cval<
0688     key_extractor_tuple,value_type,
0689     key_tuple,detail::generic_operator_equal_tuple
0690   >::compare(
0691     x.composite_key.key_extractors(),x.value,
0692     y,detail::generic_operator_equal_tuple());
0693 }
0694 
0695 template
0696 <
0697   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
0698   typename CompositeKey
0699 >
0700 inline bool operator==(
0701   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
0702   const composite_key_result<CompositeKey>& y)
0703 {
0704   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
0705   typedef typename CompositeKey::value_type              value_type;
0706   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
0707   
0708   BOOST_STATIC_ASSERT(
0709     tuples::length<key_extractor_tuple>::value==
0710     tuples::length<key_tuple>::value);
0711 
0712   return detail::equal_ckey_cval<
0713     key_extractor_tuple,value_type,
0714     key_tuple,detail::generic_operator_equal_tuple
0715   >::compare(
0716     x,y.composite_key.key_extractors(),
0717     y.value,detail::generic_operator_equal_tuple());
0718 }
0719 
0720 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
0721     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0722 template<typename CompositeKey,typename... Values>
0723 inline bool operator==(
0724   const composite_key_result<CompositeKey>& x,
0725   const std::tuple<Values...>& y)
0726 {
0727   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
0728   typedef typename CompositeKey::value_type          value_type;
0729   typedef std::tuple<Values...>                      key_tuple;
0730   typedef typename detail::cons_stdtuple_ctor<
0731     key_tuple>::result_type                          cons_key_tuple;
0732   
0733   BOOST_STATIC_ASSERT(
0734     static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
0735     std::tuple_size<key_tuple>::value);
0736 
0737   return detail::equal_ckey_cval<
0738     key_extractor_tuple,value_type,
0739     cons_key_tuple,detail::generic_operator_equal_tuple
0740   >::compare(
0741     x.composite_key.key_extractors(),x.value,
0742     detail::make_cons_stdtuple(y),detail::generic_operator_equal_tuple());
0743 }
0744 
0745 template<typename CompositeKey,typename... Values>
0746 inline bool operator==(
0747   const std::tuple<Values...>& x,
0748   const composite_key_result<CompositeKey>& y)
0749 {
0750   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
0751   typedef typename CompositeKey::value_type          value_type;
0752   typedef std::tuple<Values...>                      key_tuple;
0753   typedef typename detail::cons_stdtuple_ctor<
0754     key_tuple>::result_type                          cons_key_tuple;
0755 
0756   BOOST_STATIC_ASSERT(
0757     static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
0758     std::tuple_size<key_tuple>::value);
0759 
0760   return detail::equal_ckey_cval<
0761     key_extractor_tuple,value_type,
0762     cons_key_tuple,detail::generic_operator_equal_tuple
0763   >::compare(
0764     detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
0765     y.value,detail::generic_operator_equal_tuple());
0766 }
0767 #endif
0768 
0769 /* < */
0770 
0771 template<typename CompositeKey1,typename CompositeKey2>
0772 inline bool operator<(
0773   const composite_key_result<CompositeKey1>& x,
0774   const composite_key_result<CompositeKey2>& y)
0775 {
0776   typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
0777   typedef typename CompositeKey1::value_type          value_type1;
0778   typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
0779   typedef typename CompositeKey2::value_type          value_type2;
0780 
0781   return detail::compare_ckey_ckey<
0782    key_extractor_tuple1,value_type1,
0783    key_extractor_tuple2,value_type2,
0784    detail::generic_operator_less_tuple
0785   >::compare(
0786     x.composite_key.key_extractors(),x.value,
0787     y.composite_key.key_extractors(),y.value,
0788     detail::generic_operator_less_tuple());
0789 }
0790 
0791 template
0792 <
0793   typename CompositeKey,
0794   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
0795 >
0796 inline bool operator<(
0797   const composite_key_result<CompositeKey>& x,
0798   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
0799 {
0800   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
0801   typedef typename CompositeKey::value_type              value_type;
0802   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
0803   
0804   return detail::compare_ckey_cval<
0805     key_extractor_tuple,value_type,
0806     key_tuple,detail::generic_operator_less_tuple
0807   >::compare(
0808     x.composite_key.key_extractors(),x.value,
0809     y,detail::generic_operator_less_tuple());
0810 }
0811 
0812 template
0813 <
0814   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
0815   typename CompositeKey
0816 >
0817 inline bool operator<(
0818   const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
0819   const composite_key_result<CompositeKey>& y)
0820 {
0821   typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
0822   typedef typename CompositeKey::value_type              value_type;
0823   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
0824   
0825   return detail::compare_ckey_cval<
0826     key_extractor_tuple,value_type,
0827     key_tuple,detail::generic_operator_less_tuple
0828   >::compare(
0829     x,y.composite_key.key_extractors(),
0830     y.value,detail::generic_operator_less_tuple());
0831 }
0832 
0833 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
0834     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0835 template<typename CompositeKey,typename... Values>
0836 inline bool operator<(
0837   const composite_key_result<CompositeKey>& x,
0838   const std::tuple<Values...>& y)
0839 {
0840   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
0841   typedef typename CompositeKey::value_type          value_type;
0842   typedef std::tuple<Values...>                      key_tuple;
0843   typedef typename detail::cons_stdtuple_ctor<
0844     key_tuple>::result_type                          cons_key_tuple;
0845   
0846   return detail::compare_ckey_cval<
0847     key_extractor_tuple,value_type,
0848     cons_key_tuple,detail::generic_operator_less_tuple
0849   >::compare(
0850     x.composite_key.key_extractors(),x.value,
0851     detail::make_cons_stdtuple(y),detail::generic_operator_less_tuple());
0852 }
0853 
0854 template<typename CompositeKey,typename... Values>
0855 inline bool operator<(
0856   const std::tuple<Values...>& x,
0857   const composite_key_result<CompositeKey>& y)
0858 {
0859   typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
0860   typedef typename CompositeKey::value_type          value_type;
0861   typedef std::tuple<Values...>                      key_tuple;
0862   typedef typename detail::cons_stdtuple_ctor<
0863     key_tuple>::result_type                          cons_key_tuple;
0864   
0865   return detail::compare_ckey_cval<
0866     key_extractor_tuple,value_type,
0867     cons_key_tuple,detail::generic_operator_less_tuple
0868   >::compare(
0869     detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
0870     y.value,detail::generic_operator_less_tuple());
0871 }
0872 #endif
0873 
0874 /* rest of comparison operators */
0875 
0876 #define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2)                  \
0877 template<t1,t2> inline bool operator!=(const a1& x,const a2& y)              \
0878 {                                                                            \
0879   return !(x==y);                                                            \
0880 }                                                                            \
0881                                                                              \
0882 template<t1,t2> inline bool operator>(const a1& x,const a2& y)               \
0883 {                                                                            \
0884   return y<x;                                                                \
0885 }                                                                            \
0886                                                                              \
0887 template<t1,t2> inline bool operator>=(const a1& x,const a2& y)              \
0888 {                                                                            \
0889   return !(x<y);                                                             \
0890 }                                                                            \
0891                                                                              \
0892 template<t1,t2> inline bool operator<=(const a1& x,const a2& y)              \
0893 {                                                                            \
0894   return !(y<x);                                                             \
0895 }
0896 
0897 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
0898   typename CompositeKey1,
0899   typename CompositeKey2,
0900   composite_key_result<CompositeKey1>,
0901   composite_key_result<CompositeKey2>
0902 )
0903 
0904 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
0905   typename CompositeKey,
0906   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
0907   composite_key_result<CompositeKey>,
0908   tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>
0909 )
0910 
0911 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
0912   BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
0913   typename CompositeKey,
0914   tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>,
0915   composite_key_result<CompositeKey>
0916 )
0917 
0918 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
0919     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0920 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
0921   typename CompositeKey,
0922   typename... Values,
0923   composite_key_result<CompositeKey>,
0924   std::tuple<Values...>
0925 )
0926 
0927 BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
0928   typename CompositeKey,
0929   typename... Values,
0930   std::tuple<Values...>,
0931   composite_key_result<CompositeKey>
0932 )
0933 #endif
0934 
0935 /* composite_key_equal_to */
0936 
0937 template
0938 <
0939   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Pred)
0940 >
0941 struct composite_key_equal_to:
0942   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)>
0943 {
0944 private:
0945   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)> super;
0946 
0947 public:
0948   typedef super key_eq_tuple;
0949 
0950   composite_key_equal_to(
0951     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Pred)):
0952     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
0953   {}
0954 
0955   composite_key_equal_to(const key_eq_tuple& x):super(x){}
0956 
0957   const key_eq_tuple& key_eqs()const{return *this;}
0958   key_eq_tuple&       key_eqs(){return *this;}
0959 
0960   template<typename CompositeKey1,typename CompositeKey2>
0961   bool operator()(
0962     const composite_key_result<CompositeKey1> & x,
0963     const composite_key_result<CompositeKey2> & y)const
0964   {
0965     typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
0966     typedef typename CompositeKey1::value_type          value_type1;
0967     typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
0968     typedef typename CompositeKey2::value_type          value_type2;
0969 
0970     BOOST_STATIC_ASSERT(
0971       tuples::length<key_extractor_tuple1>::value<=
0972       tuples::length<key_eq_tuple>::value&&
0973       tuples::length<key_extractor_tuple1>::value==
0974       tuples::length<key_extractor_tuple2>::value);
0975 
0976     return detail::equal_ckey_ckey<
0977       key_extractor_tuple1,value_type1,
0978       key_extractor_tuple2,value_type2,
0979       key_eq_tuple
0980     >::compare(
0981       x.composite_key.key_extractors(),x.value,
0982       y.composite_key.key_extractors(),y.value,
0983       key_eqs());
0984   }
0985   
0986   template
0987   <
0988     typename CompositeKey,
0989     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
0990   >
0991   bool operator()(
0992     const composite_key_result<CompositeKey>& x,
0993     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
0994   {
0995     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
0996     typedef typename CompositeKey::value_type              value_type;
0997     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
0998 
0999     BOOST_STATIC_ASSERT(
1000       tuples::length<key_extractor_tuple>::value<=
1001       tuples::length<key_eq_tuple>::value&&
1002       tuples::length<key_extractor_tuple>::value==
1003       tuples::length<key_tuple>::value);
1004 
1005     return detail::equal_ckey_cval<
1006       key_extractor_tuple,value_type,
1007       key_tuple,key_eq_tuple
1008     >::compare(x.composite_key.key_extractors(),x.value,y,key_eqs());
1009   }
1010 
1011   template
1012   <
1013     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
1014     typename CompositeKey
1015   >
1016   bool operator()(
1017     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
1018     const composite_key_result<CompositeKey>& y)const
1019   {
1020     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
1021     typedef typename CompositeKey::value_type              value_type;
1022     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1023 
1024     BOOST_STATIC_ASSERT(
1025       tuples::length<key_tuple>::value<=
1026       tuples::length<key_eq_tuple>::value&&
1027       tuples::length<key_tuple>::value==
1028       tuples::length<key_extractor_tuple>::value);
1029 
1030     return detail::equal_ckey_cval<
1031       key_extractor_tuple,value_type,
1032       key_tuple,key_eq_tuple
1033     >::compare(x,y.composite_key.key_extractors(),y.value,key_eqs());
1034   }
1035 
1036 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
1037     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1038   template<typename CompositeKey,typename... Values>
1039   bool operator()(
1040     const composite_key_result<CompositeKey>& x,
1041     const std::tuple<Values...>& y)const
1042   {
1043     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1044     typedef typename CompositeKey::value_type          value_type;
1045     typedef std::tuple<Values...>                      key_tuple;
1046     typedef typename detail::cons_stdtuple_ctor<
1047       key_tuple>::result_type                          cons_key_tuple;
1048 
1049     BOOST_STATIC_ASSERT(
1050       tuples::length<key_extractor_tuple>::value<=
1051       tuples::length<key_eq_tuple>::value&&
1052       static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
1053       std::tuple_size<key_tuple>::value);
1054 
1055     return detail::equal_ckey_cval<
1056       key_extractor_tuple,value_type,
1057       cons_key_tuple,key_eq_tuple
1058     >::compare(
1059       x.composite_key.key_extractors(),x.value,
1060       detail::make_cons_stdtuple(y),key_eqs());
1061   }
1062 
1063   template<typename CompositeKey,typename... Values>
1064   bool operator()(
1065     const std::tuple<Values...>& x,
1066     const composite_key_result<CompositeKey>& y)const
1067   {
1068     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1069     typedef typename CompositeKey::value_type          value_type;
1070     typedef std::tuple<Values...>                      key_tuple;
1071     typedef typename detail::cons_stdtuple_ctor<
1072       key_tuple>::result_type                          cons_key_tuple;
1073 
1074     BOOST_STATIC_ASSERT(
1075       std::tuple_size<key_tuple>::value<=
1076       static_cast<std::size_t>(tuples::length<key_eq_tuple>::value)&&
1077       std::tuple_size<key_tuple>::value==
1078       static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value));
1079 
1080     return detail::equal_ckey_cval<
1081       key_extractor_tuple,value_type,
1082       cons_key_tuple,key_eq_tuple
1083     >::compare(
1084       detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
1085       y.value,key_eqs());
1086   }
1087 #endif
1088 };
1089 
1090 /* composite_key_compare */
1091 
1092 template
1093 <
1094   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Compare)
1095 >
1096 struct composite_key_compare:
1097   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)>
1098 {
1099 private:
1100   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)> super;
1101 
1102 public:
1103   typedef super key_comp_tuple;
1104 
1105   composite_key_compare(
1106     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Compare)):
1107     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
1108   {}
1109 
1110   composite_key_compare(const key_comp_tuple& x):super(x){}
1111 
1112   const key_comp_tuple& key_comps()const{return *this;}
1113   key_comp_tuple&       key_comps(){return *this;}
1114 
1115   template<typename CompositeKey1,typename CompositeKey2>
1116   bool operator()(
1117     const composite_key_result<CompositeKey1> & x,
1118     const composite_key_result<CompositeKey2> & y)const
1119   {
1120     typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
1121     typedef typename CompositeKey1::value_type          value_type1;
1122     typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
1123     typedef typename CompositeKey2::value_type          value_type2;
1124 
1125     BOOST_STATIC_ASSERT(
1126       tuples::length<key_extractor_tuple1>::value<=
1127       tuples::length<key_comp_tuple>::value||
1128       tuples::length<key_extractor_tuple2>::value<=
1129       tuples::length<key_comp_tuple>::value);
1130 
1131     return detail::compare_ckey_ckey<
1132       key_extractor_tuple1,value_type1,
1133       key_extractor_tuple2,value_type2,
1134       key_comp_tuple
1135     >::compare(
1136       x.composite_key.key_extractors(),x.value,
1137       y.composite_key.key_extractors(),y.value,
1138       key_comps());
1139   }
1140   
1141 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
1142   template<typename CompositeKey,typename Value>
1143   bool operator()(
1144     const composite_key_result<CompositeKey>& x,
1145     const Value& y)const
1146   {
1147     return operator()(x,boost::make_tuple(boost::cref(y)));
1148   }
1149 #endif
1150 
1151   template
1152   <
1153     typename CompositeKey,
1154     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
1155   >
1156   bool operator()(
1157     const composite_key_result<CompositeKey>& x,
1158     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
1159   {
1160     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
1161     typedef typename CompositeKey::value_type              value_type;
1162     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1163 
1164     BOOST_STATIC_ASSERT(
1165       tuples::length<key_extractor_tuple>::value<=
1166       tuples::length<key_comp_tuple>::value||
1167       tuples::length<key_tuple>::value<=
1168       tuples::length<key_comp_tuple>::value);
1169 
1170     return detail::compare_ckey_cval<
1171       key_extractor_tuple,value_type,
1172       key_tuple,key_comp_tuple
1173     >::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
1174   }
1175 
1176 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
1177   template<typename Value,typename CompositeKey>
1178   bool operator()(
1179     const Value& x,
1180     const composite_key_result<CompositeKey>& y)const
1181   {
1182     return operator()(boost::make_tuple(boost::cref(x)),y);
1183   }
1184 #endif
1185 
1186   template
1187   <
1188     BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
1189     typename CompositeKey
1190   >
1191   bool operator()(
1192     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
1193     const composite_key_result<CompositeKey>& y)const
1194   {
1195     typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
1196     typedef typename CompositeKey::value_type              value_type;
1197     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1198 
1199     BOOST_STATIC_ASSERT(
1200       tuples::length<key_tuple>::value<=
1201       tuples::length<key_comp_tuple>::value||
1202       tuples::length<key_extractor_tuple>::value<=
1203       tuples::length<key_comp_tuple>::value);
1204 
1205     return detail::compare_ckey_cval<
1206       key_extractor_tuple,value_type,
1207       key_tuple,key_comp_tuple
1208     >::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
1209   }
1210 
1211 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
1212     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1213   template<typename CompositeKey,typename... Values>
1214   bool operator()(
1215     const composite_key_result<CompositeKey>& x,
1216     const std::tuple<Values...>& y)const
1217   {
1218     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1219     typedef typename CompositeKey::value_type          value_type;
1220     typedef std::tuple<Values...>                      key_tuple;
1221     typedef typename detail::cons_stdtuple_ctor<
1222       key_tuple>::result_type                          cons_key_tuple;
1223 
1224     BOOST_STATIC_ASSERT(
1225       tuples::length<key_extractor_tuple>::value<=
1226       tuples::length<key_comp_tuple>::value||
1227       std::tuple_size<key_tuple>::value<=
1228       static_cast<std::size_t>(tuples::length<key_comp_tuple>::value));
1229 
1230     return detail::compare_ckey_cval<
1231       key_extractor_tuple,value_type,
1232       cons_key_tuple,key_comp_tuple
1233     >::compare(
1234       x.composite_key.key_extractors(),x.value,
1235       detail::make_cons_stdtuple(y),key_comps());
1236   }
1237 
1238   template<typename CompositeKey,typename... Values>
1239   bool operator()(
1240     const std::tuple<Values...>& x,
1241     const composite_key_result<CompositeKey>& y)const
1242   {
1243     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1244     typedef typename CompositeKey::value_type          value_type;
1245     typedef std::tuple<Values...>                      key_tuple;
1246     typedef typename detail::cons_stdtuple_ctor<
1247       key_tuple>::result_type                          cons_key_tuple;
1248 
1249     BOOST_STATIC_ASSERT(
1250       std::tuple_size<key_tuple>::value<=
1251       static_cast<std::size_t>(tuples::length<key_comp_tuple>::value)||
1252       tuples::length<key_extractor_tuple>::value<=
1253       tuples::length<key_comp_tuple>::value);
1254 
1255     return detail::compare_ckey_cval<
1256       key_extractor_tuple,value_type,
1257       cons_key_tuple,key_comp_tuple
1258     >::compare(
1259       detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
1260       y.value,key_comps());
1261   }
1262 #endif
1263 };
1264 
1265 /* composite_key_hash */
1266 
1267 template
1268 <
1269   BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Hash)
1270 >
1271 struct composite_key_hash:
1272   private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)>
1273 {
1274 private:
1275   typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)> super;
1276 
1277 public:
1278   typedef super key_hasher_tuple;
1279 
1280   composite_key_hash(
1281     BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Hash)):
1282     super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
1283   {}
1284 
1285   composite_key_hash(const key_hasher_tuple& x):super(x){}
1286 
1287   const key_hasher_tuple& key_hash_functions()const{return *this;}
1288   key_hasher_tuple&       key_hash_functions(){return *this;}
1289 
1290   template<typename CompositeKey>
1291   std::size_t operator()(const composite_key_result<CompositeKey> & x)const
1292   {
1293     typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
1294     typedef typename CompositeKey::value_type          value_type;
1295 
1296     BOOST_STATIC_ASSERT(
1297       tuples::length<key_extractor_tuple>::value==
1298       tuples::length<key_hasher_tuple>::value);
1299 
1300     return detail::hash_ckey<
1301       key_extractor_tuple,value_type,
1302       key_hasher_tuple
1303     >::hash(x.composite_key.key_extractors(),x.value,key_hash_functions());
1304   }
1305   
1306   template<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)>
1307   std::size_t operator()(
1308     const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x)const
1309   {
1310     typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
1311 
1312     BOOST_STATIC_ASSERT(
1313       tuples::length<key_tuple>::value==
1314       tuples::length<key_hasher_tuple>::value);
1315 
1316     return detail::hash_cval<
1317       key_tuple,key_hasher_tuple
1318     >::hash(x,key_hash_functions());
1319   }
1320 
1321 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
1322     !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1323   template<typename... Values>
1324   std::size_t operator()(const std::tuple<Values...>& x)const
1325   {
1326     typedef std::tuple<Values...>                key_tuple;
1327     typedef typename detail::cons_stdtuple_ctor<
1328       key_tuple>::result_type                    cons_key_tuple;
1329 
1330     BOOST_STATIC_ASSERT(
1331       std::tuple_size<key_tuple>::value==
1332       static_cast<std::size_t>(tuples::length<key_hasher_tuple>::value));
1333 
1334     return detail::hash_cval<
1335       cons_key_tuple,key_hasher_tuple
1336     >::hash(detail::make_cons_stdtuple(x),key_hash_functions());
1337   }
1338 #endif
1339 };
1340 
1341 /* Instantiations of the former functors with "natural" basic components:
1342  * composite_key_result_equal_to uses std::equal_to of the values.
1343  * composite_key_result_less     uses std::less.
1344  * composite_key_result_greater  uses std::greater.
1345  * composite_key_result_hash     uses boost::hash.
1346  */
1347 
1348 #define BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER                           \
1349 composite_key_equal_to<                                                      \
1350     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1351       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1352       /* the argument is a PP list */                                        \
1353       (detail::nth_composite_key_equal_to,                                   \
1354         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1355           BOOST_PP_NIL)))                                                    \
1356   >
1357 
1358 template<typename CompositeKeyResult>
1359 struct composite_key_result_equal_to:
1360 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1361 BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
1362 {
1363 private:
1364   typedef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER super;
1365 
1366 public:
1367   typedef CompositeKeyResult  first_argument_type;
1368   typedef first_argument_type second_argument_type;
1369   typedef bool                result_type;
1370 
1371   using super::operator();
1372 };
1373 
1374 #define BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER                               \
1375 composite_key_compare<                                                       \
1376     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1377       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1378       /* the argument is a PP list */                                        \
1379       (detail::nth_composite_key_less,                                       \
1380         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1381           BOOST_PP_NIL)))                                                    \
1382   >
1383 
1384 template<typename CompositeKeyResult>
1385 struct composite_key_result_less:
1386 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1387 BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
1388 {
1389 private:
1390   typedef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER super;
1391 
1392 public:
1393   typedef CompositeKeyResult  first_argument_type;
1394   typedef first_argument_type second_argument_type;
1395   typedef bool                result_type;
1396 
1397   using super::operator();
1398 };
1399 
1400 #define BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER                            \
1401 composite_key_compare<                                                       \
1402     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1403       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1404       /* the argument is a PP list */                                        \
1405       (detail::nth_composite_key_greater,                                    \
1406         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1407           BOOST_PP_NIL)))                                                    \
1408   >
1409 
1410 template<typename CompositeKeyResult>
1411 struct composite_key_result_greater:
1412 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1413 BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
1414 {
1415 private:
1416   typedef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER super;
1417 
1418 public:
1419   typedef CompositeKeyResult  first_argument_type;
1420   typedef first_argument_type second_argument_type;
1421   typedef bool                result_type;
1422 
1423   using super::operator();
1424 };
1425 
1426 #define BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER                               \
1427 composite_key_hash<                                                          \
1428     BOOST_MULTI_INDEX_CK_ENUM(                                               \
1429       BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
1430       /* the argument is a PP list */                                        \
1431       (detail::nth_composite_key_hash,                                       \
1432         (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
1433           BOOST_PP_NIL)))                                                    \
1434   >
1435 
1436 template<typename CompositeKeyResult>
1437 struct composite_key_result_hash:
1438 BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
1439 BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
1440 {
1441 private:
1442   typedef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER super;
1443 
1444 public:
1445   typedef CompositeKeyResult argument_type;
1446   typedef std::size_t        result_type;
1447 
1448   using super::operator();
1449 };
1450 
1451 } /* namespace multi_index */
1452 
1453 } /* namespace boost */
1454 
1455 /* Specializations of std::equal_to, std::less, std::greater and boost::hash
1456  * for composite_key_results enabling interoperation with tuples of values.
1457  */
1458 
1459 namespace std{
1460 
1461 template<typename CompositeKey>
1462 struct equal_to<boost::multi_index::composite_key_result<CompositeKey> >:
1463   boost::multi_index::composite_key_result_equal_to<
1464     boost::multi_index::composite_key_result<CompositeKey>
1465   >
1466 {
1467 };
1468 
1469 template<typename CompositeKey>
1470 struct less<boost::multi_index::composite_key_result<CompositeKey> >:
1471   boost::multi_index::composite_key_result_less<
1472     boost::multi_index::composite_key_result<CompositeKey>
1473   >
1474 {
1475 };
1476 
1477 template<typename CompositeKey>
1478 struct greater<boost::multi_index::composite_key_result<CompositeKey> >:
1479   boost::multi_index::composite_key_result_greater<
1480     boost::multi_index::composite_key_result<CompositeKey>
1481   >
1482 {
1483 };
1484 
1485 } /* namespace std */
1486 
1487 namespace boost{
1488 
1489 template<typename CompositeKey>
1490 struct hash<boost::multi_index::composite_key_result<CompositeKey> >:
1491   boost::multi_index::composite_key_result_hash<
1492     boost::multi_index::composite_key_result<CompositeKey>
1493   >
1494 {
1495 };
1496 
1497 } /* namespace boost */
1498 
1499 #undef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
1500 #undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
1501 #undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
1502 #undef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
1503 #undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
1504 #undef BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO
1505 #undef BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR
1506 #undef BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N
1507 #undef BOOST_MULTI_INDEX_CK_CTOR_ARG
1508 #undef BOOST_MULTI_INDEX_CK_TEMPLATE_PARM
1509 #undef BOOST_MULTI_INDEX_CK_ENUM_PARAMS
1510 #undef BOOST_MULTI_INDEX_CK_ENUM
1511 #undef BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE
1512 
1513 #endif