1325 lines
41 KiB
C++
1325 lines
41 KiB
C++
|
/* Copyright 2003-2011 Joaquin M Lopez Munoz.
|
||
|
* Distributed under the Boost Software License, Version 1.0.
|
||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||
|
*
|
||
|
* See http://www.boost.org/libs/multi_index for library home page.
|
||
|
*/
|
||
|
|
||
|
#ifndef BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
|
||
|
#define BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
|
||
|
|
||
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||
|
#pragma once
|
||
|
#endif
|
||
|
|
||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||
|
#include <boost/functional/hash_fwd.hpp>
|
||
|
#include <boost/multi_index/detail/access_specifier.hpp>
|
||
|
#include <boost/multi_index/detail/prevent_eti.hpp>
|
||
|
#include <boost/mpl/eval_if.hpp>
|
||
|
#include <boost/mpl/identity.hpp>
|
||
|
#include <boost/mpl/if.hpp>
|
||
|
#include <boost/mpl/or.hpp>
|
||
|
#include <boost/mpl/aux_/nttp_decl.hpp>
|
||
|
#include <boost/preprocessor/cat.hpp>
|
||
|
#include <boost/preprocessor/control/expr_if.hpp>
|
||
|
#include <boost/preprocessor/list/at.hpp>
|
||
|
#include <boost/preprocessor/repetition/enum.hpp>
|
||
|
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||
|
#include <boost/static_assert.hpp>
|
||
|
#include <boost/tuple/tuple.hpp>
|
||
|
#include <boost/type_traits/is_same.hpp>
|
||
|
#include <boost/utility/enable_if.hpp>
|
||
|
#include <functional>
|
||
|
|
||
|
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||
|
#include <boost/ref.hpp>
|
||
|
#endif
|
||
|
|
||
|
#if !defined(BOOST_NO_SFINAE)
|
||
|
#include <boost/type_traits/is_convertible.hpp>
|
||
|
#endif
|
||
|
|
||
|
/* A composite key stores n key extractors and "computes" the
|
||
|
* result on a given value as a packed reference to the value and
|
||
|
* the composite key itself. Actual invocations to the component
|
||
|
* key extractors are lazily performed when executing an operation
|
||
|
* on composite_key results (equality, comparison, hashing.)
|
||
|
* As the other key extractors in Boost.MultiIndex, composite_key<T,...>
|
||
|
* is overloaded to work on chained pointers to T and reference_wrappers
|
||
|
* of T.
|
||
|
*/
|
||
|
|
||
|
/* This user_definable macro limits the number of elements of a composite
|
||
|
* key; useful for shortening resulting symbol names (MSVC++ 6.0, for
|
||
|
* instance has problems coping with very long symbol names.)
|
||
|
* NB: This cannot exceed the maximum number of arguments of
|
||
|
* boost::tuple. In Boost 1.32, the limit is 10.
|
||
|
*/
|
||
|
|
||
|
#if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
|
||
|
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
|
||
|
#define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 5
|
||
|
#else
|
||
|
#define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
/* maximum number of key extractors in a composite key */
|
||
|
|
||
|
#if BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE<10 /* max length of a tuple */
|
||
|
#define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE \
|
||
|
BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE
|
||
|
#else
|
||
|
#define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE 10
|
||
|
#endif
|
||
|
|
||
|
/* BOOST_PP_ENUM of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_ENUM(macro,data) \
|
||
|
BOOST_PP_ENUM(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,macro,data)
|
||
|
|
||
|
/* BOOST_PP_ENUM_PARAMS of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_ENUM_PARAMS(param) \
|
||
|
BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,param)
|
||
|
|
||
|
/* if n==0 -> text0
|
||
|
* otherwise -> textn=tuples::null_type
|
||
|
*/
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_TEMPLATE_PARM(z,n,text) \
|
||
|
typename BOOST_PP_CAT(text,n) BOOST_PP_EXPR_IF(n,=tuples::null_type)
|
||
|
|
||
|
/* const textn& kn=textn() */
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_CTOR_ARG(z,n,text) \
|
||
|
const BOOST_PP_CAT(text,n)& BOOST_PP_CAT(k,n) = BOOST_PP_CAT(text,n)()
|
||
|
|
||
|
/* typename list(0)<list(1),n>::type */
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N(z,n,list) \
|
||
|
BOOST_DEDUCED_TYPENAME BOOST_PP_LIST_AT(list,0)< \
|
||
|
BOOST_PP_LIST_AT(list,1),n \
|
||
|
>::type
|
||
|
|
||
|
namespace boost{
|
||
|
|
||
|
template<class T> class reference_wrapper; /* fwd decl. */
|
||
|
|
||
|
namespace multi_index{
|
||
|
|
||
|
namespace detail{
|
||
|
|
||
|
/* n-th key extractor of a composite key */
|
||
|
|
||
|
template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>
|
||
|
struct nth_key_from_value
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename prevent_eti<
|
||
|
tuples::element<N,key_extractor_tuple>,
|
||
|
typename mpl::eval_if_c<
|
||
|
N<tuples::length<key_extractor_tuple>::value,
|
||
|
tuples::element<N,key_extractor_tuple>,
|
||
|
mpl::identity<tuples::null_type>
|
||
|
>::type
|
||
|
>::type type;
|
||
|
};
|
||
|
|
||
|
/* nth_composite_key_##name<CompositeKey,N>::type yields
|
||
|
* functor<nth_key_from_value<CompositeKey,N> >, or tuples::null_type
|
||
|
* if N exceeds the length of the composite key.
|
||
|
*/
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(name,functor) \
|
||
|
template<typename KeyFromValue> \
|
||
|
struct BOOST_PP_CAT(key_,name) \
|
||
|
{ \
|
||
|
typedef functor<typename KeyFromValue::result_type> type; \
|
||
|
}; \
|
||
|
\
|
||
|
template<> \
|
||
|
struct BOOST_PP_CAT(key_,name)<tuples::null_type> \
|
||
|
{ \
|
||
|
typedef tuples::null_type type; \
|
||
|
}; \
|
||
|
\
|
||
|
template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)> \
|
||
|
struct BOOST_PP_CAT(nth_composite_key_,name) \
|
||
|
{ \
|
||
|
typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value; \
|
||
|
typedef typename BOOST_PP_CAT(key_,name)<key_from_value>::type type; \
|
||
|
};
|
||
|
|
||
|
/* nth_composite_key_equal_to
|
||
|
* nth_composite_key_less
|
||
|
* nth_composite_key_greater
|
||
|
* nth_composite_key_hash
|
||
|
*/
|
||
|
|
||
|
BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(equal_to,std::equal_to)
|
||
|
BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(less,std::less)
|
||
|
BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(greater,std::greater)
|
||
|
BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(hash,boost::hash)
|
||
|
|
||
|
/* used for defining equality and comparison ops of composite_key_result */
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO(z,n,text) text
|
||
|
|
||
|
struct generic_operator_equal
|
||
|
{
|
||
|
template<typename T,typename Q>
|
||
|
bool operator()(const T& x,const Q& y)const{return x==y;}
|
||
|
};
|
||
|
|
||
|
typedef tuple<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(
|
||
|
BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
|
||
|
detail::generic_operator_equal)> generic_operator_equal_tuple;
|
||
|
|
||
|
struct generic_operator_less
|
||
|
{
|
||
|
template<typename T,typename Q>
|
||
|
bool operator()(const T& x,const Q& y)const{return x<y;}
|
||
|
};
|
||
|
|
||
|
typedef tuple<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(
|
||
|
BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
|
||
|
detail::generic_operator_less)> generic_operator_less_tuple;
|
||
|
|
||
|
/* Metaprogramming machinery for implementing equality, comparison and
|
||
|
* hashing operations of composite_key_result.
|
||
|
*
|
||
|
* equal_* checks for equality between composite_key_results and
|
||
|
* between those and tuples, accepting a tuple of basic equality functors.
|
||
|
* compare_* does lexicographical comparison.
|
||
|
* hash_* computes a combination of elementwise hash values.
|
||
|
*/
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons1,typename Value1,
|
||
|
typename KeyCons2, typename Value2,
|
||
|
typename EqualCons
|
||
|
>
|
||
|
struct equal_ckey_ckey; /* fwd decl. */
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons1,typename Value1,
|
||
|
typename KeyCons2, typename Value2,
|
||
|
typename EqualCons
|
||
|
>
|
||
|
struct equal_ckey_ckey_terminal
|
||
|
{
|
||
|
static bool compare(
|
||
|
const KeyCons1&,const Value1&,
|
||
|
const KeyCons2&,const Value2&,
|
||
|
const EqualCons&)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons1,typename Value1,
|
||
|
typename KeyCons2, typename Value2,
|
||
|
typename EqualCons
|
||
|
>
|
||
|
struct equal_ckey_ckey_normal
|
||
|
{
|
||
|
static bool compare(
|
||
|
const KeyCons1& c0,const Value1& v0,
|
||
|
const KeyCons2& c1,const Value2& v1,
|
||
|
const EqualCons& eq)
|
||
|
{
|
||
|
if(!eq.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return false;
|
||
|
return equal_ckey_ckey<
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
|
||
|
BOOST_DEDUCED_TYPENAME EqualCons::tail_type
|
||
|
>::compare(c0.get_tail(),v0,c1.get_tail(),v1,eq.get_tail());
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons1,typename Value1,
|
||
|
typename KeyCons2, typename Value2,
|
||
|
typename EqualCons
|
||
|
>
|
||
|
struct equal_ckey_ckey:
|
||
|
mpl::if_<
|
||
|
mpl::or_<
|
||
|
is_same<KeyCons1,tuples::null_type>,
|
||
|
is_same<KeyCons2,tuples::null_type>
|
||
|
>,
|
||
|
equal_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>,
|
||
|
equal_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>
|
||
|
>::type
|
||
|
{
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons,typename Value,
|
||
|
typename ValCons,typename EqualCons
|
||
|
>
|
||
|
struct equal_ckey_cval; /* fwd decl. */
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons,typename Value,
|
||
|
typename ValCons,typename EqualCons
|
||
|
>
|
||
|
struct equal_ckey_cval_terminal
|
||
|
{
|
||
|
static bool compare(
|
||
|
const KeyCons&,const Value&,const ValCons&,const EqualCons&)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool compare(
|
||
|
const ValCons&,const KeyCons&,const Value&,const EqualCons&)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons,typename Value,
|
||
|
typename ValCons,typename EqualCons
|
||
|
>
|
||
|
struct equal_ckey_cval_normal
|
||
|
{
|
||
|
static bool compare(
|
||
|
const KeyCons& c,const Value& v,const ValCons& vc,
|
||
|
const EqualCons& eq)
|
||
|
{
|
||
|
if(!eq.get_head()(c.get_head()(v),vc.get_head()))return false;
|
||
|
return equal_ckey_cval<
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
|
||
|
BOOST_DEDUCED_TYPENAME ValCons::tail_type,
|
||
|
BOOST_DEDUCED_TYPENAME EqualCons::tail_type
|
||
|
>::compare(c.get_tail(),v,vc.get_tail(),eq.get_tail());
|
||
|
}
|
||
|
|
||
|
static bool compare(
|
||
|
const ValCons& vc,const KeyCons& c,const Value& v,
|
||
|
const EqualCons& eq)
|
||
|
{
|
||
|
if(!eq.get_head()(vc.get_head(),c.get_head()(v)))return false;
|
||
|
return equal_ckey_cval<
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
|
||
|
BOOST_DEDUCED_TYPENAME ValCons::tail_type,
|
||
|
BOOST_DEDUCED_TYPENAME EqualCons::tail_type
|
||
|
>::compare(vc.get_tail(),c.get_tail(),v,eq.get_tail());
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons,typename Value,
|
||
|
typename ValCons,typename EqualCons
|
||
|
>
|
||
|
struct equal_ckey_cval:
|
||
|
mpl::if_<
|
||
|
mpl::or_<
|
||
|
is_same<KeyCons,tuples::null_type>,
|
||
|
is_same<ValCons,tuples::null_type>
|
||
|
>,
|
||
|
equal_ckey_cval_terminal<KeyCons,Value,ValCons,EqualCons>,
|
||
|
equal_ckey_cval_normal<KeyCons,Value,ValCons,EqualCons>
|
||
|
>::type
|
||
|
{
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons1,typename Value1,
|
||
|
typename KeyCons2, typename Value2,
|
||
|
typename CompareCons
|
||
|
>
|
||
|
struct compare_ckey_ckey; /* fwd decl. */
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons1,typename Value1,
|
||
|
typename KeyCons2, typename Value2,
|
||
|
typename CompareCons
|
||
|
>
|
||
|
struct compare_ckey_ckey_terminal
|
||
|
{
|
||
|
static bool compare(
|
||
|
const KeyCons1&,const Value1&,
|
||
|
const KeyCons2&,const Value2&,
|
||
|
const CompareCons&)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons1,typename Value1,
|
||
|
typename KeyCons2, typename Value2,
|
||
|
typename CompareCons
|
||
|
>
|
||
|
struct compare_ckey_ckey_normal
|
||
|
{
|
||
|
static bool compare(
|
||
|
const KeyCons1& c0,const Value1& v0,
|
||
|
const KeyCons2& c1,const Value2& v1,
|
||
|
const CompareCons& comp)
|
||
|
{
|
||
|
if(comp.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return true;
|
||
|
if(comp.get_head()(c1.get_head()(v1),c0.get_head()(v0)))return false;
|
||
|
return compare_ckey_ckey<
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
|
||
|
BOOST_DEDUCED_TYPENAME CompareCons::tail_type
|
||
|
>::compare(c0.get_tail(),v0,c1.get_tail(),v1,comp.get_tail());
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons1,typename Value1,
|
||
|
typename KeyCons2, typename Value2,
|
||
|
typename CompareCons
|
||
|
>
|
||
|
struct compare_ckey_ckey:
|
||
|
mpl::if_<
|
||
|
mpl::or_<
|
||
|
is_same<KeyCons1,tuples::null_type>,
|
||
|
is_same<KeyCons2,tuples::null_type>
|
||
|
>,
|
||
|
compare_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>,
|
||
|
compare_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>
|
||
|
>::type
|
||
|
{
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons,typename Value,
|
||
|
typename ValCons,typename CompareCons
|
||
|
>
|
||
|
struct compare_ckey_cval; /* fwd decl. */
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons,typename Value,
|
||
|
typename ValCons,typename CompareCons
|
||
|
>
|
||
|
struct compare_ckey_cval_terminal
|
||
|
{
|
||
|
static bool compare(
|
||
|
const KeyCons&,const Value&,const ValCons&,const CompareCons&)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static bool compare(
|
||
|
const ValCons&,const KeyCons&,const Value&,const CompareCons&)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons,typename Value,
|
||
|
typename ValCons,typename CompareCons
|
||
|
>
|
||
|
struct compare_ckey_cval_normal
|
||
|
{
|
||
|
static bool compare(
|
||
|
const KeyCons& c,const Value& v,const ValCons& vc,
|
||
|
const CompareCons& comp)
|
||
|
{
|
||
|
if(comp.get_head()(c.get_head()(v),vc.get_head()))return true;
|
||
|
if(comp.get_head()(vc.get_head(),c.get_head()(v)))return false;
|
||
|
return compare_ckey_cval<
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
|
||
|
BOOST_DEDUCED_TYPENAME ValCons::tail_type,
|
||
|
BOOST_DEDUCED_TYPENAME CompareCons::tail_type
|
||
|
>::compare(c.get_tail(),v,vc.get_tail(),comp.get_tail());
|
||
|
}
|
||
|
|
||
|
static bool compare(
|
||
|
const ValCons& vc,const KeyCons& c,const Value& v,
|
||
|
const CompareCons& comp)
|
||
|
{
|
||
|
if(comp.get_head()(vc.get_head(),c.get_head()(v)))return true;
|
||
|
if(comp.get_head()(c.get_head()(v),vc.get_head()))return false;
|
||
|
return compare_ckey_cval<
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
|
||
|
BOOST_DEDUCED_TYPENAME ValCons::tail_type,
|
||
|
BOOST_DEDUCED_TYPENAME CompareCons::tail_type
|
||
|
>::compare(vc.get_tail(),c.get_tail(),v,comp.get_tail());
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename KeyCons,typename Value,
|
||
|
typename ValCons,typename CompareCons
|
||
|
>
|
||
|
struct compare_ckey_cval:
|
||
|
mpl::if_<
|
||
|
mpl::or_<
|
||
|
is_same<KeyCons,tuples::null_type>,
|
||
|
is_same<ValCons,tuples::null_type>
|
||
|
>,
|
||
|
compare_ckey_cval_terminal<KeyCons,Value,ValCons,CompareCons>,
|
||
|
compare_ckey_cval_normal<KeyCons,Value,ValCons,CompareCons>
|
||
|
>::type
|
||
|
{
|
||
|
};
|
||
|
|
||
|
template<typename KeyCons,typename Value,typename HashCons>
|
||
|
struct hash_ckey; /* fwd decl. */
|
||
|
|
||
|
template<typename KeyCons,typename Value,typename HashCons>
|
||
|
struct hash_ckey_terminal
|
||
|
{
|
||
|
static std::size_t hash(
|
||
|
const KeyCons&,const Value&,const HashCons&,std::size_t carry)
|
||
|
{
|
||
|
return carry;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename KeyCons,typename Value,typename HashCons>
|
||
|
struct hash_ckey_normal
|
||
|
{
|
||
|
static std::size_t hash(
|
||
|
const KeyCons& c,const Value& v,const HashCons& h,std::size_t carry=0)
|
||
|
{
|
||
|
/* same hashing formula as boost::hash_combine */
|
||
|
|
||
|
carry^=h.get_head()(c.get_head()(v))+0x9e3779b9+(carry<<6)+(carry>>2);
|
||
|
return hash_ckey<
|
||
|
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
|
||
|
BOOST_DEDUCED_TYPENAME HashCons::tail_type
|
||
|
>::hash(c.get_tail(),v,h.get_tail(),carry);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename KeyCons,typename Value,typename HashCons>
|
||
|
struct hash_ckey:
|
||
|
mpl::if_<
|
||
|
is_same<KeyCons,tuples::null_type>,
|
||
|
hash_ckey_terminal<KeyCons,Value,HashCons>,
|
||
|
hash_ckey_normal<KeyCons,Value,HashCons>
|
||
|
>::type
|
||
|
{
|
||
|
};
|
||
|
|
||
|
template<typename ValCons,typename HashCons>
|
||
|
struct hash_cval; /* fwd decl. */
|
||
|
|
||
|
template<typename ValCons,typename HashCons>
|
||
|
struct hash_cval_terminal
|
||
|
{
|
||
|
static std::size_t hash(const ValCons&,const HashCons&,std::size_t carry)
|
||
|
{
|
||
|
return carry;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename ValCons,typename HashCons>
|
||
|
struct hash_cval_normal
|
||
|
{
|
||
|
static std::size_t hash(
|
||
|
const ValCons& vc,const HashCons& h,std::size_t carry=0)
|
||
|
{
|
||
|
carry^=h.get_head()(vc.get_head())+0x9e3779b9+(carry<<6)+(carry>>2);
|
||
|
return hash_cval<
|
||
|
BOOST_DEDUCED_TYPENAME ValCons::tail_type,
|
||
|
BOOST_DEDUCED_TYPENAME HashCons::tail_type
|
||
|
>::hash(vc.get_tail(),h.get_tail(),carry);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename ValCons,typename HashCons>
|
||
|
struct hash_cval:
|
||
|
mpl::if_<
|
||
|
is_same<ValCons,tuples::null_type>,
|
||
|
hash_cval_terminal<ValCons,HashCons>,
|
||
|
hash_cval_normal<ValCons,HashCons>
|
||
|
>::type
|
||
|
{
|
||
|
};
|
||
|
|
||
|
} /* namespace multi_index::detail */
|
||
|
|
||
|
/* composite_key_result */
|
||
|
|
||
|
#if defined(BOOST_MSVC)
|
||
|
#pragma warning(push)
|
||
|
#pragma warning(disable:4512)
|
||
|
#endif
|
||
|
|
||
|
template<typename CompositeKey>
|
||
|
struct composite_key_result
|
||
|
{
|
||
|
typedef CompositeKey composite_key_type;
|
||
|
typedef typename composite_key_type::value_type value_type;
|
||
|
|
||
|
composite_key_result(
|
||
|
const composite_key_type& composite_key_,const value_type& value_):
|
||
|
composite_key(composite_key_),value(value_)
|
||
|
{}
|
||
|
|
||
|
const composite_key_type& composite_key;
|
||
|
const value_type& value;
|
||
|
};
|
||
|
|
||
|
#if defined(BOOST_MSVC)
|
||
|
#pragma warning(pop)
|
||
|
#endif
|
||
|
|
||
|
/* composite_key */
|
||
|
|
||
|
/* NB. Some overloads of operator() have an extra dummy parameter int=0.
|
||
|
* This disambiguator serves several purposes:
|
||
|
* - Without it, MSVC++ 6.0 incorrectly regards some overloads as
|
||
|
* specializations of a previous member function template.
|
||
|
* - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
|
||
|
* as if they have the same signature.
|
||
|
* - If remove_const is broken due to lack of PTS, int=0 avoids the
|
||
|
* declaration of memfuns with identical signature.
|
||
|
*/
|
||
|
|
||
|
template<
|
||
|
typename Value,
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,KeyFromValue)
|
||
|
>
|
||
|
struct composite_key:
|
||
|
private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)>
|
||
|
{
|
||
|
private:
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)> super;
|
||
|
|
||
|
public:
|
||
|
typedef super key_extractor_tuple;
|
||
|
typedef Value value_type;
|
||
|
typedef composite_key_result<composite_key> result_type;
|
||
|
|
||
|
composite_key(
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,KeyFromValue)):
|
||
|
super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
|
||
|
{}
|
||
|
|
||
|
composite_key(const key_extractor_tuple& x):super(x){}
|
||
|
|
||
|
const key_extractor_tuple& key_extractors()const{return *this;}
|
||
|
key_extractor_tuple& key_extractors(){return *this;}
|
||
|
|
||
|
template<typename ChainedPtr>
|
||
|
|
||
|
#if !defined(BOOST_NO_SFINAE)
|
||
|
typename disable_if<
|
||
|
is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
|
||
|
#else
|
||
|
result_type
|
||
|
#endif
|
||
|
|
||
|
operator()(const ChainedPtr& x)const
|
||
|
{
|
||
|
return operator()(*x);
|
||
|
}
|
||
|
|
||
|
result_type operator()(const value_type& x)const
|
||
|
{
|
||
|
return result_type(*this,x);
|
||
|
}
|
||
|
|
||
|
result_type operator()(const reference_wrapper<const value_type>& x)const
|
||
|
{
|
||
|
return result_type(*this,x.get());
|
||
|
}
|
||
|
|
||
|
result_type operator()(const reference_wrapper<value_type>& x,int=0)const
|
||
|
{
|
||
|
return result_type(*this,x.get());
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/* comparison operators */
|
||
|
|
||
|
/* == */
|
||
|
|
||
|
template<typename CompositeKey1,typename CompositeKey2>
|
||
|
inline bool operator==(
|
||
|
const composite_key_result<CompositeKey1>& x,
|
||
|
const composite_key_result<CompositeKey2>& y)
|
||
|
{
|
||
|
typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
|
||
|
typedef typename CompositeKey1::value_type value_type1;
|
||
|
typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
|
||
|
typedef typename CompositeKey2::value_type value_type2;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_extractor_tuple1>::value==
|
||
|
tuples::length<key_extractor_tuple2>::value);
|
||
|
|
||
|
return detail::equal_ckey_ckey<
|
||
|
key_extractor_tuple1,value_type1,
|
||
|
key_extractor_tuple2,value_type2,
|
||
|
detail::generic_operator_equal_tuple
|
||
|
>::compare(
|
||
|
x.composite_key.key_extractors(),x.value,
|
||
|
y.composite_key.key_extractors(),y.value,
|
||
|
detail::generic_operator_equal_tuple());
|
||
|
}
|
||
|
|
||
|
template<
|
||
|
typename CompositeKey,
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
|
||
|
>
|
||
|
inline bool operator==(
|
||
|
const composite_key_result<CompositeKey>& x,
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_extractor_tuple>::value==
|
||
|
tuples::length<key_tuple>::value);
|
||
|
|
||
|
return detail::equal_ckey_cval<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_tuple,detail::generic_operator_equal_tuple
|
||
|
>::compare(
|
||
|
x.composite_key.key_extractors(),x.value,
|
||
|
y,detail::generic_operator_equal_tuple());
|
||
|
}
|
||
|
|
||
|
template
|
||
|
<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
|
||
|
typename CompositeKey
|
||
|
>
|
||
|
inline bool operator==(
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
|
||
|
const composite_key_result<CompositeKey>& y)
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_extractor_tuple>::value==
|
||
|
tuples::length<key_tuple>::value);
|
||
|
|
||
|
return detail::equal_ckey_cval<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_tuple,detail::generic_operator_equal_tuple
|
||
|
>::compare(
|
||
|
x,y.composite_key.key_extractors(),
|
||
|
y.value,detail::generic_operator_equal_tuple());
|
||
|
}
|
||
|
|
||
|
/* < */
|
||
|
|
||
|
template<typename CompositeKey1,typename CompositeKey2>
|
||
|
inline bool operator<(
|
||
|
const composite_key_result<CompositeKey1>& x,
|
||
|
const composite_key_result<CompositeKey2>& y)
|
||
|
{
|
||
|
typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
|
||
|
typedef typename CompositeKey1::value_type value_type1;
|
||
|
typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
|
||
|
typedef typename CompositeKey2::value_type value_type2;
|
||
|
|
||
|
return detail::compare_ckey_ckey<
|
||
|
key_extractor_tuple1,value_type1,
|
||
|
key_extractor_tuple2,value_type2,
|
||
|
detail::generic_operator_less_tuple
|
||
|
>::compare(
|
||
|
x.composite_key.key_extractors(),x.value,
|
||
|
y.composite_key.key_extractors(),y.value,
|
||
|
detail::generic_operator_less_tuple());
|
||
|
}
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename CompositeKey,
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
|
||
|
>
|
||
|
inline bool operator<(
|
||
|
const composite_key_result<CompositeKey>& x,
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
return detail::compare_ckey_cval<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_tuple,detail::generic_operator_less_tuple
|
||
|
>::compare(
|
||
|
x.composite_key.key_extractors(),x.value,
|
||
|
y,detail::generic_operator_less_tuple());
|
||
|
}
|
||
|
|
||
|
template
|
||
|
<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
|
||
|
typename CompositeKey
|
||
|
>
|
||
|
inline bool operator<(
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
|
||
|
const composite_key_result<CompositeKey>& y)
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
return detail::compare_ckey_cval<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_tuple,detail::generic_operator_less_tuple
|
||
|
>::compare(
|
||
|
x,y.composite_key.key_extractors(),
|
||
|
y.value,detail::generic_operator_less_tuple());
|
||
|
}
|
||
|
|
||
|
/* rest of comparison operators */
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2) \
|
||
|
template<t1,t2> inline bool operator!=(const a1& x,const a2& y) \
|
||
|
{ \
|
||
|
return !(x==y); \
|
||
|
} \
|
||
|
\
|
||
|
template<t1,t2> inline bool operator>(const a1& x,const a2& y) \
|
||
|
{ \
|
||
|
return y<x; \
|
||
|
} \
|
||
|
\
|
||
|
template<t1,t2> inline bool operator>=(const a1& x,const a2& y) \
|
||
|
{ \
|
||
|
return !(x<y); \
|
||
|
} \
|
||
|
\
|
||
|
template<t1,t2> inline bool operator<=(const a1& x,const a2& y) \
|
||
|
{ \
|
||
|
return !(y<x); \
|
||
|
}
|
||
|
|
||
|
BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
|
||
|
typename CompositeKey1,
|
||
|
typename CompositeKey2,
|
||
|
composite_key_result<CompositeKey1>,
|
||
|
composite_key_result<CompositeKey2>
|
||
|
)
|
||
|
|
||
|
BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
|
||
|
typename CompositeKey,
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
|
||
|
composite_key_result<CompositeKey>,
|
||
|
tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>
|
||
|
)
|
||
|
|
||
|
BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
|
||
|
typename CompositeKey,
|
||
|
tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>,
|
||
|
composite_key_result<CompositeKey>
|
||
|
)
|
||
|
|
||
|
/* composite_key_equal_to */
|
||
|
|
||
|
template
|
||
|
<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Pred)
|
||
|
>
|
||
|
struct composite_key_equal_to:
|
||
|
private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)>
|
||
|
{
|
||
|
private:
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)> super;
|
||
|
|
||
|
public:
|
||
|
typedef super key_eq_tuple;
|
||
|
|
||
|
composite_key_equal_to(
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Pred)):
|
||
|
super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
|
||
|
{}
|
||
|
|
||
|
composite_key_equal_to(const key_eq_tuple& x):super(x){}
|
||
|
|
||
|
const key_eq_tuple& key_eqs()const{return *this;}
|
||
|
key_eq_tuple& key_eqs(){return *this;}
|
||
|
|
||
|
template<typename CompositeKey1,typename CompositeKey2>
|
||
|
bool operator()(
|
||
|
const composite_key_result<CompositeKey1> & x,
|
||
|
const composite_key_result<CompositeKey2> & y)const
|
||
|
{
|
||
|
typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
|
||
|
typedef typename CompositeKey1::value_type value_type1;
|
||
|
typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
|
||
|
typedef typename CompositeKey2::value_type value_type2;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_extractor_tuple1>::value<=
|
||
|
tuples::length<key_eq_tuple>::value&&
|
||
|
tuples::length<key_extractor_tuple1>::value==
|
||
|
tuples::length<key_extractor_tuple2>::value);
|
||
|
|
||
|
return detail::equal_ckey_ckey<
|
||
|
key_extractor_tuple1,value_type1,
|
||
|
key_extractor_tuple2,value_type2,
|
||
|
key_eq_tuple
|
||
|
>::compare(
|
||
|
x.composite_key.key_extractors(),x.value,
|
||
|
y.composite_key.key_extractors(),y.value,
|
||
|
key_eqs());
|
||
|
}
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename CompositeKey,
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
|
||
|
>
|
||
|
bool operator()(
|
||
|
const composite_key_result<CompositeKey>& x,
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_extractor_tuple>::value<=
|
||
|
tuples::length<key_eq_tuple>::value&&
|
||
|
tuples::length<key_extractor_tuple>::value==
|
||
|
tuples::length<key_tuple>::value);
|
||
|
|
||
|
return detail::equal_ckey_cval<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_tuple,key_eq_tuple
|
||
|
>::compare(x.composite_key.key_extractors(),x.value,y,key_eqs());
|
||
|
}
|
||
|
|
||
|
template
|
||
|
<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
|
||
|
typename CompositeKey
|
||
|
>
|
||
|
bool operator()(
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
|
||
|
const composite_key_result<CompositeKey>& y)const
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_tuple>::value<=
|
||
|
tuples::length<key_eq_tuple>::value&&
|
||
|
tuples::length<key_tuple>::value==
|
||
|
tuples::length<key_extractor_tuple>::value);
|
||
|
|
||
|
return detail::equal_ckey_cval<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_tuple,key_eq_tuple
|
||
|
>::compare(x,y.composite_key.key_extractors(),y.value,key_eqs());
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/* composite_key_compare */
|
||
|
|
||
|
template
|
||
|
<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Compare)
|
||
|
>
|
||
|
struct composite_key_compare:
|
||
|
private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)>
|
||
|
{
|
||
|
private:
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)> super;
|
||
|
|
||
|
public:
|
||
|
typedef super key_comp_tuple;
|
||
|
|
||
|
composite_key_compare(
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Compare)):
|
||
|
super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
|
||
|
{}
|
||
|
|
||
|
composite_key_compare(const key_comp_tuple& x):super(x){}
|
||
|
|
||
|
const key_comp_tuple& key_comps()const{return *this;}
|
||
|
key_comp_tuple& key_comps(){return *this;}
|
||
|
|
||
|
template<typename CompositeKey1,typename CompositeKey2>
|
||
|
bool operator()(
|
||
|
const composite_key_result<CompositeKey1> & x,
|
||
|
const composite_key_result<CompositeKey2> & y)const
|
||
|
{
|
||
|
typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
|
||
|
typedef typename CompositeKey1::value_type value_type1;
|
||
|
typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
|
||
|
typedef typename CompositeKey2::value_type value_type2;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_extractor_tuple1>::value<=
|
||
|
tuples::length<key_comp_tuple>::value||
|
||
|
tuples::length<key_extractor_tuple2>::value<=
|
||
|
tuples::length<key_comp_tuple>::value);
|
||
|
|
||
|
return detail::compare_ckey_ckey<
|
||
|
key_extractor_tuple1,value_type1,
|
||
|
key_extractor_tuple2,value_type2,
|
||
|
key_comp_tuple
|
||
|
>::compare(
|
||
|
x.composite_key.key_extractors(),x.value,
|
||
|
y.composite_key.key_extractors(),y.value,
|
||
|
key_comps());
|
||
|
}
|
||
|
|
||
|
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||
|
template<typename CompositeKey,typename Value>
|
||
|
bool operator()(
|
||
|
const composite_key_result<CompositeKey>& x,
|
||
|
const Value& y)const
|
||
|
{
|
||
|
return operator()(x,boost::make_tuple(boost::cref(y)));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
template
|
||
|
<
|
||
|
typename CompositeKey,
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
|
||
|
>
|
||
|
bool operator()(
|
||
|
const composite_key_result<CompositeKey>& x,
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_extractor_tuple>::value<=
|
||
|
tuples::length<key_comp_tuple>::value||
|
||
|
tuples::length<key_tuple>::value<=
|
||
|
tuples::length<key_comp_tuple>::value);
|
||
|
|
||
|
return detail::compare_ckey_cval<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_tuple,key_comp_tuple
|
||
|
>::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
|
||
|
}
|
||
|
|
||
|
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||
|
template<typename Value,typename CompositeKey>
|
||
|
bool operator()(
|
||
|
const Value& x,
|
||
|
const composite_key_result<CompositeKey>& y)const
|
||
|
{
|
||
|
return operator()(boost::make_tuple(boost::cref(x)),y);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
template
|
||
|
<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
|
||
|
typename CompositeKey
|
||
|
>
|
||
|
bool operator()(
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
|
||
|
const composite_key_result<CompositeKey>& y)const
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_tuple>::value<=
|
||
|
tuples::length<key_comp_tuple>::value||
|
||
|
tuples::length<key_extractor_tuple>::value<=
|
||
|
tuples::length<key_comp_tuple>::value);
|
||
|
|
||
|
return detail::compare_ckey_cval<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_tuple,key_comp_tuple
|
||
|
>::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/* composite_key_hash */
|
||
|
|
||
|
template
|
||
|
<
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Hash)
|
||
|
>
|
||
|
struct composite_key_hash:
|
||
|
private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)>
|
||
|
{
|
||
|
private:
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)> super;
|
||
|
|
||
|
public:
|
||
|
typedef super key_hasher_tuple;
|
||
|
|
||
|
composite_key_hash(
|
||
|
BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Hash)):
|
||
|
super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
|
||
|
{}
|
||
|
|
||
|
composite_key_hash(const key_hasher_tuple& x):super(x){}
|
||
|
|
||
|
const key_hasher_tuple& key_hash_functions()const{return *this;}
|
||
|
key_hasher_tuple& key_hash_functions(){return *this;}
|
||
|
|
||
|
template<typename CompositeKey>
|
||
|
std::size_t operator()(const composite_key_result<CompositeKey> & x)const
|
||
|
{
|
||
|
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
|
||
|
typedef typename CompositeKey::value_type value_type;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_extractor_tuple>::value==
|
||
|
tuples::length<key_hasher_tuple>::value);
|
||
|
|
||
|
return detail::hash_ckey<
|
||
|
key_extractor_tuple,value_type,
|
||
|
key_hasher_tuple
|
||
|
>::hash(x.composite_key.key_extractors(),x.value,key_hash_functions());
|
||
|
}
|
||
|
|
||
|
template<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)>
|
||
|
std::size_t operator()(
|
||
|
const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x)const
|
||
|
{
|
||
|
typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
|
||
|
|
||
|
BOOST_STATIC_ASSERT(
|
||
|
tuples::length<key_tuple>::value==
|
||
|
tuples::length<key_hasher_tuple>::value);
|
||
|
|
||
|
return detail::hash_cval<
|
||
|
key_tuple,key_hasher_tuple
|
||
|
>::hash(x,key_hash_functions());
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/* Instantiations of the former functors with "natural" basic components:
|
||
|
* composite_key_result_equal_to uses std::equal_to of the values.
|
||
|
* composite_key_result_less uses std::less.
|
||
|
* composite_key_result_greater uses std::greater.
|
||
|
* composite_key_result_hash uses boost::hash.
|
||
|
*/
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER \
|
||
|
composite_key_equal_to< \
|
||
|
BOOST_MULTI_INDEX_CK_ENUM( \
|
||
|
BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
|
||
|
/* the argument is a PP list */ \
|
||
|
(detail::nth_composite_key_equal_to, \
|
||
|
(BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
|
||
|
BOOST_PP_NIL))) \
|
||
|
>
|
||
|
|
||
|
template<typename CompositeKeyResult>
|
||
|
struct composite_key_result_equal_to:
|
||
|
BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
|
||
|
BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
|
||
|
{
|
||
|
private:
|
||
|
typedef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER super;
|
||
|
|
||
|
public:
|
||
|
typedef CompositeKeyResult first_argument_type;
|
||
|
typedef first_argument_type second_argument_type;
|
||
|
typedef bool result_type;
|
||
|
|
||
|
using super::operator();
|
||
|
};
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER \
|
||
|
composite_key_compare< \
|
||
|
BOOST_MULTI_INDEX_CK_ENUM( \
|
||
|
BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
|
||
|
/* the argument is a PP list */ \
|
||
|
(detail::nth_composite_key_less, \
|
||
|
(BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
|
||
|
BOOST_PP_NIL))) \
|
||
|
>
|
||
|
|
||
|
template<typename CompositeKeyResult>
|
||
|
struct composite_key_result_less:
|
||
|
BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
|
||
|
BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
|
||
|
{
|
||
|
private:
|
||
|
typedef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER super;
|
||
|
|
||
|
public:
|
||
|
typedef CompositeKeyResult first_argument_type;
|
||
|
typedef first_argument_type second_argument_type;
|
||
|
typedef bool result_type;
|
||
|
|
||
|
using super::operator();
|
||
|
};
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER \
|
||
|
composite_key_compare< \
|
||
|
BOOST_MULTI_INDEX_CK_ENUM( \
|
||
|
BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
|
||
|
/* the argument is a PP list */ \
|
||
|
(detail::nth_composite_key_greater, \
|
||
|
(BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
|
||
|
BOOST_PP_NIL))) \
|
||
|
>
|
||
|
|
||
|
template<typename CompositeKeyResult>
|
||
|
struct composite_key_result_greater:
|
||
|
BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
|
||
|
BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
|
||
|
{
|
||
|
private:
|
||
|
typedef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER super;
|
||
|
|
||
|
public:
|
||
|
typedef CompositeKeyResult first_argument_type;
|
||
|
typedef first_argument_type second_argument_type;
|
||
|
typedef bool result_type;
|
||
|
|
||
|
using super::operator();
|
||
|
};
|
||
|
|
||
|
#define BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER \
|
||
|
composite_key_hash< \
|
||
|
BOOST_MULTI_INDEX_CK_ENUM( \
|
||
|
BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
|
||
|
/* the argument is a PP list */ \
|
||
|
(detail::nth_composite_key_hash, \
|
||
|
(BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
|
||
|
BOOST_PP_NIL))) \
|
||
|
>
|
||
|
|
||
|
template<typename CompositeKeyResult>
|
||
|
struct composite_key_result_hash:
|
||
|
BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
|
||
|
BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
|
||
|
{
|
||
|
private:
|
||
|
typedef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER super;
|
||
|
|
||
|
public:
|
||
|
typedef CompositeKeyResult argument_type;
|
||
|
typedef std::size_t result_type;
|
||
|
|
||
|
using super::operator();
|
||
|
};
|
||
|
|
||
|
} /* namespace multi_index */
|
||
|
|
||
|
} /* namespace boost */
|
||
|
|
||
|
/* Specializations of std::equal_to, std::less, std::greater and boost::hash
|
||
|
* for composite_key_results enabling interoperation with tuples of values.
|
||
|
*/
|
||
|
|
||
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||
|
namespace std{
|
||
|
|
||
|
template<typename CompositeKey>
|
||
|
struct equal_to<boost::multi_index::composite_key_result<CompositeKey> >:
|
||
|
boost::multi_index::composite_key_result_equal_to<
|
||
|
boost::multi_index::composite_key_result<CompositeKey>
|
||
|
>
|
||
|
{
|
||
|
};
|
||
|
|
||
|
template<typename CompositeKey>
|
||
|
struct less<boost::multi_index::composite_key_result<CompositeKey> >:
|
||
|
boost::multi_index::composite_key_result_less<
|
||
|
boost::multi_index::composite_key_result<CompositeKey>
|
||
|
>
|
||
|
{
|
||
|
};
|
||
|
|
||
|
template<typename CompositeKey>
|
||
|
struct greater<boost::multi_index::composite_key_result<CompositeKey> >:
|
||
|
boost::multi_index::composite_key_result_greater<
|
||
|
boost::multi_index::composite_key_result<CompositeKey>
|
||
|
>
|
||
|
{
|
||
|
};
|
||
|
|
||
|
} /* namespace std */
|
||
|
|
||
|
namespace boost{
|
||
|
|
||
|
template<typename CompositeKey>
|
||
|
struct hash<boost::multi_index::composite_key_result<CompositeKey> >:
|
||
|
boost::multi_index::composite_key_result_hash<
|
||
|
boost::multi_index::composite_key_result<CompositeKey>
|
||
|
>
|
||
|
{
|
||
|
};
|
||
|
|
||
|
} /* namespace boost */
|
||
|
#else
|
||
|
/* Lacking template partial specialization, std::equal_to, std::less and
|
||
|
* std::greater will still work for composite_key_results although without
|
||
|
* tuple interoperability. To achieve the same graceful degrading with
|
||
|
* boost::hash, we define the appropriate hash_value overload.
|
||
|
*/
|
||
|
|
||
|
namespace boost{
|
||
|
|
||
|
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||
|
namespace multi_index{
|
||
|
#endif
|
||
|
|
||
|
template<typename CompositeKey>
|
||
|
inline std::size_t hash_value(
|
||
|
const boost::multi_index::composite_key_result<CompositeKey>& x)
|
||
|
{
|
||
|
boost::multi_index::composite_key_result_hash<
|
||
|
boost::multi_index::composite_key_result<CompositeKey> > h;
|
||
|
return h(x);
|
||
|
}
|
||
|
|
||
|
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||
|
} /* namespace multi_index */
|
||
|
#endif
|
||
|
|
||
|
} /* namespace boost */
|
||
|
#endif
|
||
|
|
||
|
#undef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
|
||
|
#undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
|
||
|
#undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
|
||
|
#undef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
|
||
|
#undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
|
||
|
#undef BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO
|
||
|
#undef BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR
|
||
|
#undef BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N
|
||
|
#undef BOOST_MULTI_INDEX_CK_CTOR_ARG
|
||
|
#undef BOOST_MULTI_INDEX_CK_TEMPLATE_PARM
|
||
|
#undef BOOST_MULTI_INDEX_CK_ENUM_PARAMS
|
||
|
#undef BOOST_MULTI_INDEX_CK_ENUM
|
||
|
#undef BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE
|
||
|
|
||
|
#endif
|