epoc32/include/stdapis/boost/multi_index/composite_key.hpp
branchSymbian2
changeset 2 2fe1408b6811
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/epoc32/include/stdapis/boost/multi_index/composite_key.hpp	Tue Mar 16 16:12:26 2010 +0000
     1.3 @@ -0,0 +1,1315 @@
     1.4 +/* Copyright 2003-2006 Joaquín M López Muñoz.
     1.5 + * Distributed under the Boost Software License, Version 1.0.
     1.6 + * (See accompanying file LICENSE_1_0.txt or copy at
     1.7 + * http://www.boost.org/LICENSE_1_0.txt)
     1.8 + *
     1.9 + * See http://www.boost.org/libs/multi_index for library home page.
    1.10 + */
    1.11 +
    1.12 +#ifndef BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
    1.13 +#define BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
    1.14 +
    1.15 +#if defined(_MSC_VER)&&(_MSC_VER>=1200)
    1.16 +#pragma once
    1.17 +#endif
    1.18 +
    1.19 +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
    1.20 +#include <boost/multi_index/detail/access_specifier.hpp>
    1.21 +#include <boost/multi_index/detail/prevent_eti.hpp>
    1.22 +#include <boost/mpl/eval_if.hpp>
    1.23 +#include <boost/mpl/identity.hpp>
    1.24 +#include <boost/mpl/if.hpp>
    1.25 +#include <boost/mpl/or.hpp>
    1.26 +#include <boost/mpl/aux_/nttp_decl.hpp>
    1.27 +#include <boost/preprocessor/cat.hpp>
    1.28 +#include <boost/preprocessor/control/expr_if.hpp>
    1.29 +#include <boost/preprocessor/list/at.hpp>
    1.30 +#include <boost/preprocessor/repetition/enum.hpp>
    1.31 +#include <boost/preprocessor/repetition/enum_params.hpp> 
    1.32 +#include <boost/static_assert.hpp>
    1.33 +#include <boost/tuple/tuple.hpp>
    1.34 +#include <boost/type_traits/is_same.hpp>
    1.35 +#include <boost/utility/enable_if.hpp>
    1.36 +#include <functional>
    1.37 +
    1.38 +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
    1.39 +#include <boost/ref.hpp>
    1.40 +#endif
    1.41 +
    1.42 +#if !defined(BOOST_NO_SFINAE)
    1.43 +#include <boost/type_traits/is_convertible.hpp>
    1.44 +#endif
    1.45 +
    1.46 +/* A composite key stores n key extractors and "computes" the
    1.47 + * result on a given value as a packed reference to the value and
    1.48 + * the composite key itself. Actual invocations to the component
    1.49 + * key extractors are lazily performed when executing an operation
    1.50 + * on composite_key results (equality, comparison, hashing.)
    1.51 + * As the other key extractors in Boost.MultiIndex, composite_key<T,...>
    1.52 + * is  overloaded to work on chained pointers to T and reference_wrappers
    1.53 + * of T.
    1.54 + */
    1.55 +
    1.56 +/* This user_definable macro limits the number of elements of a composite
    1.57 + * key; useful for shortening resulting symbol names (MSVC++ 6.0, for
    1.58 + * instance has problems coping with very long symbol names.)
    1.59 + * NB: This cannot exceed the maximum number of arguments of
    1.60 + * boost::tuple. In Boost 1.32, the limit is 10.
    1.61 + */
    1.62 +
    1.63 +#if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
    1.64 +#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
    1.65 +#define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 5
    1.66 +#else
    1.67 +#define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
    1.68 +#endif
    1.69 +#endif
    1.70 +
    1.71 +/* maximum number of key extractors in a composite key */
    1.72 +
    1.73 +#if BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE<10 /* max length of a tuple */
    1.74 +#define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE \
    1.75 +  BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE
    1.76 +#else
    1.77 +#define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE 10
    1.78 +#endif
    1.79 +
    1.80 +/* BOOST_PP_ENUM of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
    1.81 +
    1.82 +#define BOOST_MULTI_INDEX_CK_ENUM(macro,data)                                \
    1.83 +  BOOST_PP_ENUM(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,macro,data)
    1.84 +
    1.85 +/* BOOST_PP_ENUM_PARAMS of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
    1.86 +
    1.87 +#define BOOST_MULTI_INDEX_CK_ENUM_PARAMS(param)                              \
    1.88 +  BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,param)
    1.89 +
    1.90 +/* if n==0 ->   text0
    1.91 + * otherwise -> textn=tuples::null_type
    1.92 + */
    1.93 +
    1.94 +#define BOOST_MULTI_INDEX_CK_TEMPLATE_PARM(z,n,text)                         \
    1.95 +  typename BOOST_PP_CAT(text,n) BOOST_PP_EXPR_IF(n,=tuples::null_type)
    1.96 +
    1.97 +/* const textn& kn=textn() */
    1.98 +
    1.99 +#define BOOST_MULTI_INDEX_CK_CTOR_ARG(z,n,text)                              \
   1.100 +  const BOOST_PP_CAT(text,n)& BOOST_PP_CAT(k,n) = BOOST_PP_CAT(text,n)()
   1.101 +
   1.102 +/* typename list(0)<list(1),n>::type */
   1.103 +
   1.104 +#define BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N(z,n,list)                  \
   1.105 +  BOOST_DEDUCED_TYPENAME BOOST_PP_LIST_AT(list,0)<                           \
   1.106 +    BOOST_PP_LIST_AT(list,1),n                                               \
   1.107 +  >::type
   1.108 +
   1.109 +namespace boost{
   1.110 +
   1.111 +template<class T> class reference_wrapper; /* fwd decl. */
   1.112 +template<class T> struct hash; /* fwd decl. */
   1.113 +
   1.114 +namespace multi_index{
   1.115 +
   1.116 +namespace detail{
   1.117 +
   1.118 +/* n-th key extractor of a composite key */
   1.119 +
   1.120 +template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>
   1.121 +struct nth_key_from_value
   1.122 +{
   1.123 +  typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
   1.124 +  typedef typename prevent_eti<
   1.125 +    tuples::element<N,key_extractor_tuple>,
   1.126 +    typename mpl::eval_if_c<
   1.127 +      N<tuples::length<key_extractor_tuple>::value,
   1.128 +      tuples::element<N,key_extractor_tuple>,
   1.129 +      mpl::identity<tuples::null_type>
   1.130 +    >::type
   1.131 +  >::type                                            type;
   1.132 +};
   1.133 +
   1.134 +/* nth_composite_key_##name<CompositeKey,N>::type yields
   1.135 + * functor<nth_key_from_value<CompositeKey,N> >, or tuples::null_type
   1.136 + * if N exceeds the length of the composite key.
   1.137 + */
   1.138 +
   1.139 +#define BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(name,functor)         \
   1.140 +template<typename KeyFromValue>                                              \
   1.141 +struct BOOST_PP_CAT(key_,name)                                               \
   1.142 +{                                                                            \
   1.143 +  typedef functor<typename KeyFromValue::result_type> type;                  \
   1.144 +};                                                                           \
   1.145 +                                                                             \
   1.146 +template<>                                                                   \
   1.147 +struct BOOST_PP_CAT(key_,name)<tuples::null_type>                            \
   1.148 +{                                                                            \
   1.149 +  typedef tuples::null_type type;                                            \
   1.150 +};                                                                           \
   1.151 +                                                                             \
   1.152 +template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>              \
   1.153 +struct BOOST_PP_CAT(nth_composite_key_,name)                                 \
   1.154 +{                                                                            \
   1.155 +  typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;  \
   1.156 +  typedef typename BOOST_PP_CAT(key_,name)<key_from_value>::type type;       \
   1.157 +};
   1.158 +
   1.159 +/* nth_composite_key_equal_to
   1.160 + * nth_composite_key_less
   1.161 + * nth_composite_key_greater
   1.162 + * nth_composite_key_hash
   1.163 + */
   1.164 +
   1.165 +BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(equal_to,std::equal_to)
   1.166 +BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(less,std::less)
   1.167 +BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(greater,std::greater)
   1.168 +BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(hash,boost::hash)
   1.169 +
   1.170 +/* used for defining equality and comparison ops of composite_key_result */
   1.171 +
   1.172 +#define BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO(z,n,text) text
   1.173 +
   1.174 +struct generic_operator_equal
   1.175 +{
   1.176 +  template<typename T,typename Q>
   1.177 +  bool operator()(const T& x,const Q& y)const{return x==y;}
   1.178 +};
   1.179 +
   1.180 +typedef tuple<
   1.181 +  BOOST_MULTI_INDEX_CK_ENUM(
   1.182 +    BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
   1.183 +    detail::generic_operator_equal)>          generic_operator_equal_tuple;
   1.184 +
   1.185 +struct generic_operator_less
   1.186 +{
   1.187 +  template<typename T,typename Q>
   1.188 +  bool operator()(const T& x,const Q& y)const{return x<y;}
   1.189 +};
   1.190 +
   1.191 +typedef tuple<
   1.192 +  BOOST_MULTI_INDEX_CK_ENUM(
   1.193 +    BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
   1.194 +    detail::generic_operator_less)>           generic_operator_less_tuple;
   1.195 +
   1.196 +/* Metaprogramming machinery for implementing equality, comparison and
   1.197 + * hashing operations of composite_key_result.
   1.198 + *
   1.199 + * equal_* checks for equality between composite_key_results and
   1.200 + * between those and tuples, accepting a tuple of basic equality functors.
   1.201 + * compare_* does lexicographical comparison.
   1.202 + * hash_* computes a combination of elementwise hash values.
   1.203 + */
   1.204 +
   1.205 +template
   1.206 +<
   1.207 +  typename KeyCons1,typename Value1,
   1.208 +  typename KeyCons2, typename Value2,
   1.209 +  typename EqualCons
   1.210 +>
   1.211 +struct equal_ckey_ckey; /* fwd decl. */
   1.212 +
   1.213 +template
   1.214 +<
   1.215 +  typename KeyCons1,typename Value1,
   1.216 +  typename KeyCons2, typename Value2,
   1.217 +  typename EqualCons
   1.218 +>
   1.219 +struct equal_ckey_ckey_terminal
   1.220 +{
   1.221 +  static bool compare(
   1.222 +    const KeyCons1&,const Value1&,
   1.223 +    const KeyCons2&,const Value2&,
   1.224 +    const EqualCons&)
   1.225 +  {
   1.226 +    return true;
   1.227 +  }
   1.228 +};
   1.229 +
   1.230 +template
   1.231 +<
   1.232 +  typename KeyCons1,typename Value1,
   1.233 +  typename KeyCons2, typename Value2,
   1.234 +  typename EqualCons
   1.235 +>
   1.236 +struct equal_ckey_ckey_normal
   1.237 +{
   1.238 +  static bool compare(
   1.239 +    const KeyCons1& c0,const Value1& v0,
   1.240 +    const KeyCons2& c1,const Value2& v1,
   1.241 +    const EqualCons& eq)
   1.242 +  {
   1.243 +    if(!eq.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return false;
   1.244 +    return equal_ckey_ckey<
   1.245 +      BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
   1.246 +      BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
   1.247 +      BOOST_DEDUCED_TYPENAME EqualCons::tail_type
   1.248 +    >::compare(c0.get_tail(),v0,c1.get_tail(),v1,eq.get_tail());
   1.249 +  }
   1.250 +};
   1.251 +
   1.252 +template
   1.253 +<
   1.254 +  typename KeyCons1,typename Value1,
   1.255 +  typename KeyCons2, typename Value2,
   1.256 +  typename EqualCons
   1.257 +>
   1.258 +struct equal_ckey_ckey:
   1.259 +  mpl::if_<
   1.260 +    mpl::or_<
   1.261 +      is_same<KeyCons1,tuples::null_type>,
   1.262 +      is_same<KeyCons2,tuples::null_type>
   1.263 +    >,
   1.264 +    equal_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>,
   1.265 +    equal_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>
   1.266 +  >::type
   1.267 +{
   1.268 +};
   1.269 +
   1.270 +template
   1.271 +<
   1.272 +  typename KeyCons,typename Value,
   1.273 +  typename ValCons,typename EqualCons
   1.274 +>
   1.275 +struct equal_ckey_cval; /* fwd decl. */
   1.276 +
   1.277 +template
   1.278 +<
   1.279 +  typename KeyCons,typename Value,
   1.280 +  typename ValCons,typename EqualCons
   1.281 +>
   1.282 +struct equal_ckey_cval_terminal
   1.283 +{
   1.284 +  static bool compare(
   1.285 +    const KeyCons&,const Value&,const ValCons&,const EqualCons&)
   1.286 +  {
   1.287 +    return true;
   1.288 +  }
   1.289 +
   1.290 +  static bool compare(
   1.291 +    const ValCons&,const KeyCons&,const Value&,const EqualCons&)
   1.292 +  {
   1.293 +    return true;
   1.294 +  }
   1.295 +};
   1.296 +
   1.297 +template
   1.298 +<
   1.299 +  typename KeyCons,typename Value,
   1.300 +  typename ValCons,typename EqualCons
   1.301 +>
   1.302 +struct equal_ckey_cval_normal
   1.303 +{
   1.304 +  static bool compare(
   1.305 +    const KeyCons& c,const Value& v,const ValCons& vc,
   1.306 +    const EqualCons& eq)
   1.307 +  {
   1.308 +    if(!eq.get_head()(c.get_head()(v),vc.get_head()))return false;
   1.309 +    return equal_ckey_cval<
   1.310 +      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
   1.311 +      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
   1.312 +      BOOST_DEDUCED_TYPENAME EqualCons::tail_type
   1.313 +    >::compare(c.get_tail(),v,vc.get_tail(),eq.get_tail());
   1.314 +  }
   1.315 +
   1.316 +  static bool compare(
   1.317 +    const ValCons& vc,const KeyCons& c,const Value& v,
   1.318 +    const EqualCons& eq)
   1.319 +  {
   1.320 +    if(!eq.get_head()(vc.get_head(),c.get_head()(v)))return false;
   1.321 +    return equal_ckey_cval<
   1.322 +      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
   1.323 +      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
   1.324 +      BOOST_DEDUCED_TYPENAME EqualCons::tail_type
   1.325 +    >::compare(vc.get_tail(),c.get_tail(),v,eq.get_tail());
   1.326 +  }
   1.327 +};
   1.328 +
   1.329 +template
   1.330 +<
   1.331 +  typename KeyCons,typename Value,
   1.332 +  typename ValCons,typename EqualCons
   1.333 +>
   1.334 +struct equal_ckey_cval:
   1.335 +  mpl::if_<
   1.336 +    mpl::or_<
   1.337 +      is_same<KeyCons,tuples::null_type>,
   1.338 +      is_same<ValCons,tuples::null_type>
   1.339 +    >,
   1.340 +    equal_ckey_cval_terminal<KeyCons,Value,ValCons,EqualCons>,
   1.341 +    equal_ckey_cval_normal<KeyCons,Value,ValCons,EqualCons>
   1.342 +  >::type
   1.343 +{
   1.344 +};
   1.345 +
   1.346 +template
   1.347 +<
   1.348 +  typename KeyCons1,typename Value1,
   1.349 +  typename KeyCons2, typename Value2,
   1.350 +  typename CompareCons
   1.351 +>
   1.352 +struct compare_ckey_ckey; /* fwd decl. */
   1.353 +
   1.354 +template
   1.355 +<
   1.356 +  typename KeyCons1,typename Value1,
   1.357 +  typename KeyCons2, typename Value2,
   1.358 +  typename CompareCons
   1.359 +>
   1.360 +struct compare_ckey_ckey_terminal
   1.361 +{
   1.362 +  static bool compare(
   1.363 +    const KeyCons1&,const Value1&,
   1.364 +    const KeyCons2&,const Value2&,
   1.365 +    const CompareCons&)
   1.366 +  {
   1.367 +    return false;
   1.368 +  }
   1.369 +};
   1.370 +
   1.371 +template
   1.372 +<
   1.373 +  typename KeyCons1,typename Value1,
   1.374 +  typename KeyCons2, typename Value2,
   1.375 +  typename CompareCons
   1.376 +>
   1.377 +struct compare_ckey_ckey_normal
   1.378 +{
   1.379 +  static bool compare(
   1.380 +    const KeyCons1& c0,const Value1& v0,
   1.381 +    const KeyCons2& c1,const Value2& v1,
   1.382 +    const CompareCons& comp)
   1.383 +  {
   1.384 +    if(comp.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return true;
   1.385 +    if(comp.get_head()(c1.get_head()(v1),c0.get_head()(v0)))return false;
   1.386 +    return compare_ckey_ckey<
   1.387 +      BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
   1.388 +      BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
   1.389 +      BOOST_DEDUCED_TYPENAME CompareCons::tail_type
   1.390 +    >::compare(c0.get_tail(),v0,c1.get_tail(),v1,comp.get_tail());
   1.391 +  }
   1.392 +};
   1.393 +
   1.394 +template
   1.395 +<
   1.396 +  typename KeyCons1,typename Value1,
   1.397 +  typename KeyCons2, typename Value2,
   1.398 +  typename CompareCons
   1.399 +>
   1.400 +struct compare_ckey_ckey:
   1.401 +  mpl::if_<
   1.402 +    mpl::or_<
   1.403 +      is_same<KeyCons1,tuples::null_type>,
   1.404 +      is_same<KeyCons2,tuples::null_type>
   1.405 +    >,
   1.406 +    compare_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>,
   1.407 +    compare_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>
   1.408 +  >::type
   1.409 +{
   1.410 +};
   1.411 +
   1.412 +template
   1.413 +<
   1.414 +  typename KeyCons,typename Value,
   1.415 +  typename ValCons,typename CompareCons
   1.416 +>
   1.417 +struct compare_ckey_cval; /* fwd decl. */
   1.418 +
   1.419 +template
   1.420 +<
   1.421 +  typename KeyCons,typename Value,
   1.422 +  typename ValCons,typename CompareCons
   1.423 +>
   1.424 +struct compare_ckey_cval_terminal
   1.425 +{
   1.426 +  static bool compare(
   1.427 +    const KeyCons&,const Value&,const ValCons&,const CompareCons&)
   1.428 +  {
   1.429 +    return false;
   1.430 +  }
   1.431 +
   1.432 +  static bool compare(
   1.433 +    const ValCons&,const KeyCons&,const Value&,const CompareCons&)
   1.434 +  {
   1.435 +    return false;
   1.436 +  }
   1.437 +};
   1.438 +
   1.439 +template
   1.440 +<
   1.441 +  typename KeyCons,typename Value,
   1.442 +  typename ValCons,typename CompareCons
   1.443 +>
   1.444 +struct compare_ckey_cval_normal
   1.445 +{
   1.446 +  static bool compare(
   1.447 +    const KeyCons& c,const Value& v,const ValCons& vc,
   1.448 +    const CompareCons& comp)
   1.449 +  {
   1.450 +    if(comp.get_head()(c.get_head()(v),vc.get_head()))return true;
   1.451 +    if(comp.get_head()(vc.get_head(),c.get_head()(v)))return false;
   1.452 +    return compare_ckey_cval<
   1.453 +      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
   1.454 +      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
   1.455 +      BOOST_DEDUCED_TYPENAME CompareCons::tail_type
   1.456 +    >::compare(c.get_tail(),v,vc.get_tail(),comp.get_tail());
   1.457 +  }
   1.458 +
   1.459 +  static bool compare(
   1.460 +    const ValCons& vc,const KeyCons& c,const Value& v,
   1.461 +    const CompareCons& comp)
   1.462 +  {
   1.463 +    if(comp.get_head()(vc.get_head(),c.get_head()(v)))return true;
   1.464 +    if(comp.get_head()(c.get_head()(v),vc.get_head()))return false;
   1.465 +    return compare_ckey_cval<
   1.466 +      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
   1.467 +      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
   1.468 +      BOOST_DEDUCED_TYPENAME CompareCons::tail_type
   1.469 +    >::compare(vc.get_tail(),c.get_tail(),v,comp.get_tail());
   1.470 +  }
   1.471 +};
   1.472 +
   1.473 +template
   1.474 +<
   1.475 +  typename KeyCons,typename Value,
   1.476 +  typename ValCons,typename CompareCons
   1.477 +>
   1.478 +struct compare_ckey_cval:
   1.479 +  mpl::if_<
   1.480 +    mpl::or_<
   1.481 +      is_same<KeyCons,tuples::null_type>,
   1.482 +      is_same<ValCons,tuples::null_type>
   1.483 +    >,
   1.484 +    compare_ckey_cval_terminal<KeyCons,Value,ValCons,CompareCons>,
   1.485 +    compare_ckey_cval_normal<KeyCons,Value,ValCons,CompareCons>
   1.486 +  >::type
   1.487 +{
   1.488 +};
   1.489 +
   1.490 +template<typename KeyCons,typename Value,typename HashCons>
   1.491 +struct hash_ckey; /* fwd decl. */
   1.492 +
   1.493 +template<typename KeyCons,typename Value,typename HashCons>
   1.494 +struct hash_ckey_terminal
   1.495 +{
   1.496 +  static std::size_t hash(
   1.497 +    const KeyCons&,const Value&,const HashCons&,std::size_t carry)
   1.498 +  {
   1.499 +    return carry;
   1.500 +  }
   1.501 +};
   1.502 +
   1.503 +template<typename KeyCons,typename Value,typename HashCons>
   1.504 +struct hash_ckey_normal
   1.505 +{
   1.506 +  static std::size_t hash(
   1.507 +    const KeyCons& c,const Value& v,const HashCons& h,std::size_t carry=0)
   1.508 +  {
   1.509 +    /* same hashing formula as boost::hash_combine */
   1.510 +
   1.511 +    carry^=h.get_head()(c.get_head()(v))+0x9e3779b9+(carry<<6)+(carry>>2);
   1.512 +    return hash_ckey<
   1.513 +      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
   1.514 +      BOOST_DEDUCED_TYPENAME HashCons::tail_type
   1.515 +    >::hash(c.get_tail(),v,h.get_tail(),carry);
   1.516 +  }
   1.517 +};
   1.518 +
   1.519 +template<typename KeyCons,typename Value,typename HashCons>
   1.520 +struct hash_ckey:
   1.521 +  mpl::if_<
   1.522 +    is_same<KeyCons,tuples::null_type>,
   1.523 +    hash_ckey_terminal<KeyCons,Value,HashCons>,
   1.524 +    hash_ckey_normal<KeyCons,Value,HashCons>
   1.525 +  >::type
   1.526 +{
   1.527 +};
   1.528 +
   1.529 +template<typename ValCons,typename HashCons>
   1.530 +struct hash_cval; /* fwd decl. */
   1.531 +
   1.532 +template<typename ValCons,typename HashCons>
   1.533 +struct hash_cval_terminal
   1.534 +{
   1.535 +  static std::size_t hash(const ValCons&,const HashCons&,std::size_t carry)
   1.536 +  {
   1.537 +    return carry;
   1.538 +  }
   1.539 +};
   1.540 +
   1.541 +template<typename ValCons,typename HashCons>
   1.542 +struct hash_cval_normal
   1.543 +{
   1.544 +  static std::size_t hash(
   1.545 +    const ValCons& vc,const HashCons& h,std::size_t carry=0)
   1.546 +  {
   1.547 +    carry^=h.get_head()(vc.get_head())+0x9e3779b9+(carry<<6)+(carry>>2);
   1.548 +    return hash_cval<
   1.549 +      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
   1.550 +      BOOST_DEDUCED_TYPENAME HashCons::tail_type
   1.551 +    >::hash(vc.get_tail(),h.get_tail(),carry);
   1.552 +  }
   1.553 +};
   1.554 +
   1.555 +template<typename ValCons,typename HashCons>
   1.556 +struct hash_cval:
   1.557 +  mpl::if_<
   1.558 +    is_same<ValCons,tuples::null_type>,
   1.559 +    hash_cval_terminal<ValCons,HashCons>,
   1.560 +    hash_cval_normal<ValCons,HashCons>
   1.561 +  >::type
   1.562 +{
   1.563 +};
   1.564 +
   1.565 +} /* namespace multi_index::detail */
   1.566 +
   1.567 +/* composite_key_result */
   1.568 +
   1.569 +template<typename CompositeKey>
   1.570 +struct composite_key_result
   1.571 +{
   1.572 +  typedef CompositeKey                            composite_key_type;
   1.573 +  typedef typename composite_key_type::value_type value_type;
   1.574 +
   1.575 +  composite_key_result(
   1.576 +    const composite_key_type& composite_key_,const value_type& value_):
   1.577 +    composite_key(composite_key_),value(value_)
   1.578 +  {}
   1.579 +
   1.580 +  const composite_key_type& composite_key;
   1.581 +  const value_type&         value;
   1.582 +};
   1.583 +
   1.584 +/* composite_key */
   1.585 +
   1.586 +/* NB. Some overloads of operator() have an extra dummy parameter int=0.
   1.587 + * This disambiguator serves several purposes:
   1.588 + *  - Without it, MSVC++ 6.0 incorrectly regards some overloads as
   1.589 + *    specializations of a previous member function template.
   1.590 + *  - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
   1.591 + *    as if they have the same signature.
   1.592 + *  - If remove_const is broken due to lack of PTS, int=0 avoids the
   1.593 + *    declaration of memfuns with identical signature.
   1.594 + */
   1.595 +
   1.596 +template<
   1.597 +  typename Value,
   1.598 +  BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,KeyFromValue)
   1.599 +>
   1.600 +struct composite_key:
   1.601 +  private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)>
   1.602 +{
   1.603 +private:
   1.604 +  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)> super;
   1.605 +
   1.606 +public:
   1.607 +  typedef super                               key_extractor_tuple;
   1.608 +  typedef Value                               value_type;
   1.609 +  typedef composite_key_result<composite_key> result_type;
   1.610 +
   1.611 +  composite_key(
   1.612 +    BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,KeyFromValue)):
   1.613 +    super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
   1.614 +  {}
   1.615 +
   1.616 +  composite_key(const key_extractor_tuple& x):super(x){}
   1.617 +
   1.618 +  const key_extractor_tuple& key_extractors()const{return *this;}
   1.619 +  key_extractor_tuple&       key_extractors(){return *this;}
   1.620 +
   1.621 +  template<typename ChainedPtr>
   1.622 +
   1.623 +#if !defined(BOOST_NO_SFINAE)
   1.624 +  typename disable_if<
   1.625 +    is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
   1.626 +#else
   1.627 +  result_type
   1.628 +#endif
   1.629 +
   1.630 +  operator()(const ChainedPtr& x)const
   1.631 +  {
   1.632 +    return operator()(*x);
   1.633 +  }
   1.634 +
   1.635 +  result_type operator()(const value_type& x)const
   1.636 +  {
   1.637 +    return result_type(*this,x);
   1.638 +  }
   1.639 +
   1.640 +  result_type operator()(const reference_wrapper<const value_type>& x)const
   1.641 +  {
   1.642 +    return result_type(*this,x.get());
   1.643 +  }
   1.644 +
   1.645 +  result_type operator()(const reference_wrapper<value_type>& x,int=0)const
   1.646 +  {
   1.647 +    return result_type(*this,x.get());
   1.648 +  }
   1.649 +};
   1.650 +
   1.651 +/* comparison operators */
   1.652 +
   1.653 +/* == */
   1.654 +
   1.655 +template<typename CompositeKey1,typename CompositeKey2>
   1.656 +inline bool operator==(
   1.657 +  const composite_key_result<CompositeKey1>& x,
   1.658 +  const composite_key_result<CompositeKey2>& y)
   1.659 +{
   1.660 +  typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
   1.661 +  typedef typename CompositeKey1::value_type          value_type1;
   1.662 +  typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
   1.663 +  typedef typename CompositeKey2::value_type          value_type2;
   1.664 +
   1.665 +  BOOST_STATIC_ASSERT(
   1.666 +    tuples::length<key_extractor_tuple1>::value==
   1.667 +    tuples::length<key_extractor_tuple2>::value);
   1.668 +
   1.669 +  return detail::equal_ckey_ckey<
   1.670 +    key_extractor_tuple1,value_type1,
   1.671 +    key_extractor_tuple2,value_type2,
   1.672 +    detail::generic_operator_equal_tuple
   1.673 +  >::compare(
   1.674 +    x.composite_key.key_extractors(),x.value,
   1.675 +    y.composite_key.key_extractors(),y.value,
   1.676 +    detail::generic_operator_equal_tuple());
   1.677 +}
   1.678 +
   1.679 +template<
   1.680 +  typename CompositeKey,
   1.681 +  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
   1.682 +>
   1.683 +inline bool operator==(
   1.684 +  const composite_key_result<CompositeKey>& x,
   1.685 +  const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
   1.686 +{
   1.687 +  typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
   1.688 +  typedef typename CompositeKey::value_type              value_type;
   1.689 +  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
   1.690 +  
   1.691 +  BOOST_STATIC_ASSERT(
   1.692 +    tuples::length<key_extractor_tuple>::value==
   1.693 +    tuples::length<key_tuple>::value);
   1.694 +
   1.695 +  return detail::equal_ckey_cval<
   1.696 +    key_extractor_tuple,value_type,
   1.697 +    key_tuple,detail::generic_operator_equal_tuple
   1.698 +  >::compare(
   1.699 +    x.composite_key.key_extractors(),x.value,
   1.700 +    y,detail::generic_operator_equal_tuple());
   1.701 +}
   1.702 +
   1.703 +template
   1.704 +<
   1.705 +  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
   1.706 +  typename CompositeKey
   1.707 +>
   1.708 +inline bool operator==(
   1.709 +  const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
   1.710 +  const composite_key_result<CompositeKey>& y)
   1.711 +{
   1.712 +  typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
   1.713 +  typedef typename CompositeKey::value_type              value_type;
   1.714 +  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
   1.715 +  
   1.716 +  BOOST_STATIC_ASSERT(
   1.717 +    tuples::length<key_extractor_tuple>::value==
   1.718 +    tuples::length<key_tuple>::value);
   1.719 +
   1.720 +  return detail::equal_ckey_cval<
   1.721 +    key_extractor_tuple,value_type,
   1.722 +    key_tuple,detail::generic_operator_equal_tuple
   1.723 +  >::compare(
   1.724 +    x,y.composite_key.key_extractors(),
   1.725 +    y.value,detail::generic_operator_equal_tuple());
   1.726 +}
   1.727 +
   1.728 +/* < */
   1.729 +
   1.730 +template<typename CompositeKey1,typename CompositeKey2>
   1.731 +inline bool operator<(
   1.732 +  const composite_key_result<CompositeKey1>& x,
   1.733 +  const composite_key_result<CompositeKey2>& y)
   1.734 +{
   1.735 +  typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
   1.736 +  typedef typename CompositeKey1::value_type          value_type1;
   1.737 +  typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
   1.738 +  typedef typename CompositeKey2::value_type          value_type2;
   1.739 +
   1.740 +  return detail::compare_ckey_ckey<
   1.741 +   key_extractor_tuple1,value_type1,
   1.742 +   key_extractor_tuple2,value_type2,
   1.743 +   detail::generic_operator_less_tuple
   1.744 +  >::compare(
   1.745 +    x.composite_key.key_extractors(),x.value,
   1.746 +    y.composite_key.key_extractors(),y.value,
   1.747 +    detail::generic_operator_less_tuple());
   1.748 +}
   1.749 +
   1.750 +template
   1.751 +<
   1.752 +  typename CompositeKey,
   1.753 +  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
   1.754 +>
   1.755 +inline bool operator<(
   1.756 +  const composite_key_result<CompositeKey>& x,
   1.757 +  const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
   1.758 +{
   1.759 +  typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
   1.760 +  typedef typename CompositeKey::value_type              value_type;
   1.761 +  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
   1.762 +  
   1.763 +  return detail::compare_ckey_cval<
   1.764 +    key_extractor_tuple,value_type,
   1.765 +    key_tuple,detail::generic_operator_less_tuple
   1.766 +  >::compare(
   1.767 +    x.composite_key.key_extractors(),x.value,
   1.768 +    y,detail::generic_operator_less_tuple());
   1.769 +}
   1.770 +
   1.771 +template
   1.772 +<
   1.773 +  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
   1.774 +  typename CompositeKey
   1.775 +>
   1.776 +inline bool operator<(
   1.777 +  const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
   1.778 +  const composite_key_result<CompositeKey>& y)
   1.779 +{
   1.780 +  typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
   1.781 +  typedef typename CompositeKey::value_type              value_type;
   1.782 +  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
   1.783 +  
   1.784 +  return detail::compare_ckey_cval<
   1.785 +    key_extractor_tuple,value_type,
   1.786 +    key_tuple,detail::generic_operator_less_tuple
   1.787 +  >::compare(
   1.788 +    x,y.composite_key.key_extractors(),
   1.789 +    y.value,detail::generic_operator_less_tuple());
   1.790 +}
   1.791 +
   1.792 +/* rest of comparison operators */
   1.793 +
   1.794 +#define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2)                  \
   1.795 +template<t1,t2> inline bool operator!=(const a1& x,const a2& y)              \
   1.796 +{                                                                            \
   1.797 +  return !(x==y);                                                            \
   1.798 +}                                                                            \
   1.799 +                                                                             \
   1.800 +template<t1,t2> inline bool operator>(const a1& x,const a2& y)               \
   1.801 +{                                                                            \
   1.802 +  return y<x;                                                                \
   1.803 +}                                                                            \
   1.804 +                                                                             \
   1.805 +template<t1,t2> inline bool operator>=(const a1& x,const a2& y)              \
   1.806 +{                                                                            \
   1.807 +  return !(x<y);                                                             \
   1.808 +}                                                                            \
   1.809 +                                                                             \
   1.810 +template<t1,t2> inline bool operator<=(const a1& x,const a2& y)              \
   1.811 +{                                                                            \
   1.812 +  return !(y<x);                                                             \
   1.813 +}
   1.814 +
   1.815 +BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
   1.816 +  typename CompositeKey1,
   1.817 +  typename CompositeKey2,
   1.818 +  composite_key_result<CompositeKey1>,
   1.819 +  composite_key_result<CompositeKey2>
   1.820 +)
   1.821 +
   1.822 +BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
   1.823 +  typename CompositeKey,
   1.824 +  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
   1.825 +  composite_key_result<CompositeKey>,
   1.826 +  tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>
   1.827 +)
   1.828 +
   1.829 +BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
   1.830 +  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
   1.831 +  typename CompositeKey,
   1.832 +  tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>,
   1.833 +  composite_key_result<CompositeKey>
   1.834 +)
   1.835 +
   1.836 +/* composite_key_equal_to */
   1.837 +
   1.838 +template
   1.839 +<
   1.840 +  BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Pred)
   1.841 +>
   1.842 +struct composite_key_equal_to:
   1.843 +  private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)>
   1.844 +{
   1.845 +private:
   1.846 +  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)> super;
   1.847 +
   1.848 +public:
   1.849 +  typedef super key_eq_tuple;
   1.850 +
   1.851 +  composite_key_equal_to(
   1.852 +    BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Pred)):
   1.853 +    super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
   1.854 +  {}
   1.855 +
   1.856 +  composite_key_equal_to(const key_eq_tuple& x):super(x){}
   1.857 +
   1.858 +  const key_eq_tuple& key_eqs()const{return *this;}
   1.859 +  key_eq_tuple&       key_eqs(){return *this;}
   1.860 +
   1.861 +  template<typename CompositeKey1,typename CompositeKey2>
   1.862 +  bool operator()(
   1.863 +    const composite_key_result<CompositeKey1> & x,
   1.864 +    const composite_key_result<CompositeKey2> & y)const
   1.865 +  {
   1.866 +    typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
   1.867 +    typedef typename CompositeKey1::value_type          value_type1;
   1.868 +    typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
   1.869 +    typedef typename CompositeKey2::value_type          value_type2;
   1.870 +
   1.871 +    BOOST_STATIC_ASSERT(
   1.872 +      tuples::length<key_extractor_tuple1>::value<=
   1.873 +      tuples::length<key_eq_tuple>::value&&
   1.874 +      tuples::length<key_extractor_tuple1>::value==
   1.875 +      tuples::length<key_extractor_tuple2>::value);
   1.876 +
   1.877 +    return detail::equal_ckey_ckey<
   1.878 +      key_extractor_tuple1,value_type1,
   1.879 +      key_extractor_tuple2,value_type2,
   1.880 +      key_eq_tuple
   1.881 +    >::compare(
   1.882 +      x.composite_key.key_extractors(),x.value,
   1.883 +      y.composite_key.key_extractors(),y.value,
   1.884 +      key_eqs());
   1.885 +  }
   1.886 +  
   1.887 +  template
   1.888 +  <
   1.889 +    typename CompositeKey,
   1.890 +    BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
   1.891 +  >
   1.892 +  bool operator()(
   1.893 +    const composite_key_result<CompositeKey>& x,
   1.894 +    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
   1.895 +  {
   1.896 +    typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
   1.897 +    typedef typename CompositeKey::value_type              value_type;
   1.898 +    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
   1.899 +
   1.900 +    BOOST_STATIC_ASSERT(
   1.901 +      tuples::length<key_extractor_tuple>::value<=
   1.902 +      tuples::length<key_eq_tuple>::value&&
   1.903 +      tuples::length<key_extractor_tuple>::value==
   1.904 +      tuples::length<key_tuple>::value);
   1.905 +
   1.906 +    return detail::equal_ckey_cval<
   1.907 +      key_extractor_tuple,value_type,
   1.908 +      key_tuple,key_eq_tuple
   1.909 +    >::compare(x.composite_key.key_extractors(),x.value,y,key_eqs());
   1.910 +  }
   1.911 +
   1.912 +  template
   1.913 +  <
   1.914 +    BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
   1.915 +    typename CompositeKey
   1.916 +  >
   1.917 +  bool operator()(
   1.918 +    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
   1.919 +    const composite_key_result<CompositeKey>& y)const
   1.920 +  {
   1.921 +    typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
   1.922 +    typedef typename CompositeKey::value_type              value_type;
   1.923 +    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
   1.924 +
   1.925 +    BOOST_STATIC_ASSERT(
   1.926 +      tuples::length<key_tuple>::value<=
   1.927 +      tuples::length<key_eq_tuple>::value&&
   1.928 +      tuples::length<key_tuple>::value==
   1.929 +      tuples::length<key_extractor_tuple>::value);
   1.930 +
   1.931 +    return detail::equal_ckey_cval<
   1.932 +      key_extractor_tuple,value_type,
   1.933 +      key_tuple,key_eq_tuple
   1.934 +    >::compare(x,y.composite_key.key_extractors(),y.value,key_eqs());
   1.935 +  }
   1.936 +};
   1.937 +
   1.938 +/* composite_key_compare */
   1.939 +
   1.940 +template
   1.941 +<
   1.942 +  BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Compare)
   1.943 +>
   1.944 +struct composite_key_compare:
   1.945 +  private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)>
   1.946 +{
   1.947 +private:
   1.948 +  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)> super;
   1.949 +
   1.950 +public:
   1.951 +  typedef super key_comp_tuple;
   1.952 +
   1.953 +  composite_key_compare(
   1.954 +    BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Compare)):
   1.955 +    super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
   1.956 +  {}
   1.957 +
   1.958 +  composite_key_compare(const key_comp_tuple& x):super(x){}
   1.959 +
   1.960 +  const key_comp_tuple& key_comps()const{return *this;}
   1.961 +  key_comp_tuple&       key_comps(){return *this;}
   1.962 +
   1.963 +  template<typename CompositeKey1,typename CompositeKey2>
   1.964 +  bool operator()(
   1.965 +    const composite_key_result<CompositeKey1> & x,
   1.966 +    const composite_key_result<CompositeKey2> & y)const
   1.967 +  {
   1.968 +    typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
   1.969 +    typedef typename CompositeKey1::value_type          value_type1;
   1.970 +    typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
   1.971 +    typedef typename CompositeKey2::value_type          value_type2;
   1.972 +
   1.973 +    BOOST_STATIC_ASSERT(
   1.974 +      tuples::length<key_extractor_tuple1>::value<=
   1.975 +      tuples::length<key_comp_tuple>::value||
   1.976 +      tuples::length<key_extractor_tuple2>::value<=
   1.977 +      tuples::length<key_comp_tuple>::value);
   1.978 +
   1.979 +    return detail::compare_ckey_ckey<
   1.980 +      key_extractor_tuple1,value_type1,
   1.981 +      key_extractor_tuple2,value_type2,
   1.982 +      key_comp_tuple
   1.983 +    >::compare(
   1.984 +      x.composite_key.key_extractors(),x.value,
   1.985 +      y.composite_key.key_extractors(),y.value,
   1.986 +      key_comps());
   1.987 +  }
   1.988 +  
   1.989 +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
   1.990 +  template<typename CompositeKey,typename Value>
   1.991 +  bool operator()(
   1.992 +    const composite_key_result<CompositeKey>& x,
   1.993 +    const Value& y)const
   1.994 +  {
   1.995 +    return operator()(x,make_tuple(cref(y)));
   1.996 +  }
   1.997 +#endif
   1.998 +
   1.999 +  template
  1.1000 +  <
  1.1001 +    typename CompositeKey,
  1.1002 +    BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
  1.1003 +  >
  1.1004 +  bool operator()(
  1.1005 +    const composite_key_result<CompositeKey>& x,
  1.1006 +    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
  1.1007 +  {
  1.1008 +    typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
  1.1009 +    typedef typename CompositeKey::value_type              value_type;
  1.1010 +    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  1.1011 +
  1.1012 +    BOOST_STATIC_ASSERT(
  1.1013 +      tuples::length<key_extractor_tuple>::value<=
  1.1014 +      tuples::length<key_comp_tuple>::value||
  1.1015 +      tuples::length<key_tuple>::value<=
  1.1016 +      tuples::length<key_comp_tuple>::value);
  1.1017 +
  1.1018 +    return detail::compare_ckey_cval<
  1.1019 +      key_extractor_tuple,value_type,
  1.1020 +      key_tuple,key_comp_tuple
  1.1021 +    >::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
  1.1022 +  }
  1.1023 +
  1.1024 +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  1.1025 +  template<typename Value,typename CompositeKey>
  1.1026 +  bool operator()(
  1.1027 +    const Value& x,
  1.1028 +    const composite_key_result<CompositeKey>& y)const
  1.1029 +  {
  1.1030 +    return operator()(make_tuple(cref(x)),y);
  1.1031 +  }
  1.1032 +#endif
  1.1033 +
  1.1034 +  template
  1.1035 +  <
  1.1036 +    BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
  1.1037 +    typename CompositeKey
  1.1038 +  >
  1.1039 +  bool operator()(
  1.1040 +    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
  1.1041 +    const composite_key_result<CompositeKey>& y)const
  1.1042 +  {
  1.1043 +    typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
  1.1044 +    typedef typename CompositeKey::value_type              value_type;
  1.1045 +    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  1.1046 +
  1.1047 +    BOOST_STATIC_ASSERT(
  1.1048 +      tuples::length<key_tuple>::value<=
  1.1049 +      tuples::length<key_comp_tuple>::value||
  1.1050 +      tuples::length<key_extractor_tuple>::value<=
  1.1051 +      tuples::length<key_comp_tuple>::value);
  1.1052 +
  1.1053 +    return detail::compare_ckey_cval<
  1.1054 +      key_extractor_tuple,value_type,
  1.1055 +      key_tuple,key_comp_tuple
  1.1056 +    >::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
  1.1057 +  }
  1.1058 +};
  1.1059 +
  1.1060 +/* composite_key_hash */
  1.1061 +
  1.1062 +template
  1.1063 +<
  1.1064 +  BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Hash)
  1.1065 +>
  1.1066 +struct composite_key_hash:
  1.1067 +  private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)>
  1.1068 +{
  1.1069 +private:
  1.1070 +  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)> super;
  1.1071 +
  1.1072 +public:
  1.1073 +  typedef super key_hasher_tuple;
  1.1074 +
  1.1075 +  composite_key_hash(
  1.1076 +    BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Hash)):
  1.1077 +    super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
  1.1078 +  {}
  1.1079 +
  1.1080 +  composite_key_hash(const key_hasher_tuple& x):super(x){}
  1.1081 +
  1.1082 +  const key_hasher_tuple& key_hash_functions()const{return *this;}
  1.1083 +  key_hasher_tuple&       key_hash_functions(){return *this;}
  1.1084 +
  1.1085 +  template<typename CompositeKey>
  1.1086 +  std::size_t operator()(const composite_key_result<CompositeKey> & x)const
  1.1087 +  {
  1.1088 +    typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  1.1089 +    typedef typename CompositeKey::value_type          value_type;
  1.1090 +
  1.1091 +    BOOST_STATIC_ASSERT(
  1.1092 +      tuples::length<key_extractor_tuple>::value==
  1.1093 +      tuples::length<key_hasher_tuple>::value);
  1.1094 +
  1.1095 +    return detail::hash_ckey<
  1.1096 +      key_extractor_tuple,value_type,
  1.1097 +      key_hasher_tuple
  1.1098 +    >::hash(x.composite_key.key_extractors(),x.value,key_hash_functions());
  1.1099 +  }
  1.1100 +  
  1.1101 +  template<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)>
  1.1102 +  std::size_t operator()(
  1.1103 +    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x)const
  1.1104 +  {
  1.1105 +    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  1.1106 +
  1.1107 +    BOOST_STATIC_ASSERT(
  1.1108 +      tuples::length<key_tuple>::value==
  1.1109 +      tuples::length<key_hasher_tuple>::value);
  1.1110 +
  1.1111 +    return detail::hash_cval<
  1.1112 +      key_tuple,key_hasher_tuple
  1.1113 +    >::hash(x,key_hash_functions());
  1.1114 +  }
  1.1115 +};
  1.1116 +
  1.1117 +/* Instantiations of the former functors with "natural" basic components:
  1.1118 + * composite_key_result_equal_to uses std::equal_to of the values.
  1.1119 + * composite_key_result_less     uses std::less.
  1.1120 + * composite_key_result_greater  uses std::greater.
  1.1121 + * composite_key_result_hash     uses boost::hash.
  1.1122 + */
  1.1123 +
  1.1124 +#define BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER                           \
  1.1125 +composite_key_equal_to<                                                      \
  1.1126 +    BOOST_MULTI_INDEX_CK_ENUM(                                               \
  1.1127 +      BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
  1.1128 +      /* the argument is a PP list */                                        \
  1.1129 +      (detail::nth_composite_key_equal_to,                                   \
  1.1130 +        (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
  1.1131 +          BOOST_PP_NIL)))                                                    \
  1.1132 +  >
  1.1133 +
  1.1134 +template<typename CompositeKeyResult>
  1.1135 +struct composite_key_result_equal_to:
  1.1136 +BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
  1.1137 +BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
  1.1138 +{
  1.1139 +private:
  1.1140 +  typedef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER super;
  1.1141 +
  1.1142 +public:
  1.1143 +  typedef CompositeKeyResult  first_argument_type;
  1.1144 +  typedef first_argument_type second_argument_type;
  1.1145 +  typedef bool                result_type;
  1.1146 +
  1.1147 +  using super::operator();
  1.1148 +};
  1.1149 +
  1.1150 +#define BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER                               \
  1.1151 +composite_key_compare<                                                       \
  1.1152 +    BOOST_MULTI_INDEX_CK_ENUM(                                               \
  1.1153 +      BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
  1.1154 +      /* the argument is a PP list */                                        \
  1.1155 +      (detail::nth_composite_key_less,                                       \
  1.1156 +        (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
  1.1157 +          BOOST_PP_NIL)))                                                    \
  1.1158 +  >
  1.1159 +
  1.1160 +template<typename CompositeKeyResult>
  1.1161 +struct composite_key_result_less:
  1.1162 +BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
  1.1163 +BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
  1.1164 +{
  1.1165 +private:
  1.1166 +  typedef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER super;
  1.1167 +
  1.1168 +public:
  1.1169 +  typedef CompositeKeyResult  first_argument_type;
  1.1170 +  typedef first_argument_type second_argument_type;
  1.1171 +  typedef bool                result_type;
  1.1172 +
  1.1173 +  using super::operator();
  1.1174 +};
  1.1175 +
  1.1176 +#define BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER                            \
  1.1177 +composite_key_compare<                                                       \
  1.1178 +    BOOST_MULTI_INDEX_CK_ENUM(                                               \
  1.1179 +      BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
  1.1180 +      /* the argument is a PP list */                                        \
  1.1181 +      (detail::nth_composite_key_greater,                                    \
  1.1182 +        (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
  1.1183 +          BOOST_PP_NIL)))                                                    \
  1.1184 +  >
  1.1185 +
  1.1186 +template<typename CompositeKeyResult>
  1.1187 +struct composite_key_result_greater:
  1.1188 +BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
  1.1189 +BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
  1.1190 +{
  1.1191 +private:
  1.1192 +  typedef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER super;
  1.1193 +
  1.1194 +public:
  1.1195 +  typedef CompositeKeyResult  first_argument_type;
  1.1196 +  typedef first_argument_type second_argument_type;
  1.1197 +  typedef bool                result_type;
  1.1198 +
  1.1199 +  using super::operator();
  1.1200 +};
  1.1201 +
  1.1202 +#define BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER                               \
  1.1203 +composite_key_hash<                                                          \
  1.1204 +    BOOST_MULTI_INDEX_CK_ENUM(                                               \
  1.1205 +      BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
  1.1206 +      /* the argument is a PP list */                                        \
  1.1207 +      (detail::nth_composite_key_hash,                                       \
  1.1208 +        (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
  1.1209 +          BOOST_PP_NIL)))                                                    \
  1.1210 +  >
  1.1211 +
  1.1212 +template<typename CompositeKeyResult>
  1.1213 +struct composite_key_result_hash:
  1.1214 +BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
  1.1215 +BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
  1.1216 +{
  1.1217 +private:
  1.1218 +  typedef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER super;
  1.1219 +
  1.1220 +public:
  1.1221 +  typedef CompositeKeyResult argument_type;
  1.1222 +  typedef std::size_t        result_type;
  1.1223 +
  1.1224 +  using super::operator();
  1.1225 +};
  1.1226 +
  1.1227 +} /* namespace multi_index */
  1.1228 +
  1.1229 +} /* namespace boost */
  1.1230 +
  1.1231 +/* Specializations of std::equal_to, std::less, std::greater and boost::hash
  1.1232 + * for composite_key_results enabling interoperation with tuples of values.
  1.1233 + */
  1.1234 +
  1.1235 +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
  1.1236 +namespace std{
  1.1237 +
  1.1238 +template<typename CompositeKey>
  1.1239 +struct equal_to<boost::multi_index::composite_key_result<CompositeKey> >:
  1.1240 +  boost::multi_index::composite_key_result_equal_to<
  1.1241 +    boost::multi_index::composite_key_result<CompositeKey>
  1.1242 +  >
  1.1243 +{
  1.1244 +};
  1.1245 +
  1.1246 +template<typename CompositeKey>
  1.1247 +struct less<boost::multi_index::composite_key_result<CompositeKey> >:
  1.1248 +  boost::multi_index::composite_key_result_less<
  1.1249 +    boost::multi_index::composite_key_result<CompositeKey>
  1.1250 +  >
  1.1251 +{
  1.1252 +};
  1.1253 +
  1.1254 +template<typename CompositeKey>
  1.1255 +struct greater<boost::multi_index::composite_key_result<CompositeKey> >:
  1.1256 +  boost::multi_index::composite_key_result_greater<
  1.1257 +    boost::multi_index::composite_key_result<CompositeKey>
  1.1258 +  >
  1.1259 +{
  1.1260 +};
  1.1261 +
  1.1262 +} /* namespace std */
  1.1263 +
  1.1264 +namespace boost{
  1.1265 +
  1.1266 +template<typename CompositeKey>
  1.1267 +struct hash<boost::multi_index::composite_key_result<CompositeKey> >:
  1.1268 +  boost::multi_index::composite_key_result_hash<
  1.1269 +    boost::multi_index::composite_key_result<CompositeKey>
  1.1270 +  >
  1.1271 +{
  1.1272 +};
  1.1273 +
  1.1274 +} /* namespace boost */
  1.1275 +#else
  1.1276 +/* Lacking template partial specialization, std::equal_to, std::less and
  1.1277 + * std::greater will still work for composite_key_results although without
  1.1278 + * tuple interoperability. To achieve the same graceful degrading with
  1.1279 + * boost::hash, we define the appropriate hash_value overload.
  1.1280 + */
  1.1281 +
  1.1282 +namespace boost{
  1.1283 +
  1.1284 +#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  1.1285 +namespace multi_index{
  1.1286 +#endif
  1.1287 +
  1.1288 +template<typename CompositeKey>
  1.1289 +inline std::size_t hash_value(
  1.1290 +  const boost::multi_index::composite_key_result<CompositeKey>& x)
  1.1291 +{
  1.1292 +  boost::multi_index::composite_key_result_hash<
  1.1293 +    boost::multi_index::composite_key_result<CompositeKey> > h;
  1.1294 +  return h(x);
  1.1295 +}
  1.1296 +
  1.1297 +#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  1.1298 +} /* namespace multi_index */
  1.1299 +#endif
  1.1300 +
  1.1301 +} /* namespace boost */
  1.1302 +#endif
  1.1303 +
  1.1304 +#undef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
  1.1305 +#undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
  1.1306 +#undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
  1.1307 +#undef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
  1.1308 +#undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
  1.1309 +#undef BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO
  1.1310 +#undef BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR
  1.1311 +#undef BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N
  1.1312 +#undef BOOST_MULTI_INDEX_CK_CTOR_ARG
  1.1313 +#undef BOOST_MULTI_INDEX_CK_TEMPLATE_PARM
  1.1314 +#undef BOOST_MULTI_INDEX_CK_ENUM_PARAMS
  1.1315 +#undef BOOST_MULTI_INDEX_CK_ENUM
  1.1316 +#undef BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE
  1.1317 +
  1.1318 +#endif