PageRenderTime 125ms CodeModel.GetById 31ms app.highlight 85ms RepoModel.GetById 2ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/multi_index/composite_key.hpp

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