/* Copyright 2003-2008 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,make_tuple(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()(make_tuple(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 |