Compare commits

...

3 Commits

Author SHA1 Message Date
Hartmut Kaiser f0b6472499 Removed part of the Boost files from the SPIRIT_MINIBOOST branch.
[SVN r26368]
2004-11-30 07:52:25 +00:00
Hartmut Kaiser 4ee5a7e0e9 Removed part of the Boost files from the SPIRIT_MINIBOOST branch.
[SVN r26353]
2004-11-29 16:07:37 +00:00
nobody a657e1df3b This commit was manufactured by cvs2svn to create branch
'SPIRIT_MINIBOOST'.

[SVN r26343]
2004-11-29 07:29:20 +00:00
44 changed files with 0 additions and 7928 deletions
-959
View File
@@ -1,959 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#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 <functional>
/* 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 on comparison time.
* 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.
* composite_key_compare is overloaded to enable comparisons between
* composite_key_results and tuples of values. Comparison is done
* lexicographically on on the maximum common number of elements of the
* operands. This allows searching for incomplete keys
*/
/* 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.31, 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{
/* nth_composite_key_less<CompositeKey,N>:: yields std::less<result_type>
* where result_type is the result_type of the nth key extractor of
* CompositeKey. If N >= the length of CompositeKey, it yields
* tuples::null_type.
* Similar thing for nth_composite_key_greater.
*/
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;
};
template<typename KeyFromValue>
struct key_std_less
{
typedef std::less<typename KeyFromValue::result_type> type;
};
template<>
struct key_std_less<tuples::null_type>
{
typedef tuples::null_type type;
};
template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>
struct nth_composite_key_less
{
typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;
typedef typename key_std_less<key_from_value>::type type;
};
template<typename KeyFromValue>
struct key_std_greater
{
typedef std::greater<typename KeyFromValue::result_type> type;
};
template<>
struct key_std_greater<tuples::null_type>
{
typedef tuples::null_type type;
};
template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>
struct nth_composite_key_greater
{
typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;
typedef typename key_std_greater<key_from_value>::type type;
};
/* Metaprogramming machinery to compare composite_key_results between
* them and with tuples of values.
* equals_* computes equality of two tuple objects x,y with the same
* length, defined as
*
* xi==yi for all i in [0,...,min(length(x),length(y))).
*
* less_* accepts operands of different lenghts and computes the
* following less-than relation:
*
* !(xi<yi) && !(yi<xi) && xj<yj
* for all i in [0,j) and some j in [0,...,min(length(x),length(y)).
*
* compare_* computes the same algorithm than less_*, but taking a tuple
* of comparison predicates instead of operator<.
*/
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct equals_ckey_ckey; /* fwd decl. */
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct equals_ckey_ckey_terminal
{
static bool compare(
const KeyCons1&,const Value1&,
const KeyCons2&,const Value2&)
{
return true;
}
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct equals_ckey_ckey_normal
{
static bool compare(
const KeyCons1& c0,const Value1& v0,
const KeyCons2& c1,const Value2& v1)
{
if(!(c0.get_head()(v0)==c1.get_head()(v1)))return false;
return equals_ckey_ckey<
BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2
>::compare(c0.get_tail(),v0,c1.get_tail(),v1);
}
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct equals_ckey_ckey:
mpl::if_<
mpl::or_<
is_same<KeyCons1,tuples::null_type>,
is_same<KeyCons2,tuples::null_type>
>,
equals_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2>,
equals_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2>
>::type
{
};
template<typename KeyCons,typename Value,typename ValCons>
struct equals_ckey_cval; /* fwd decl. */
template<typename KeyCons,typename Value,typename ValCons>
struct equals_ckey_cval_terminal
{
static bool compare(const KeyCons&,const Value&,const ValCons&)
{
return true;
}
static bool compare(const ValCons&,const KeyCons&,const Value&)
{
return true;
}
};
template<typename KeyCons,typename Value,typename ValCons>
struct equals_ckey_cval_normal
{
static bool compare(const KeyCons& c,const Value& v,const ValCons& vc)
{
if(!(c.get_head()(v)==vc.get_head()))return false;
return equals_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type
>::compare(c.get_tail(),v,vc.get_tail());
}
static bool compare(const ValCons& vc,const KeyCons& c,const Value& v)
{
if(!(vc.get_head()==c.get_head()(v)))return false;
return equals_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type
>::compare(vc.get_tail(),c.get_tail(),v);
}
};
template<typename KeyCons,typename Value,typename ValCons>
struct equals_ckey_cval:
mpl::if_<
mpl::or_<
is_same<KeyCons,tuples::null_type>,
is_same<ValCons,tuples::null_type>
>,
equals_ckey_cval_terminal<KeyCons,Value,ValCons>,
equals_ckey_cval_normal<KeyCons,Value, ValCons>
>::type
{
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct less_ckey_ckey; /* fwd decl. */
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct less_ckey_ckey_terminal
{
static bool compare(
const KeyCons1&,const Value1&,const KeyCons2&,const Value2&)
{
return false;
}
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct less_ckey_ckey_normal
{
static bool compare(
const KeyCons1& c0,const Value1& v0,
const KeyCons2& c1,const Value2& v1)
{
if(c0.get_head()(v0)<c1.get_head()(v1))return true;
if(c1.get_head()(v1)<c0.get_head()(v0))return false;
return less_ckey_ckey<
BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2
>::compare(c0.get_tail(),v0,c1.get_tail(),v1);
}
};
template<typename KeyCons1,typename Value1,typename KeyCons2,typename Value2>
struct less_ckey_ckey:
mpl::if_<
mpl::or_<
is_same<KeyCons1,tuples::null_type>,
is_same<KeyCons2,tuples::null_type>
>,
less_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2>,
less_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2>
>::type
{
};
template<typename KeyCons,typename Value,typename ValCons>
struct less_ckey_cval; /* fwd decl. */
template<typename KeyCons,typename Value,typename ValCons>
struct less_ckey_cval_terminal
{
static bool compare(const KeyCons&,const Value&,const ValCons&)
{
return false;
}
static bool compare(const ValCons&,const KeyCons&,const Value&)
{
return false;
}
};
template<typename KeyCons,typename Value,typename ValCons>
struct less_ckey_cval_normal
{
static bool compare(const KeyCons& c,const Value& v,const ValCons& vc)
{
if(c.get_head()(v)<vc.get_head())return true;
if(vc.get_head()<c.get_head()(v))return false;
return less_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type
>::compare(c.get_tail(),v,vc.get_tail());
}
static bool compare(const ValCons& vc,const KeyCons& c,const Value& v)
{
if(vc.get_head()<c.get_head()(v))return true;
if(c.get_head()(v)<vc.get_head())return false;
return less_ckey_cval<
BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
BOOST_DEDUCED_TYPENAME ValCons::tail_type
>::compare(vc.get_tail(),c.get_tail(),v);
}
};
template<typename KeyCons,typename Value,typename ValCons>
struct less_ckey_cval:
mpl::if_<
mpl::or_<
is_same<KeyCons,tuples::null_type>,
is_same<ValCons,tuples::null_type>
>,
less_ckey_cval_terminal<KeyCons,Value,ValCons>,
less_ckey_cval_normal<KeyCons,Value,ValCons>
>::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
{
};
} /* namespace multi_index::detail */
/* composite_key_result */
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;
};
/* 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>
result_type 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::equals_ckey_ckey<
key_extractor_tuple1,value_type1,
key_extractor_tuple2,value_type2
>::compare(
x.composite_key.key_extractors(),x.value,
y.composite_key.key_extractors(),y.value);
}
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::equals_ckey_cval<key_extractor_tuple,value_type,key_tuple>::
compare(x.composite_key.key_extractors(),x.value,y);
}
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::equals_ckey_cval<key_extractor_tuple,value_type,key_tuple>::
compare(x,y.composite_key.key_extractors(),y.value);
}
/* < */
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::less_ckey_ckey<
key_extractor_tuple1,value_type1,
key_extractor_tuple2,value_type2
>::compare(
x.composite_key.key_extractors(),x.value,
y.composite_key.key_extractors(),y.value);
}
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::less_ckey_cval<key_extractor_tuple,value_type,key_tuple>::
compare(x.composite_key.key_extractors(),x.value,y);
}
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::less_ckey_cval<key_extractor_tuple,value_type,key_tuple>::
compare(x,y.composite_key.key_extractors(),y.value);
}
/* 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_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());
}
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());
}
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_compare_less is merely a composite_key_compare
* instantiation with the corresponding std::less<> comparison
* predicates for each key extractor. Useful as a substitute for
* std::less<CompositeKey::result_type> when the compiler does not
* support partial specialization.
* Same with composite_key_compare_greater.
*/
#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();
};
} /* namespace multi_index */
} /* namespace boost */
/* Specialization of std::less and std::greater for composite_key_results
* enabling comparison with tuples of values.
*/
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace std{
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 */
#endif
#undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
#undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
#undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
#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
@@ -1,55 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_ACCESS_SPECIFIER_HPP
#define BOOST_MULTI_INDEX_DETAIL_ACCESS_SPECIFIER_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
/* In those compilers that do not accept the member template friend syntax,
* some protected and private sections might need to be specified as
* public.
* As per a discussion on the Boost mailing list, and pending the
* resolution of whether BOOST_NO_MEMBER_TEMPLATE_FRIENDS should
* apply to MSVC 8.0, I act here as if it did. The relevant
* discussion can be found at:
* [boost] [config] seems like VC 8.0 needsBOOST_NO_MEMBER_TEMPLATE_FRIENDS
* http://lists.boost.org/MailArchives/boost/msg68369.php
*/
#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) ||\
defined(BOOST_MSVC)&&(BOOST_MSVC==1400)
#define BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS
#endif
#if defined(BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS)
#define BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS public
#define BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS public
#else
#define BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS protected
#define BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS private
#endif
/* GCC does not correctly support in-class using declarations for template
* functions. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9810
* MSVC 7.1/8.0 seem to have a similar problem, though the conditions in
* which the error happens are not that simple. I have yet to isolate this
* into a snippet suitable for bug reporting.
*/
#if BOOST_WORKAROUND(__GNUC__, <3)||\
BOOST_WORKAROUND(__GNUC__,==3)&&(__GNUC_MINOR__<4)||\
BOOST_WORKAROUND(BOOST_MSVC,==1310)||\
BOOST_WORKAROUND(BOOST_MSVC,==1400)
#define BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS public
#else
#define BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS private
#endif
#endif
@@ -1,65 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_AUTO_SPACE_HPP
#define BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_HPP
#include <boost/detail/allocator_utilities.hpp>
#include <boost/noncopyable.hpp>
#include <memory>
namespace boost{
namespace multi_index{
namespace detail{
/* auto_space provides uninitialized space suitably to store
* a given number of elements of a given type.
*/
/* NB: it is not clear whether using an allocator to handle
* zero-sized arrays of elements is conformant or not. GCC 3.3.1
* and prior fail here, other stdlibs handle the issue gracefully.
* To be on the safe side, the case n==0 is given special treatment.
* References:
* GCC Bugzilla, "standard allocator crashes when deallocating segment
* "of zero length", http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14176
* C++ Standard Library Defect Report List (Revision 28), issue 199
* "What does allocate(0) return?",
* http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#199
*/
template<typename T,typename Allocator=std::allocator<T> >
struct auto_space:private noncopyable
{
explicit auto_space(const Allocator& al=Allocator(),std::size_t n=1):
al_(al),n_(n),data_(n_?al_.allocate(n_):0)
{}
~auto_space()
{
if(n_)al_.deallocate(data_,n_);
}
T* data()const{return data_;}
private:
typename boost::detail::allocator::rebind_to<
Allocator,T>::type al_;
std::size_t n_;
T* data_;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,84 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_BASE_TYPE_HPP
#define BOOST_MULTI_INDEX_DETAIL_BASE_TYPE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#include <boost/mpl/bind.hpp>
#include <boost/mpl/reverse_iter_fold.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/multi_index/detail/header_holder.hpp>
#include <boost/multi_index/detail/index_base.hpp>
#include <boost/multi_index/detail/is_index_list.hpp>
#include <boost/multi_index/detail/msvc_index_specifier.hpp>
#include <boost/multi_index/ordered_index_fwd.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/static_assert.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* MPL machinery to construct a linear hierarchy of indices out of
* a index list.
*/
#if BOOST_WORKAROUND(BOOST_MSVC,<1310)
struct index_applier
{
template<typename IndexSpecifierIterator,typename Super>
struct apply:
msvc_index_specifier< mpl::deref<IndexSpecifierIterator>::type>::
template result_index_class<Super>
{
};
};
#else
struct index_applier
{
template<typename IndexSpecifierIterator,typename Super>
struct apply
{
typedef typename mpl::deref<IndexSpecifierIterator>::type index_specifier;
typedef typename index_specifier::
BOOST_NESTED_TEMPLATE index_class<Super>::type type;
};
};
#endif
template<typename Value,typename IndexSpecifierList,typename Allocator>
struct multi_index_base_type
{
BOOST_STATIC_ASSERT(detail::is_index_list<IndexSpecifierList>::value);
typedef typename prevent_eti<
multi_index_container<Value,IndexSpecifierList,Allocator>,
typename mpl::reverse_iter_fold<
IndexSpecifierList,
index_base<Value,IndexSpecifierList,Allocator>,
mpl::bind2<
index_applier,
mpl::_2,
mpl::_1
>
>::type
>::type type;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,48 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_CONVERTER_HPP
#define BOOST_MULTI_INDEX_DETAIL_CONVERTER_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* converter offers means to access indices of a given multi_index_container
* and for convertibilty between index iterators, so providing a
* localized access point for get() and project() functions.
*/
template<typename MultiIndexContainer,typename Index>
struct converter
{
static const Index& index(const MultiIndexContainer& x){return x;}
static Index& index(MultiIndexContainer& x){return x;}
static typename Index::const_iterator const_iterator(
const MultiIndexContainer& x,typename MultiIndexContainer::node_type* node)
{
return x.Index::make_iterator(node);
}
static typename Index::iterator iterator(
MultiIndexContainer& x,typename MultiIndexContainer::node_type* node)
{
return x.Index::make_iterator(node);
}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,129 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_COPY_MAP_HPP
#define BOOST_MULTI_INDEX_DETAIL_COPY_MAP_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
/* copy_map is used as an auxiliary structure during copy_() operations.
* When a container with n nodes is replicated, node_map holds the pairings
* between original and copied nodes, and provides a fast way to find a
* copied node from an original one.
* The semantics of the class are not simple, and no attempt has been made
* to enforce it: multi_index_container handles it right. On the other hand,
* the const interface, which is the one provided to index implementations,
* only allows for:
* - Enumeration of pairs of (original,copied) nodes (excluding the headers),
* - fast retrieval of copied nodes (including the headers.)
*/
template <typename Node>
struct copy_map_entry
{
copy_map_entry(Node* f,Node* s):first(f),second(s){}
Node* first;
Node* second;
bool operator<(const copy_map_entry<Node>& x)const
{
return std::less<Node*>()(first,x.first);
}
};
template <typename Node,typename Allocator>
class copy_map:private noncopyable
{
public:
typedef const copy_map_entry<Node>* const_iterator;
copy_map(
const Allocator& al,std::size_t size,Node* header_org,Node* header_cpy):
al_(al),size_(size),spc(al_,size_),n(0),
header_org_(header_org),header_cpy_(header_cpy),released(false)
{}
~copy_map()
{
if(!released){
for(std::size_t i=0;i<n;++i){
boost::detail::allocator::destroy(&spc.data()[i].second->value);
deallocate(spc.data()[i].second);
}
}
}
const_iterator begin()const{return spc.data();}
const_iterator end()const{return spc.data()+n;}
void clone(Node* node)
{
spc.data()[n].first=node;
spc.data()[n].second=al_.allocate(1);
BOOST_TRY{
boost::detail::allocator::construct(
&spc.data()[n].second->value,node->value);
}
BOOST_CATCH(...){
deallocate(spc.data()[n].second);
BOOST_RETHROW;
}
BOOST_CATCH_END
++n;
if(n==size_)std::sort(spc.data(),spc.data()+size_);
}
Node* find(Node* node)const
{
if(node==header_org_)return header_cpy_;
return std::lower_bound(
begin(),end(),copy_map_entry<Node>(node,0))->second;
}
void release()
{
released=true;
}
private:
typename boost::detail::allocator::rebind_to<
Allocator,Node>::type al_;
std::size_t size_;
auto_space<copy_map_entry<Node>,Allocator> spc;
std::size_t n;
Node* header_org_;
Node* header_cpy_;
bool released;
void deallocate(Node* node)
{
al_.deallocate(node,1);
}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,55 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_DEF_CTOR_TUPLE_CONS_HPP
#define BOOST_MULTI_INDEX_DETAIL_DEF_CTOR_TUPLE_CONS_HPP
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
/* In MSVC, tuples::cons is not default constructible. We provide a
* tiny wrapper around tuple::cons filling that hole.
*/
#include <boost/tuple/tuple.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename Cons>
struct default_constructible_tuple_cons:Cons
{
default_constructible_tuple_cons():
Cons(
Cons::head_type(),
static_cast<const Cons::tail_type&>(
default_constructible_tuple_cons<Cons::tail_type>()))
{}
default_constructible_tuple_cons(const Cons& cons):Cons(cons){}
};
template<>
struct default_constructible_tuple_cons<tuples::null_type>:tuples::null_type
{
default_constructible_tuple_cons(){}
default_constructible_tuple_cons(const tuples::null_type&){}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* BOOST_MSVC */
#endif
@@ -1,38 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_HAS_TAG_HPP
#define BOOST_MULTI_INDEX_DETAIL_HAS_TAG_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/contains.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* determines whether an index type has a given tag in its tag list */
template<typename Tag>
struct has_tag
{
template<typename Index>
struct apply:mpl::contains<BOOST_DEDUCED_TYPENAME Index::tag_list,Tag>
{
};
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,47 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_HEADER_HOLDER_HPP
#define BOOST_MULTI_INDEX_DETAIL_HEADER_HOLDER_HPP
#include <boost/noncopyable.hpp>
#include <boost/utility/base_from_member.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* An utility class derived from base_from_member used to hold
* a pointer to the header node. The base from member idiom is used
* because index classes, which are superclasses of multi_index_container,
* need this header in construction time.
* The allocation is made by the allocator of the multi_index_container
* class --hence, this allocator needs also be stored resorting
* to the base from member trick.
*/
template<typename NodeType,typename Final>
struct header_holder:base_from_member<NodeType*>,private noncopyable
{
header_holder():super(final().allocate_node()){}
~header_holder(){final().deallocate_node(super::member);}
private:
typedef base_from_member<NodeType*> super;
Final& final(){return *static_cast<Final*>(this);}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,138 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_INDEX_BASE_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_BASE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/call_traits.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/multi_index/detail/copy_map.hpp>
#include <boost/multi_index/detail/node_type.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/tuple/tuple.hpp>
#include <utility>
namespace boost{
namespace multi_index{
namespace detail{
/* The role of this class is threefold:
* - tops the linear hierarchy of indices.
* - terminates some cascading backbone function calls (insert_, etc.),
* - grants access to the backbone functions of the final
* multi_index_container class (for access restriction reasons, these
* cannot be called directly from the index classes.)
*/
template<typename Value,typename IndexSpecifierList,typename Allocator>
class index_base
{
protected:
typedef index_node_base<Value> node_type;
typedef typename multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type final_node_type;
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> final_type;
typedef tuples::null_type ctor_args_list;
typedef typename
boost::detail::allocator::rebind_to<
Allocator,
typename Allocator::value_type>::type final_allocator_type;
typedef mpl::vector0<> index_type_list;
typedef mpl::vector0<> iterator_type_list;
typedef mpl::vector0<> const_iterator_type_list;
typedef copy_map<
final_node_type,
final_allocator_type> copy_map_type;
private:
typedef typename call_traits<Value>::param_type value_param_type;
protected:
explicit index_base(const ctor_args_list&,const Allocator&){}
void copy_(
const index_base<Value,IndexSpecifierList,Allocator>&,const copy_map_type&)
{}
node_type* insert_(value_param_type v,node_type* x)
{
boost::detail::allocator::construct(&x->value,v);
return x;
}
node_type* insert_(value_param_type v,node_type*,node_type* x)
{
boost::detail::allocator::construct(&x->value,v);
return x;
}
void erase_(node_type* x)
{
boost::detail::allocator::destroy(&x->value);
}
void swap_(index_base<Value,IndexSpecifierList,Allocator>&){}
bool replace_(value_param_type v,node_type* x)
{
x->value=v;
return true;
}
bool modify_(node_type*){return true;}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
bool invariant_()const{return true;}
#endif
/* access to backbone memfuns of Final class */
final_type& final(){return *static_cast<final_type*>(this);}
const final_type& final()const{return *static_cast<const final_type*>(this);}
final_node_type* final_header()const{return final().header();}
bool final_empty_()const{return final().empty_();}
std::size_t final_size_()const{return final().size_();}
std::size_t final_max_size_()const{return final().max_size_();}
std::pair<final_node_type*,bool> final_insert_(value_param_type x)
{return final().insert_(x);}
std::pair<final_node_type*,bool> final_insert_(
value_param_type x,final_node_type* position)
{return final().insert_(x,position);}
void final_erase_(final_node_type* x){final().erase_(x);}
void final_swap_(final_type& x){final().swap_(x);}
bool final_replace_(
value_param_type k,final_node_type* x)
{return final().replace_(k,x);}
template<typename Modifier>
bool final_modify_(Modifier mod,final_node_type* x)
{return final().modify_(mod,x);}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
void final_check_invariant_()const{final().check_invariant_();}
#endif
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,140 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_INDEX_ITERATOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#include <boost/multi_index/detail/index_iterator_fwd.hpp>
#include <boost/multi_index/detail/index_proxy.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
#include <boost/operators.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* An iterator template for nodes of multi_index::detail::index.
* Built with the aid boost::bidirectional_iterator_helper from
* boost/operators.hpp.
*/
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
template<typename Node>
class index_iterator:
public boost::bidirectional_iterator_helper<
index_iterator<Node>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>,
public safe_iterator<index_proxy<Node> >
#else
template<typename Node,typename Container>
class index_iterator:
public boost::bidirectional_iterator_helper<
index_iterator<Node,Container>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>,
public safe_iterator<Container>
#endif
#else
template<typename Node>
class index_iterator:
public boost::bidirectional_iterator_helper<
index_iterator<Node>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>
#endif
{
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
public:
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef index_proxy<Node> container_type;
#else
typedef Container container_type;
#endif
private:
typedef safe_iterator<container_type> safe_super;
public:
index_iterator():node(0){}
index_iterator(Node* node_,container_type* cont_):
safe_super(cont_),node(node_){}
index_iterator& operator=(const index_iterator& x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
safe_super::operator=(x);
node=x.node;
return *this;
}
#else
public:
index_iterator(){}
index_iterator(Node* node_):node(node_){}
#endif
const typename Node::value_type& operator*()const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);
return node->value;
}
index_iterator& operator++()
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);
Node::increment(node);
return *this;
}
index_iterator& operator--()
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(*this);
Node::decrement(node);
return *this;
}
friend bool operator==(const index_iterator& x,const index_iterator& y)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(y);
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(x,y);
return x.node==y.node;
}
/* get_node is not to be used by the user */
Node* get_node()const{return node;}
private:
Node* node;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,40 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_INDEX_ITERATOR_FWD_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_FWD_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
namespace boost{
namespace multi_index{
namespace detail{
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
template<typename Node>
class index_iterator;
#else
template<typename Node,typename Container>
class index_iterator;
#endif
#else
template<typename Node>
class index_iterator;
#endif
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,39 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_INDEX_NODE_BASE_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_NODE_BASE_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* index_node_base tops the node hierarchy of multi_index_container. It holds
* the value of the element contained.
*/
template<typename Value>
struct index_node_base
{
typedef Value value_type;
value_type value;
private:
index_node_base();
/* this class is not intended to be cted, merely allocated */
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,78 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_INDEX_PROXY_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_PROXY_HPP
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
#include <algorithm>
#include <boost/multi_index/detail/index_iterator_fwd.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* In safe mode, index iterators are derived from safe_iterator<Index>,
* where Index is the type of the index where the iterator belongs. Due
* to the long symbol names of indices, MSVC++ 6.0 often issues a
* LNK1179 (duplicate comdat) error. To workaround this problem,
* index_proxy is used instead. index_proxy<Node> acts as an index
* over nodes of type Node in all aspects relevant to safe_iterator, and
* its shorter symbol name makes life easier for MSVC++ 6.0.
*/
template<typename Node>
class index_proxy:public safe_container<index_proxy<Node> >
{
protected:
index_proxy(Node* header_):header(header_){}
void swap(index_proxy<Node>& x)
{
std::swap(header,x.header);
safe_container<index_proxy<Node> >::swap(x);
}
public:
typedef index_iterator<Node> iterator;
typedef index_iterator<Node> const_iterator;
index_iterator<Node> begin()const
{
return index_iterator<Node>(
Node::begin(header),const_cast<index_proxy*>(this));
}
index_iterator<Node> end()const
{
return index_iterator<Node>(
Node::end(header),const_cast<index_proxy*>(this));
}
private:
Node* header;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* workaround */
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
#endif
@@ -1,17 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_INVARIANT_ASSERT_HPP
#define BOOST_MULTI_INDEX_DETAIL_INVARIANT_ASSERT_HPP
#if !defined(BOOST_MULTI_INDEX_INVARIANT_ASSERT)
#include <boost/assert.hpp>
#define BOOST_MULTI_INDEX_INVARIANT_ASSERT BOOST_ASSERT
#endif
#endif
@@ -1,36 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_IS_INDEX_LIST_HPP
#define BOOST_MULTI_INDEX_DETAIL_IS_INDEX_LIST_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/empty.hpp>
#include <boost/mpl/is_sequence.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename T>
struct is_index_list
{
BOOST_STATIC_CONSTANT(bool,mpl_sequence=mpl::is_sequence<T>::value);
BOOST_STATIC_CONSTANT(bool,non_empty=!mpl::empty<T>::value);
BOOST_STATIC_CONSTANT(bool,value=mpl_sequence&&non_empty);
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,45 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_MODIFY_KEY_ADAPTOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_MODIFY_KEY_ADAPTOR_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* Functional adaptor to resolve modify_key as a call to modify.
* Preferred over compose_f_gx and stuff cause it eliminates problems
* with references to references, dealing with function pointers, etc.
*/
template<typename Modifier,typename Value,typename KeyFromValue>
struct modify_key_adaptor
{
modify_key_adaptor(Modifier mod_,KeyFromValue kfv_):mod(mod_),kfv(kfv_){}
void operator()(Value& x)
{
mod(kfv(x));
}
private:
Modifier mod;
KeyFromValue kfv;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,65 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_MSVC_INDEX_SPECIFIER_HPP
#define BOOST_MULTI_INDEX_DETAIL_MSVC_INDEX_SPECIFIER_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,<1310)
/* Workaround for a problem in MSVC with dependent template typedefs
* when accesing index specifiers.
* Modeled after <boost/mpl/aux_/msvc_dtw.hpp> (thanks, Aleksey!)
*/
#include <boost/mpl/aux_/msvc_never_true.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename IndexSpecifier>
struct msvc_index_specifier
{
template<bool> struct fake_index_type:IndexSpecifier{};
template<> struct fake_index_type<true>
{
template<typename Super>
struct node_class{};
template<typename Super>
struct index_class{};
};
template<typename Super>
struct result_node_class:
fake_index_type<mpl::aux::msvc_never_true<IndexSpecifier>::value>::
template node_class<Super>
{
};
template<typename Super>
struct result_index_class:
fake_index_type<mpl::aux::msvc_never_true<IndexSpecifier>::value>::
template index_class<Super>
{
};
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* workaround */
#endif
@@ -1,93 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_NO_DUPLICATE_TAGS_HPP
#define BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/fold.hpp>
#include <boost/mpl/set/set0.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* no_duplicate_tags check at compile-time that a tag list
* has no duplicate tags.
* The algorithm deserves some explanation: tags
* are sequentially inserted into a mpl::set if they were
* not already present. Due to the magic of mpl::set
* (mpl::has_key is contant time), this operation takes linear
* time, and even MSVC++ 6.5 handles it gracefully (other obvious
* solutions are quadratic.)
*/
struct duplicate_tag_mark{};
struct duplicate_tag_marker
{
template <typename MplSet,typename Tag>
struct apply
{
typedef mpl::s_item<
typename mpl::if_<mpl::has_key<MplSet,Tag>,duplicate_tag_mark,Tag>::type,
MplSet
> type;
};
};
template<typename TagList>
struct no_duplicate_tags
{
typedef typename mpl::fold<
TagList,
mpl::set0<>,
duplicate_tag_marker
>::type aux;
BOOST_STATIC_CONSTANT(
bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value));
};
/* Variant for an index list: duplication is checked
* across all the indices.
*/
struct duplicate_tag_list_marker
{
template <typename MplSet,typename Index>
struct apply:mpl::fold<
BOOST_DEDUCED_TYPENAME Index::tag_list,
MplSet,
duplicate_tag_marker>
{
};
};
template<typename IndexList>
struct no_duplicate_tags_in_index_list
{
typedef typename mpl::fold<
IndexList,
mpl::set0<>,
duplicate_tag_list_marker
>::type aux;
BOOST_STATIC_CONSTANT(
bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value));
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,76 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_NODE_TYPE_HPP
#define BOOST_MULTI_INDEX_DETAIL_NODE_TYPE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#include <boost/mpl/bind.hpp>
#include <boost/mpl/reverse_iter_fold.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/multi_index/detail/header_holder.hpp>
#include <boost/multi_index/detail/index_node_base.hpp>
#include <boost/multi_index/detail/is_index_list.hpp>
#include <boost/multi_index/detail/msvc_index_specifier.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/static_assert.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* MPL machinery to construct the internal node type associated to an
* index list.
*/
#if BOOST_WORKAROUND(BOOST_MSVC,<1310)
struct index_node_applier
{
template<typename IndexSpecifierIterator,typename Super>
struct apply:
msvc_index_specifier< mpl::deref<IndexSpecifierIterator>::type >::
template result_node_class<Super>
{
};
};
#else
struct index_node_applier
{
template<typename IndexSpecifierIterator,typename Super>
struct apply
{
typedef typename mpl::deref<IndexSpecifierIterator>::type index_specifier;
typedef typename index_specifier::
BOOST_NESTED_TEMPLATE node_class<Super>::type type;
};
};
#endif
template<typename Value,typename IndexSpecifierList,typename Allocator>
struct multi_index_node_type
{
BOOST_STATIC_ASSERT(detail::is_index_list<IndexSpecifierList>::value);
typedef typename mpl::reverse_iter_fold<
IndexSpecifierList,
index_node_base<Value>,
mpl::bind2<index_node_applier,mpl::_2,mpl::_1>
>::type type;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,86 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_ORD_INDEX_ARGS_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_ARGS_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
/* Oredered index specifiers can be instantiated in two forms:
*
* (ordered_unique|ordered_non_unique)<
* KeyFromValue,Compare=std::less<KeyFromValue::result_type> >
* (ordered_unique|ordered_non_unique)<
* TagList,KeyFromValue,Compare=std::less<KeyFromValue::result_type> >
*
* index_args implements the machinery to accept this argument-dependent
* polymorphism.
*/
struct null_arg{};
template<typename T>
struct not_is_null_arg
{
BOOST_STATIC_CONSTANT(bool,value=!(is_same<null_arg,T>::value));
};
template<typename KeyFromValue>
struct index_args_default_compare
{
typedef std::less<typename KeyFromValue::result_type> type;
};
template<typename Arg1,typename Arg2,typename Arg3>
struct ordered_index_args
{
typedef is_tag<Arg1> full_form;
typedef typename mpl::if_<
full_form,
Arg1,
tag< > >::type tag_list_type;
typedef typename mpl::if_<
full_form,
Arg2,
Arg1>::type key_from_value_type;
typedef typename mpl::if_<
full_form,
Arg3,
Arg2>::type supplied_compare_type;
typedef typename mpl::eval_if<
is_same<supplied_compare_type,null_arg>,
index_args_default_compare<key_from_value_type>,
mpl::identity<supplied_compare_type>
>::type compare_type;
BOOST_STATIC_ASSERT(is_tag<tag_list_type>::value);
BOOST_STATIC_ASSERT(not_is_null_arg<key_from_value_type>::value);
BOOST_STATIC_ASSERT(not_is_null_arg<compare_type>::value);
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,457 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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.
*
* The internal implementation of red-black trees is based on that of SGI STL
* stl_tree.h file:
*
* Copyright (c) 1996,1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
#include <algorithm>
#include <cstddef>
namespace boost{
namespace multi_index{
namespace detail{
/* definition of red-black nodes for ordered_index */
enum ordered_index_color{red=false,black=true};
struct ordered_index_node_impl
{
ordered_index_color& color(){return color_;}
const ordered_index_color& color()const{return color_;}
ordered_index_node_impl*& parent(){return parent_;}
ordered_index_node_impl*const & parent()const{return parent_;}
ordered_index_node_impl*& left(){return left_;}
ordered_index_node_impl*const & left()const{return left_;}
ordered_index_node_impl*& right(){return right_;}
ordered_index_node_impl*const & right()const{return right_;}
/* interoperability with index_iterator */
static void increment(ordered_index_node_impl*& x)
{
if(x->right()){
x=x->right();
while(x->left())x=x->left();
}
else{
ordered_index_node_impl* y=x->parent();
while(x==y->right()){
x=y;
y=y->parent();
}
if(x->right()!=y)x=y;
}
}
static void decrement(ordered_index_node_impl*& x)
{
if(x->color()==red&&x->parent()->parent()==x){
x=x->right();
}
else if(x->left()){
ordered_index_node_impl* y=x->left();
while(y->right())y=y->right();
x=y;
}else{
ordered_index_node_impl* y=x->parent();
while(x==y->left()){
x=y;
y=y->parent();
}
x=y;
}
}
/* interoperability with index_proxy */
static ordered_index_node_impl* begin(ordered_index_node_impl* header)
{
return header->left();
}
static ordered_index_node_impl* end(ordered_index_node_impl* header)
{
return header;
}
/* algorithmic stuff */
static void rotate_left(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
{
ordered_index_node_impl* y=x->right();
x->right()=y->left();
if(y->left())y->left()->parent()=x;
y->parent()=x->parent();
if(x==root) root=y;
else if(x==x->parent()->left())x->parent()->left()=y;
else x->parent()->right()=y;
y->left()=x;
x->parent()=y;
}
static ordered_index_node_impl* minimum(ordered_index_node_impl* x)
{
while(x->left())x=x->left();
return x;
}
static ordered_index_node_impl* maximum(ordered_index_node_impl* x)
{
while(x->right())x=x->right();
return x;
}
static void rotate_right(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
{
ordered_index_node_impl* y=x->left();
x->left()=y->right();
if(y->right())y->right()->parent()=x;
y->parent()=x->parent();
if(x==root) root=y;
else if(x==x->parent()->right())x->parent()->right()=y;
else x->parent()->left()=y;
y->right()=x;
x->parent()=y;
}
static void rebalance(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
{
x->color()=red;
while(x!=root&&x->parent()->color()==red){
if(x->parent()==x->parent()->parent()->left()){
ordered_index_node_impl* y=x->parent()->parent()->right();
if(y&&y->color()==red){
x->parent()->color()=black;
y->color()=black;
x->parent()->parent()->color()=red;
x=x->parent()->parent();
}
else{
if(x==x->parent()->right()){
x=x->parent();
rotate_left(x,root);
}
x->parent()->color()=black;
x->parent()->parent()->color()=red;
rotate_right(x->parent()->parent(),root);
}
}
else{
ordered_index_node_impl* y=x->parent()->parent()->left();
if(y&&y->color()==red){
x->parent()->color()=black;
y->color()=black;
x->parent()->parent()->color()=red;
x=x->parent()->parent();
}
else{
if(x==x->parent()->left()){
x=x->parent();
rotate_right(x,root);
}
x->parent()->color()=black;
x->parent()->parent()->color()=red;
rotate_left(x->parent()->parent(),root);
}
}
}
root->color()=black;
}
static ordered_index_node_impl* rebalance_for_erase(
ordered_index_node_impl* z,ordered_index_node_impl*& root,
ordered_index_node_impl*& leftmost,ordered_index_node_impl*& rightmost)
{
ordered_index_node_impl* y=z;
ordered_index_node_impl* x=0;
ordered_index_node_impl* x_parent=0;
if(y->left()==0){ /* z has at most one non-null child. y==z. */
x=y->right(); /* x might be null */
}
else{
if(y->right()==0) { /* z has exactly one non-null child. y==z. */
x=y->left(); /* x is not null */
}
else{ /* z has two non-null children. Set y to */
y=y->right(); /* z's successor. x might be null. */
while(y->left())y=y->left();
x=y->right();
}
}
if(y!=z){
z->left()->parent()=y; /* relink y in place of z. y is z's successor */
y->left()=z->left();
if(y!=z->right()){
x_parent=y->parent();
if(x) x->parent()=y->parent();
y->parent()->left()=x; /* y must be a child of left */
y->right()=z->right();
z->right()->parent()=y;
}
else{
x_parent=y;
}
if(root==z) root=y;
else if(z->parent()->left()==z)z->parent()->left()=y;
else z->parent()->right()=y;
y->parent()=z->parent();
std::swap(y->color(),z->color());
y=z; /* y now points to node to be actually deleted */
}
else{ /* y==z */
x_parent=y->parent();
if(x)x->parent()=y->parent();
if(root==z){
root=x;
}
else{
if(z->parent()->left()==z)z->parent()->left()=x;
else z->parent()->right()=x;
}
if(leftmost==z){
if(z->right()==0){ /* z->left() must be null also */
leftmost=z->parent();
}
else{
leftmost=minimum(x); /* makes leftmost==header if z==root */
}
}
if(rightmost==z){
if(z->left()==0){ /* z->right() must be null also */
rightmost=z->parent();
}
else{ /* x==z->left() */
rightmost=maximum(x); /* makes rightmost==header if z==root */
}
}
}
if(y->color()!=red){
while(x!=root&&(x==0 || x->color()==black)){
if(x==x_parent->left()){
ordered_index_node_impl* w=x_parent->right();
if(w->color()==red){
w->color()=black;
x_parent->color()=red;
rotate_left(x_parent,root);
w=x_parent->right();
}
if((w->left()==0||w->left()->color()==black) &&
(w->right()==0||w->right()->color()==black)){
w->color()=red;
x=x_parent;
x_parent=x_parent->parent();
}
else{
if(w->right()==0
|| w->right()->color()==black){
if(w->left()) w->left()->color()=black;
w->color()=red;
rotate_right(w,root);
w=x_parent->right();
}
w->color()=x_parent->color();
x_parent->color()=black;
if(w->right())w->right()->color()=black;
rotate_left(x_parent,root);
break;
}
}
else{ /* same as above,with right <-> left */
ordered_index_node_impl* w=x_parent->left();
if(w->color()==red){
w->color()=black;
x_parent->color()=red;
rotate_right(x_parent,root);
w=x_parent->left();
}
if((w->right()==0||w->right()->color()==black) &&
(w->left()==0||w->left()->color()==black)){
w->color()=red;
x=x_parent;
x_parent=x_parent->parent();
}
else{
if(w->left()==0||w->left()->color()==black){
if(w->right())w->right()->color()=black;
w->color()=red;
rotate_left(w,root);
w=x_parent->left();
}
w->color()=x_parent->color();
x_parent->color()=black;
if(w->left())w->left()->color()=black;
rotate_right(x_parent,root);
break;
}
}
}
if(x)x->color()=black;
}
return y;
}
static void restore(
ordered_index_node_impl* x,ordered_index_node_impl* prior,
ordered_index_node_impl* next,ordered_index_node_impl* header)
{
if(next->left()==0){
next->left()=x;
x->parent()=next;
if(next==header->left()){
header->left()=x; /* maintain leftmost pointing to min node */
}
}
else if(x!=prior){ /* prior->right() must be null */
prior->right()=x;
x->parent()=prior;
if(prior==header->right()){
header->right()=x; /* maintain rightmost pointing to max node */
}
}
else{
header->parent()=x;
header->left()=x;
header->right()=x;
x->parent()=header;
}
x->left()=0;
x->right()=0;
rebalance(x,header->parent());
}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
static std::size_t black_count(
ordered_index_node_impl* node,ordered_index_node_impl* root)
{
if(!node)return 0;
std::size_t sum=0;
for(;;){
if(node->color()==black)++sum;
if(node==root)break;
node=node->parent();
}
return sum;
}
#endif
private:
ordered_index_node_impl();
ordered_index_color color_;
ordered_index_node_impl* parent_;
ordered_index_node_impl* left_;
ordered_index_node_impl* right_;
};
template<typename Super>
struct ordered_index_node_trampoline:ordered_index_node_impl{};
template<typename Super>
struct ordered_index_node:Super,ordered_index_node_trampoline<Super>
{
ordered_index_color& color(){return impl_type::color();}
const ordered_index_color& color()const{return impl_type::color();}
ordered_index_node_impl*& parent(){return impl_type::parent();}
ordered_index_node_impl*const & parent()const{return impl_type::parent();}
ordered_index_node_impl*& left(){return impl_type::left();}
ordered_index_node_impl*const & left()const{return impl_type::left();}
ordered_index_node_impl*& right(){return impl_type::right();}
ordered_index_node_impl*const & right()const{return impl_type::right();}
ordered_index_node_impl* impl(){return static_cast<impl_type*>(this);}
const ordered_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
static ordered_index_node* from_impl(ordered_index_node_impl *x)
{
return static_cast<ordered_index_node*>(static_cast<impl_type*>(x));
}
static const ordered_index_node* from_impl(const ordered_index_node_impl* x)
{
return static_cast<const ordered_index_node*>(
static_cast<const impl_type*>(x));
}
/* interoperability with index_iterator */
static void increment(ordered_index_node*& x)
{
ordered_index_node_impl* xi=x->impl();
impl_type::increment(xi);
x=from_impl(xi);
}
static void decrement(ordered_index_node*& x)
{
ordered_index_node_impl* xi=x->impl();
impl_type::decrement(xi);
x=from_impl(xi);
}
/* interoperability with index_proxy */
static ordered_index_node* begin(ordered_index_node* header)
{
return from_impl(impl_type::begin(header->impl()));
}
static ordered_index_node* end(ordered_index_node* header)
{
return from_impl(impl_type::end(header->impl()));
}
private:
typedef ordered_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,121 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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.
*
* The internal implementation of red-black trees is based on that of SGI STL
* stl_tree.h file:
*
* Copyright (c) 1996,1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_OPS_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_OPS_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* Common code for index memfuns having templatized and
* non-templatized versions.
*/
template<
typename Node,typename KeyFromValue,
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_find(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while (z){
if(!comp(key(z->value),x)){
y=z;
z=Node::from_impl(z->left());
}
else z=Node::from_impl(z->right());
}
return (y==header||comp(x,key(y->value)))?header:y;
}
template<
typename Node,typename KeyFromValue,
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_lower_bound(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while(z){
if(!comp(key(z->value),x)){
y=z;
z=Node::from_impl(z->left());
}
else z=Node::from_impl(z->right());
}
return y;
}
template<
typename Node,typename KeyFromValue,
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_upper_bound(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while(z){
if(comp(x,key(z->value))){
y=z;
z=Node::from_impl(z->left());
}
else z=Node::from_impl(z->right());
}
return y;
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,56 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_PREVENT_ETI_HPP
#define BOOST_MULTI_INDEX_DETAIL_PREVENT_ETI_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
#include <boost/mpl/if.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/aux_/msvc_never_true.hpp>
#endif
namespace boost{
namespace multi_index{
namespace detail{
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
/* See
* http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Effective_MPL
* Item 5.6, Beware of the 'early template instantiation' trap.
*/
template<typename Type,typename Construct>
struct prevent_eti
{
typedef typename mpl::if_<
mpl::aux::msvc_never_true<Type>,
mpl::integral_c<int,0>,
Construct
>::type type;
};
#else
template<typename Type,typename Construct>
struct prevent_eti
{
typedef Construct type;
};
#endif
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,339 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_SAFE_MODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_SAFE_MODE_HPP
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/safe_mode_errors.hpp>
#include <boost/noncopyable.hpp>
namespace boost{
namespace multi_index{
/* Safe mode machinery, in the spirit of Cay Hortmann's "Safe STL"
* (http://www.horstmann.com/safestl.html).
* In this mode, containers of type Container are derived from
* safe_container<Container>, and their corresponding iterators
* are derived from safe_iterator<Container>. These classes provide
* an internal record of which iterators are at a given moment associated
* to a given container, and properly mark the iterators as invalid
* when the container gets destroyed.
* Iterators are chained in a single attached list, whose header is
* kept by the container. More elaborate data structures would yield better
* performance, but I decided to keep complexity to a minimum since
* speed is not an issue here.
* This is not a full-fledged safe mode framework, and is only inteded
* for use within the limits of Boost.MultiIndex.
*/
namespace safe_mode{
/* Invalidates all iterators equivalent to that given. Defined before
* safe_iterator_base and safe_container_base as these contain friendship
* declarations to this function.
*/
template<typename Iterator>
inline void detach_equivalent_iterators(Iterator& it)
{
if(it.valid()){
Iterator *prev_,*next_;
for(
prev_=static_cast<Iterator*>(&it.cont->header);
(next_=static_cast<Iterator*>(prev_->next))!=0;){
if(next_!=&it&&*next_==it){
prev_->next=next_->next;
next_->cont=0;
}
else prev_=next_;
}
it.detach();
}
}
} /* namespace multi_index::safe_mode */
namespace detail{
class safe_container_base;
class safe_iterator_base
{
public:
bool valid()const{return cont!=0;}
inline void detach();
protected:
safe_iterator_base():cont(0),next(0){}
explicit safe_iterator_base(safe_container_base* cont_){attach(cont_);}
safe_iterator_base(const safe_iterator_base& it){attach(it.cont);}
safe_iterator_base& operator=(const safe_iterator_base& it)
{
safe_container_base* new_cont=it.cont;
if(cont!=new_cont){
detach();
attach(new_cont);
}
return *this;
}
~safe_iterator_base()
{
detach();
}
const safe_container_base* owner()const{return cont;}
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
friend class safe_container_base;
#if !defined(BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS)
template<typename Iterator> friend
void safe_mode::detach_equivalent_iterators(Iterator&);
#endif
inline void attach(safe_container_base* cont_);
safe_container_base* cont;
safe_iterator_base* next;
};
class safe_container_base:private noncopyable
{
public:
safe_container_base(){}
~safe_container_base()
{
for(safe_iterator_base* it=header.next;it;it=it->next)it->cont=0;
}
void swap(safe_container_base& x)
{
for(safe_iterator_base* it0=header.next;it0;it0=it0->next)it0->cont=&x;
for(safe_iterator_base* it1=x.header.next;it1;it1=it1->next)it1->cont=this;
std::swap(header.cont,x.header.cont);
std::swap(header.next,x.header.next);
}
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
friend class safe_iterator_base;
#if !defined(BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS)
template<typename Iterator> friend
void safe_mode::detach_equivalent_iterators(Iterator&);
#endif
safe_iterator_base header;
};
void safe_iterator_base::attach(safe_container_base* cont_)
{
cont=cont_;
if(cont){
next=cont->header.next;
cont->header.next=this;
}
}
void safe_iterator_base::detach()
{
if(cont){
safe_iterator_base *prev_,*next_;
for(prev_=&cont->header;(next_=prev_->next)!=this;prev_=next_){}
prev_->next=next;
cont=0;
}
}
template<typename Container>
class safe_container;
template<typename Container>
class safe_iterator:public safe_iterator_base
{
public:
typedef Container container_type;
safe_iterator():safe_iterator_base(){}
explicit safe_iterator(safe_container<container_type>* cont_):
safe_iterator_base(cont_){}
const container_type* owner()const
{
return
static_cast<const container_type*>(
static_cast<const safe_container<container_type>*>(
safe_iterator_base::owner()));
}
};
template<typename Container>
class safe_container:public safe_container_base
{
public:
void swap(safe_container<Container>& x){safe_container_base::swap(x);}
};
} /* namespace multi_index::detail */
namespace safe_mode{
/* checking routines */
template<typename Iterator>
inline bool check_valid_iterator(const Iterator& it)
{
return it.valid();
}
template<typename Iterator>
inline bool check_dereferenceable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->end();
}
template<typename Iterator>
inline bool check_incrementable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->end();
}
template<typename Iterator>
inline bool check_decrementable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->begin();
}
template<typename Iterator>
inline bool check_is_owner(
const Iterator& it,const typename Iterator::container_type& cont)
{
return it.valid()&&it.owner()==&cont;
}
template<typename Iterator>
inline bool check_same_owner(const Iterator& it0,const Iterator& it1)
{
return it0.valid()&&it1.valid()&&it0.owner()==it1.owner();
}
template<typename Iterator>
inline bool check_valid_range(const Iterator& it0,const Iterator& it1)
{
if(!it0.valid()||!it1.valid()||it0.owner()!=it1.owner())return false;
Iterator last=it0.owner()->end();
if(it1==last)return true;
for(Iterator first=it0;first!=last;++first){
if(first==it1)return true;
}
return false;
}
template<typename Iterator>
inline bool check_outside_range(
const Iterator& it,const Iterator& it0,const Iterator& it1)
{
if(!it0.valid()||!it1.valid()||it0.owner()!=it1.owner())return false;
Iterator last=it0.owner()->end();
bool found=false;
Iterator first=it0;
for(;first!=last;++first){
if(first==it1)break;
/* crucial that this check goes after previous break */
if(first==it)found=true;
}
if(first!=it1)return false;
return !found;
}
template<typename Container>
inline bool check_different_container(
const Container& cont0,const Container& cont1)
{
return &cont0!=&cont1;
}
} /* namespace multi_index::safe_mode */
} /* namespace multi_index */
} /* namespace boost */
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
/* assertion macros */
#if !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#undef BOOST_MULTI_INDEX_SAFE_MODE_ASSERT
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) ((void)0)
#else
#if !defined(BOOST_MULTI_INDEX_SAFE_MODE_ASSERT)
#include <boost/assert.hpp>
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) BOOST_ASSERT(expr)
#endif
#endif
#define BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_valid_iterator(it), \
safe_mode::invalid_iterator);
#define BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_dereferenceable_iterator(it), \
safe_mode::not_dereferenceable_iterator);
#define BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_incrementable_iterator(it), \
safe_mode::not_incrementable_iterator);
#define BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
safe_mode::check_decrementable_iterator(it), \
safe_mode::not_decrementable_iterator);
#define BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,cont) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_is_owner(it,cont), \
safe_mode::not_owner);
#define BOOST_MULTI_INDEX_CHECK_SAME_OWNER(it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
safe_mode::check_same_owner(it0,it1), \
safe_mode::not_same_owner);
#define BOOST_MULTI_INDEX_CHECK_VALID_RANGE(it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_valid_range(it0,it1), \
safe_mode::invalid_range);
#define BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(it,it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
safe_mode::check_outside_range(it,it0,it1), \
safe_mode::inside_range);
#define BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(cont0,cont1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_different_container(cont0,cont1), \
safe_mode::same_container);
#endif
@@ -1,273 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_SCOPE_GUARD_HPP
#define BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
namespace boost{
namespace multi_index{
namespace detail{
/* Until some official version of the ScopeGuard idiom makes it into Boost,
* we locally define our own. This is a merely reformated version of
* ScopeGuard.h as defined in:
* Alexandrescu, A., Marginean, P.:"Generic<Programming>: Change the Way You
* Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000,
* http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/
* with the following modifications:
* - General pretty formatting (pretty to my taste at least.)
* - Naming style changed to standard C++ library requirements.
* - safe_execute does not feature a try-catch protection, so we can
* use this even if BOOST_NO_EXCEPTIONS is defined.
* - Added scope_guard_impl4 and obj_scope_guard_impl3, (Boost.MultiIndex
* needs them). A better design would provide guards for many more
* arguments through the Boost Preprocessor Library.
* - Added scope_guard_impl_base::touch (see below.)
* - Removed RefHolder and ByRef, whose functionality is provided
* already by Boost.Ref.
* - Removed static make_guard's and make_obj_guard's, so that the code
* will work even if BOOST_NO_MEMBER_TEMPLATES is defined. This forces
* us to move some private ctors to public, though.
*
* NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute
* without an explicit qualification.
*/
class scope_guard_impl_base
{
public:
scope_guard_impl_base():dismissed_(false){}
void dismiss()const{dismissed_=true;}
/* This helps prevent some "unused variable" warnings under, for instance,
* GCC 3.2.
*/
void touch()const{}
protected:
~scope_guard_impl_base(){}
scope_guard_impl_base(const scope_guard_impl_base& other):
dismissed_(other.dismissed_)
{
other.dismiss();
}
template<typename J>
static void safe_execute(J& j){if(!j.dismissed_)j.execute();}
mutable bool dismissed_;
private:
scope_guard_impl_base& operator=(const scope_guard_impl_base&);
};
typedef const scope_guard_impl_base& scope_guard;
template<typename F>
class scope_guard_impl0:public scope_guard_impl_base
{
public:
scope_guard_impl0(F fun):fun_(fun){}
~scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);}
void execute(){fun_();}
protected:
F fun_;
};
template<typename F>
inline scope_guard_impl0<F> make_guard(F fun)
{
return scope_guard_impl0<F>(fun);
}
template<typename F,typename P1>
class scope_guard_impl1:public scope_guard_impl_base
{
public:
scope_guard_impl1(F fun,P1 p1):fun_(fun),p1_(p1){}
~scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);}
void execute(){fun_(p1_);}
protected:
F fun_;
const P1 p1_;
};
template<typename F,typename P1>
inline scope_guard_impl1<F,P1> make_guard(F fun,P1 p1)
{
return scope_guard_impl1<F,P1>(fun,p1);
}
template<typename F,typename P1,typename P2>
class scope_guard_impl2:public scope_guard_impl_base
{
public:
scope_guard_impl2(F fun,P1 p1,P2 p2):fun_(fun),p1_(p1),p2_(p2){}
~scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
void execute(){fun_(p1_,p2_);}
protected:
F fun_;
const P1 p1_;
const P2 p2_;
};
template<typename F,typename P1,typename P2>
inline scope_guard_impl2<F,P1,P2> make_guard(F fun,P1 p1,P2 p2)
{
return scope_guard_impl2<F,P1,P2>(fun,p1,p2);
}
template<typename F,typename P1,typename P2,typename P3>
class scope_guard_impl3:public scope_guard_impl_base
{
public:
scope_guard_impl3(F fun,P1 p1,P2 p2,P3 p3):fun_(fun),p1_(p1),p2_(p2),p3_(p3){}
~scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);}
void execute(){fun_(p1_,p2_,p3_);}
protected:
F fun_;
const P1 p1_;
const P2 p2_;
const P3 p3_;
};
template<typename F,typename P1,typename P2,typename P3>
inline scope_guard_impl3<F,P1,P2,P3> make_guard(F fun,P1 p1,P2 p2,P3 p3)
{
return scope_guard_impl3<F,P1,P2,P3>(fun,p1,p2,p3);
}
template<typename F,typename P1,typename P2,typename P3,typename P4>
class scope_guard_impl4:public scope_guard_impl_base
{
public:
scope_guard_impl4(F fun,P1 p1,P2 p2,P3 p3,P4 p4):
fun_(fun),p1_(p1),p2_(p2),p3_(p3),p4_(p4){}
~scope_guard_impl4(){scope_guard_impl_base::safe_execute(*this);}
void execute(){fun_(p1_,p2_,p3_,p4_);}
protected:
F fun_;
const P1 p1_;
const P2 p2_;
const P3 p3_;
const P4 p4_;
};
template<typename F,typename P1,typename P2,typename P3,typename P4>
inline scope_guard_impl4<F,P1,P2,P3,P4> make_guard(
F fun,P1 p1,P2 p2,P3 p3,P4 p4)
{
return scope_guard_impl4<F,P1,P2,P3,P4>(fun,p1,p2,p3,p4);
}
template<class Obj,typename MemFun>
class obj_scope_guard_impl0:public scope_guard_impl_base
{
public:
obj_scope_guard_impl0(Obj& obj,MemFun mem_fun):obj_(obj),mem_fun_(mem_fun){}
~obj_scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);}
void execute(){(obj_.*mem_fun_)();}
protected:
Obj& obj_;
MemFun mem_fun_;
};
template<class Obj,typename MemFun>
inline obj_scope_guard_impl0<Obj,MemFun> make_obj_guard(Obj& obj,MemFun mem_fun)
{
return obj_scope_guard_impl0<Obj,MemFun>(obj,mem_fun);
}
template<class Obj,typename MemFun,typename P1>
class obj_scope_guard_impl1:public scope_guard_impl_base
{
public:
obj_scope_guard_impl1(Obj& obj,MemFun mem_fun,P1 p1):
obj_(obj),mem_fun_(mem_fun),p1_(p1){}
~obj_scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);}
void execute(){(obj_.*mem_fun_)(p1_);}
protected:
Obj& obj_;
MemFun mem_fun_;
const P1 p1_;
};
template<class Obj,typename MemFun,typename P1>
inline obj_scope_guard_impl1<Obj,MemFun,P1> make_obj_guard(
Obj& obj,MemFun mem_fun,P1 p1)
{
return obj_scope_guard_impl1<Obj,MemFun,P1>(obj,mem_fun,p1);
}
template<class Obj,typename MemFun,typename P1,typename P2>
class obj_scope_guard_impl2:public scope_guard_impl_base
{
public:
obj_scope_guard_impl2(Obj& obj,MemFun mem_fun,P1 p1,P2 p2):
obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2)
{}
~obj_scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
void execute(){(obj_.*mem_fun_)(p1_,p2_);}
protected:
Obj& obj_;
MemFun mem_fun_;
const P1 p1_;
const P2 p2_;
};
template<class Obj,typename MemFun,typename P1,typename P2>
inline obj_scope_guard_impl2<Obj,MemFun,P1,P2>
make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
{
return obj_scope_guard_impl2<Obj,MemFun,P1,P2>(obj,mem_fun,p1,p2);
}
template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
class obj_scope_guard_impl3:public scope_guard_impl_base
{
public:
obj_scope_guard_impl3(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3):
obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2),p3_(p3)
{}
~obj_scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);}
void execute(){(obj_.*mem_fun_)(p1_,p2_,p3_);}
protected:
Obj& obj_;
MemFun mem_fun_;
const P1 p1_;
const P2 p2_;
const P3 p3_;
};
template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
inline obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>
make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
{
return obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>(obj,mem_fun,p1,p2,p3);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,197 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_SEQ_INDEX_NODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_NODE_HPP
#include <algorithm>
namespace boost{
namespace multi_index{
namespace detail{
/* doubly-linked node for use by sequenced_index */
struct sequenced_index_node_impl
{
sequenced_index_node_impl*& prior(){return prior_;}
sequenced_index_node_impl*const & prior()const{return prior_;}
sequenced_index_node_impl*& next(){return next_;}
sequenced_index_node_impl*const & next()const{return next_;}
/* interoperability with index_iterator */
static void increment(sequenced_index_node_impl*& x){x=x->next();}
static void decrement(sequenced_index_node_impl*& x){x=x->prior();}
/* interoperability with index_proxy */
static sequenced_index_node_impl* begin(sequenced_index_node_impl* header)
{
return header->next();
}
static sequenced_index_node_impl* end(sequenced_index_node_impl* header)
{
return header;
}
/* algorithmic stuff */
static void link(
sequenced_index_node_impl* x,sequenced_index_node_impl* header)
{
x->prior()=header->prior();
x->next()=header;
x->prior()->next()=x->next()->prior()=x;
};
static void unlink(sequenced_index_node_impl* x)
{
x->prior()->next()=x->next();
x->next()->prior()=x->prior();
}
static void relink(
sequenced_index_node_impl* position,sequenced_index_node_impl* x)
{
unlink(x);
x->prior()=position->prior();
x->next()=position;
x->prior()->next()=x->next()->prior()=x;
}
static void relink(
sequenced_index_node_impl* position,
sequenced_index_node_impl* x,sequenced_index_node_impl* y)
{
/* position is assumed not to be in [x,y) */
if(x!=y){
sequenced_index_node_impl* z=y->prior();
x->prior()->next()=y;
y->prior()=x->prior();
x->prior()=position->prior();
z->next()=position;
x->prior()->next()=x;
z->next()->prior()=z;
}
}
static void reverse(sequenced_index_node_impl* header)
{
sequenced_index_node_impl* x=header;
do{
sequenced_index_node_impl* y=x->next();
std::swap(x->prior(),x->next());
x=y;
}while(x!=header);
}
static void swap(sequenced_index_node_impl* x,sequenced_index_node_impl* y)
{
/* This swap function does not exchange the header nodes,
* but rather their pointers. This is *not* used for implementing
* sequenced_index::swap.
*/
if(x->next()!=x){
if(y->next()!=y){
std::swap(x->next(),y->next());
std::swap(x->prior(),y->prior());
x->next()->prior()=x->prior()->next()=x;
y->next()->prior()=y->prior()->next()=y;
}
else{
y->next()=x->next();
y->prior()=x->prior();
x->next()=x->prior()=x;
y->next()->prior()=y->prior()->next()=y;
}
}
else if(y->next()!=y){
x->next()=y->next();
x->prior()=y->prior();
y->next()=y->prior()=y;
x->next()->prior()=x->prior()->next()=x;
}
}
private:
sequenced_index_node_impl();
sequenced_index_node_impl* prior_;
sequenced_index_node_impl* next_;
};
template<typename Super>
struct sequenced_index_node_trampoline:sequenced_index_node_impl{};
template<typename Super>
struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
{
sequenced_index_node_impl*& prior(){return impl_type::prior();}
sequenced_index_node_impl*const & prior()const{return impl_type::prior();}
sequenced_index_node_impl*& next(){return impl_type::next();}
sequenced_index_node_impl*const & next()const{return impl_type::next();}
sequenced_index_node_impl* impl()
{return static_cast<impl_type*>(this);}
const sequenced_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
static sequenced_index_node* from_impl(sequenced_index_node_impl *x)
{return static_cast<sequenced_index_node*>(static_cast<impl_type*>(x));}
static const sequenced_index_node* from_impl(
const sequenced_index_node_impl* x)
{
return static_cast<const sequenced_index_node*>(
static_cast<const impl_type*>(x));
}
/* interoperability with index_iterator */
static void increment(sequenced_index_node*& x)
{
sequenced_index_node_impl* xi=x->impl();
impl_type::increment(xi);
x=from_impl(xi);
}
static void decrement(sequenced_index_node*& x)
{
sequenced_index_node_impl* xi=x->impl();
impl_type::decrement(xi);
x=from_impl(xi);
}
/* interoperability with index_proxy */
static sequenced_index_node* begin(sequenced_index_node* header)
{
return from_impl(impl_type::begin(header->impl()));
}
static sequenced_index_node* end(sequenced_index_node* header)
{
return from_impl(impl_type::end(header->impl()));
}
private:
typedef sequenced_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,164 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_SEQ_INDEX_OPS_HPP
#define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_OPS_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/aligned_storage.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/multi_index/detail/seq_index_node.hpp>
#include <boost/limits.hpp>
#include <cstddef>
namespace boost{
namespace multi_index{
namespace detail{
/* Common code for sequenced_index memfuns having templatized and
* non-templatized versions.
*/
template <typename SequencedIndex,typename Predicate>
void sequenced_index_remove(SequencedIndex& x,Predicate pred)
{
typedef typename SequencedIndex::iterator iterator;
iterator first=x.begin(),last=x.end();
while(first!=last){
if(pred(*first))x.erase(first++);
else ++first;
}
}
template <typename SequencedIndex,class BinaryPredicate>
void sequenced_index_unique(SequencedIndex& x,BinaryPredicate binary_pred)
{
typedef typename SequencedIndex::iterator iterator;
iterator first=x.begin();
iterator last=x.end();
if(first!=last){
for(iterator middle=first;++middle!=last;middle=first){
if(binary_pred(*middle,*first))x.erase(middle);
else first=middle;
}
}
}
template <typename SequencedIndex,typename Compare>
void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
{
typedef typename SequencedIndex::iterator iterator;
if(x!=y){
iterator first0=x.begin(),last0=x.end();
iterator first1=y.begin(),last1=y.end();
while(first0!=last0&&first1!=last1){
if(comp(*first1,*first0))x.splice(first0,y,first1++);
else ++first0;
}
x.splice(last0,y,first1,last1);
}
}
/* sorting */
/* auxiliary stuff */
template<typename Node,typename Compare>
void sequenced_index_collate(
sequenced_index_node_impl* x,sequenced_index_node_impl* y,Compare comp
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
sequenced_index_node_impl* first0=x->next();
sequenced_index_node_impl* last0=x;
sequenced_index_node_impl* first1=y->next();
sequenced_index_node_impl* last1=y;
while(first0!=last0&&first1!=last1){
if(comp(Node::from_impl(first1)->value,Node::from_impl(first0)->value)){
sequenced_index_node_impl* tmp=first1->next();
sequenced_index_node_impl::relink(first0,first1);
first1=tmp;
}
else first0=first0->next();
}
sequenced_index_node_impl::relink(last0,first1,last1);
}
template<typename Node,typename Compare>
void sequenced_index_sort(Node* header,Compare comp)
{
/* Musser's mergesort, see http://www.cs.rpi.edu/~musser/gp/List/lists1.html.
* The implementation is a little convoluted: in the original code
* counter elements and carry are std::lists: here we do not want
* to use multi_index instead, so we do things at a lower level, managing
* directly the internal node representation.
* Incidentally, the implementations I've seen of this algorithm (SGI,
* Dinkumware, STLPort) are not exception-safe: this is. Moreover, we do not
* use any dynamic storage.
*/
if(header->next()==header->impl()||
header->next()->next()==header->impl())return;
BOOST_STATIC_CONSTANT(
std::size_t,
max_fill=(std::size_t)std::numeric_limits<std::size_t>::digits+1);
aligned_storage<
sizeof(sequenced_index_node_impl)> carry_spc;
sequenced_index_node_impl& carry=
*static_cast<sequenced_index_node_impl*>(carry_spc.address());
aligned_storage<
sizeof(
sequenced_index_node_impl[max_fill])> counter_spc;
sequenced_index_node_impl* counter=
static_cast<sequenced_index_node_impl*>(counter_spc.address());
std::size_t fill=0;
carry.prior()=carry.next()=&carry;
counter[0].prior()=counter[0].next()=&counter[0];
BOOST_TRY{
while(header->next()!=header->impl()){
sequenced_index_node_impl::relink(carry.next(),header->next());
std::size_t i=0;
while(i<fill&&counter[i].next()!=&counter[i]){
sequenced_index_collate<Node>(&carry,&counter[i++],comp);
}
sequenced_index_node_impl::swap(&carry,&counter[i]);
if(i==fill){
++fill;
counter[fill].prior()=counter[fill].next()=&counter[fill];
}
}
for(std::size_t i=1;i<fill;++i){
sequenced_index_collate<Node>(&counter[i],&counter[i-1],comp);
}
sequenced_index_node_impl::swap(header->impl(),&counter[fill-1]);
}
BOOST_CATCH(...)
{
sequenced_index_node_impl::relink(header->impl(),carry.next(),&carry);
for(std::size_t i=0;i<=fill;++i){
sequenced_index_node_impl::relink(
header->impl(),counter[i].next(),&counter[i]);
}
BOOST_RETHROW;
}
BOOST_CATCH_END
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,35 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_UNBOUNDED_HPP
#define BOOST_MULTI_INDEX_DETAIL_UNBOUNDED_HPP
namespace boost{
namespace multi_index{
/* dummy type and variable for use in ordered_index::range() */
namespace detail{
struct unbounded_type{};
} /* namespace multi_index::detail */
namespace{
detail::unbounded_type unbounded_obj=detail::unbounded_type();
detail::unbounded_type& unbounded=unbounded_obj;
} /* unnamed */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,48 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_DETAIL_VALUE_COMPARE_HPP
#define BOOST_MULTI_INDEX_DETAIL_VALUE_COMPARE_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/call_traits.hpp>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
template<typename Value,typename KeyFromValue,typename Compare>
struct value_comparison:std::binary_function<Value,Value,bool>
{
value_comparison(KeyFromValue key_=KeyFromValue(),Compare comp_=Compare()):
key(key_),comp(comp_)
{
}
bool operator()(
typename call_traits<Value>::param_type x,
typename call_traits<Value>::param_type y)
{
return comp(key(x),key(y));
}
private:
KeyFromValue key;
Compare comp;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
-123
View File
@@ -1,123 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_IDENTITY_HPP
#define BOOST_MULTI_INDEX_IDENTITY_HPP
#include <boost/config.hpp>
#include <boost/mpl/if.hpp>
#include <boost/multi_index/identity_fwd.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_const.hpp>
namespace boost{
template<class Type> class reference_wrapper; /* fwd decl. */
namespace multi_index{
namespace detail{
/* identity is a do-nothing key extractor that returns the [const] Type&
* object passed.
* Additionally, identity is overloaded to support referece_wrappers
* of Type and "chained pointers" to Type's. By chained pointer to Type we
* mean a type P such that, given a p of type P
* *...n...*x is convertible to Type&, for some n>=1.
* Examples of chained pointers are raw and smart pointers, iterators and
* arbitrary combinations of these (vg. Type** or auto_ptr<Type*>.)
*/
/* 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 Type>
struct const_identity_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type& operator()(Type& x)const
{
return x;
}
Type& operator()(const reference_wrapper<Type>& x)const
{
return x.get();
}
Type& operator()(
const reference_wrapper<typename remove_const<Type>::type>& x,int=0)const
{
return x.get();
}
};
template<typename Type>
struct non_const_identity_base
{
typedef Type result_type;
/* templatized for pointer-like types */
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
const Type& operator()(const Type& x,int=0)const
{
return x;
}
Type& operator()(Type& x)const
{
return x;
}
const Type& operator()(const reference_wrapper<const Type>& x,int=0)const
{
return x.get();
}
Type& operator()(const reference_wrapper<Type>& x)const
{
return x.get();
}
};
} /* namespace multi_index::detail */
template<class Type>
struct identity:
mpl::if_c<
is_const<Type>::value,
detail::const_identity_base<Type>,detail::non_const_identity_base<Type>
>::type
{
};
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,22 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_IDENTITY_HPP
#define BOOST_MULTI_INDEX_IDENTITY_HPP
namespace boost{
namespace multi_index{
template<class Type> struct identity;
} /* namespace multi_index */
} /* namespace boost */
#endif
-68
View File
@@ -1,68 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_INDEXED_BY_HPP
#define BOOST_MULTI_INDEX_INDEXED_BY_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/control/expr_if.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
/* An alias to mpl::vector used to hide MPL from the user.
* indexed_by contains the index specifiers for instantiation
* of a multi_index_container.
*/
/* This user_definable macro limits the number of elements of an index list;
* useful for shortening resulting symbol names (MSVC++ 6.0, for instance,
* has problems coping with very long symbol names.)
*/
#if !defined(BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE)
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
#define BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE 5
#else
#define BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
#endif
#endif
#if BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE<BOOST_MPL_LIMIT_VECTOR_SIZE
#define BOOST_MULTI_INDEX_INDEXED_BY_SIZE \
BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE
#else
#define BOOST_MULTI_INDEX_INDEXED_BY_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
#endif
#define BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM(z,n,var) \
typename BOOST_PP_CAT(var,n) BOOST_PP_EXPR_IF(n,=mpl::na)
namespace boost{
namespace multi_index{
template<
BOOST_PP_ENUM(
BOOST_MULTI_INDEX_INDEXED_BY_SIZE,
BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM,T)
>
struct indexed_by:
mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_INDEXED_BY_SIZE,T)>
{
};
} /* namespace multi_index */
} /* namespace boost */
#undef BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM
#undef BOOST_MULTI_INDEX_INDEXED_BY_SIZE
#endif
@@ -1,17 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_KEY_EXTRACTORS_HPP
#define BOOST_MULTI_INDEX_KEY_EXTRACTORS_HPP
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#endif
-181
View File
@@ -1,181 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_MEM_FUN_HPP
#define BOOST_MULTI_INDEX_MEM_FUN_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/if.hpp>
#include <boost/type_traits/remove_reference.hpp>
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
namespace multi_index{
/* mem_fun implements a read-only key extractor based on a given non-const
* member function of a class.
* const_mem_fun does the same for const member functions.
* Additionally, mem_fun and const_mem_fun are overloaded to support
* referece_wrappers of T and "chained pointers" to T's. By chained pointer
* to T we mean a type P such that, given a p of Type P
* *...n...*x is convertible to T&, for some n>=1.
* Examples of chained pointers are raw and smart pointers, iterators and
* arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
*/
/* 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<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
struct const_mem_fun
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(const Class& x)const
{
return (x.*PtrToMemberFunction)();
}
Type operator()(const reference_wrapper<const Class>& x)const
{
return operator()(x.get());
}
Type operator()(const reference_wrapper<Class>& x,int=0)const
{
return operator()(x.get());
}
};
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
struct mem_fun
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(Class& x)const
{
return (x.*PtrToMemberFunction)();
}
Type operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
/* MSVC++ 6.0 has problems with const member functions as non-type template
* parameters, somehow it takes them as non-const. mem_fun_explicit workarounds
* this defficiency by accepting an extra type parameter that specifies the
* signature of he member function. The workaround was found at:
* Daniel, C.:"Re: weird typedef problem in VC",
* news:microsoft.public.vc.language, 21st nov 2002,
* http://groups.google.com/groups?
* hl=en&lr=&ie=UTF-8&selm=ukwvg3O0BHA.1512%40tkmsftngp05
*/
template<
class Class,typename Type,
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
struct const_mem_fun_explicit
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(const Class& x)const
{
return (x.*PtrToMemberFunction)();
}
Type operator()(const reference_wrapper<const Class>& x)const
{
return operator()(x.get());
}
Type operator()(const reference_wrapper<Class>& x,int=0)const
{
return operator()(x.get());
}
};
template<
class Class,typename Type,
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
struct mem_fun_explicit
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(Class& x)const
{
return (x.*PtrToMemberFunction)();
}
Type operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
/* BOOST_MULTI_INDEX_CONST_MEM_FUN and BOOST_MULTI_INDEX_MEM_FUN resolve to
* mem_fun_explicit for MSVC++ 6.0 and to [const_]mem_fun otherwise.
*/
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
#define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::const_mem_fun_explicit<\
Class,Type,Type (Class::*)()const,&Class::MemberFunName>
#define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::mem_fun_explicit<\
Class,Type,Type (Class::*)(),&Class::MemberFunName>
#else
#define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::const_mem_fun<Class,Type,&Class::MemberFunName>
#define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::mem_fun<Class,Type,&Class::MemberFunName>
#endif
} /* namespace multi_index */
} /* namespace boost */
#endif
-235
View File
@@ -1,235 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_MEMBER_HPP
#define BOOST_MULTI_INDEX_MEMBER_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>
#include <cstddef>
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
namespace multi_index{
namespace detail{
/* member is a read/write key extractor for accessing a given
* member of a class.
* Additionally, member is overloaded to support referece_wrappers
* of T and "chained pointers" to T's. By chained pointer to T we mean
* a type P such that, given a p of Type P
* *...n...*x is convertible to T&, for some n>=1.
* Examples of chained pointers are raw and smart pointers, iterators and
* arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
*/
/* 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<class Class,typename Type,Type Class::*PtrToMember>
struct const_member_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type& operator()(const Class& x)const
{
return x.*PtrToMember;
}
Type& operator()(const reference_wrapper<const Class>& x)const
{
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class> x,int=0)const
{
return operator()(x.get());
}
};
template<class Class,typename Type,Type Class::*PtrToMember>
struct non_const_member_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
const Type& operator()(const Class& x,int=0)const
{
return x.*PtrToMember;
}
Type& operator()(Class& x)const
{
return x.*PtrToMember;
}
const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
{
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
} /* namespace multi_index::detail */
template<class Class,typename Type,Type Class::*PtrToMember>
struct member:
mpl::if_c<
is_const<Type>::value,
detail::const_member_base<Class,Type,PtrToMember>,
detail::non_const_member_base<Class,Type,PtrToMember>
>::type
{
};
namespace detail{
/* MSVC++ 6.0 does not support properly pointers to members as
* non-type template arguments, as reported in
* http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
* A similar problem (though not identical) is shown by MSVC++ 7.0.
* We provide an alternative to member<> accepting offsets instead
* of pointers to members. This happens to work even for non-POD
* types (although the standard forbids use of offsetof on these),
* so it serves as a workaround in this compiler for all practical
* purposes.
* Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
* Visual Age 6.0, have similar bugs. This replacement of member<>
* can be used for them too.
*/
template<class Class,typename Type,std::size_t OffsetOfMember>
struct const_member_offset_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type& operator()(const Class& x)const
{
return *static_cast<const Type*>(
static_cast<const void*>(
static_cast<const char*>(
static_cast<const void *>(&x))+OffsetOfMember));
}
Type& operator()(const reference_wrapper<const Class>& x)const
{
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class>& x,int=0)const
{
return operator()(x.get());
}
};
template<class Class,typename Type,std::size_t OffsetOfMember>
struct non_const_member_offset_base
{
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
const Type& operator()(const Class& x,int=0)const
{
return *static_cast<const Type*>(
static_cast<const void*>(
static_cast<const char*>(
static_cast<const void *>(&x))+OffsetOfMember));
}
Type& operator()(Class& x)const
{
return *static_cast<Type*>(
static_cast<void*>(
static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
}
const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
{
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
};
} /* namespace multi_index::detail */
template<class Class,typename Type,std::size_t OffsetOfMember>
struct member_offset:
mpl::if_c<
is_const<Type>::value,
detail::const_member_offset_base<Class,Type,OffsetOfMember>,
detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
>::type
{
};
/* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
* and to member_offset as a workaround in those defective compilers for
* which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
* This latter defect macro was included in Boost.Config starting from
* Boost 1.32, but we keep some additional checking of our own to
* remain compatible with Boost 1.31.
*/
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\
defined(BOOST_MSVC)&&(BOOST_MSVC<1310) ||\
defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\
(BOOST_INTEL_CXX_VERSION<=700) ||\
defined(__IBMCPP__)&&(__IBMCPP__<=600)
#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
::boost::multi_index::member_offset<Class,Type,offsetof(Class,MemberName)>
#else
#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
::boost::multi_index::member<Class,Type,&Class::MemberName>
#endif
} /* namespace multi_index */
} /* namespace boost */
#endif
File diff suppressed because it is too large Load Diff
@@ -1,112 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muńoz.
* 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_ORDERED_INDEX_FWD_HPP
#define BOOST_MULTI_INDEX_ORDERED_INDEX_FWD_HPP
#include <boost/multi_index/detail/ord_index_args.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<
typename KeyFromValue,typename Compare,
typename Super,typename TagList,typename Category
>
class index;
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator==(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator<(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator!=(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator>(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator>=(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue1,typename Compare1,
typename Super1,typename TagList1,typename Category1,
typename KeyFromValue2,typename Compare2,
typename Super2,typename TagList2,typename Category2
>
bool operator<=(
const index<KeyFromValue1,Compare1,Super1,TagList1,Category1>& x,
const index<KeyFromValue2,Compare2,Super2,TagList2,Category2>& y);
template<
typename KeyFromValue,typename Compare,
typename Super,typename TagList,typename Category
>
void swap(
index<KeyFromValue,Compare,Super,TagList,Category>& x,
index<KeyFromValue,Compare,Super,TagList,Category>& y);
} /* namespace multi_index::detail */
/* index specifiers */
template<
typename Arg1,typename Arg2=detail::null_arg,typename Arg3=detail::null_arg
>
struct ordered_unique;
template<
typename Arg1,typename Arg2=detail::null_arg,typename Arg3=detail::null_arg
>
struct ordered_non_unique;
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,43 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_SAFE_MODE_ERRORS_HPP
#define BOOST_MULTI_INDEX_SAFE_MODE_ERRORS_HPP
namespace boost{
namespace multi_index{
namespace safe_mode{
/* Error codes for Boost.MultiIndex safe mode. These go in a separate
* header so that the user can include it when redefining
* BOOST_MULTI_INDEX_SAFE_MODE_ASSERT prior to the inclusion of
* any other header of Boost.MultiIndex.
*/
enum error_code
{
invalid_iterator=0,
not_dereferenceable_iterator,
not_incrementable_iterator,
not_decrementable_iterator,
not_owner,
not_same_owner,
invalid_range,
inside_range,
same_container
};
} /* namespace multi_index::safe_mode */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,754 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_SEQUENCED_INDEX_HPP
#define BOOST_MULTI_INDEX_SEQUENCED_INDEX_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/call_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/index_iterator.hpp>
#include <boost/multi_index/detail/seq_index_node.hpp>
#include <boost/multi_index/detail/seq_index_ops.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
#include <boost/multi_index/detail/scope_guard.hpp>
#include <boost/multi_index/sequenced_index_fwd.hpp>
#include <boost/tuple/tuple.hpp>
#include <cstddef>
#include <functional>
#include <utility>
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
#define BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT \
detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
detail::make_obj_guard(*this,&sequenced_index::check_invariant_); \
BOOST_JOIN(check_invariant_,__LINE__).touch();
#else
#define BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT
#endif
namespace boost{
namespace multi_index{
namespace detail{
/* sequenced_index adds a layer of sequenced indexing to a given Super */
template<typename Super,typename TagList>
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
class sequenced_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS Super,
public index_proxy<sequenced_index_node<typename Super::node_type> >
#else
class sequenced_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS Super,
public safe_container<sequenced_index<Super,TagList> >
#endif
#else
class sequenced_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS Super
#endif
{
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
BOOST_WORKAROUND(__MWERKS__,<=0x3003)
/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
* lifetime of const references bound to temporaries --precisely what
* scopeguards are.
*/
#pragma parse_mfunc_templ off
#endif
protected:
typedef sequenced_index_node<typename Super::node_type> node_type;
public:
/* types */
typedef typename node_type::value_type value_type;
typedef tuples::null_type ctor_args;
typedef typename Super::final_allocator_type allocator_type;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef index_iterator<node_type> iterator;
typedef index_iterator<node_type> const_iterator;
#else
typedef index_iterator<node_type,sequenced_index> iterator;
typedef index_iterator<node_type,sequenced_index> const_iterator;
#endif
#else
typedef index_iterator<node_type> iterator;
typedef index_iterator<node_type> const_iterator;
#endif
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename
boost::reverse_iterator<iterator> reverse_iterator;
typedef typename
boost::reverse_iterator<const_iterator> const_reverse_iterator;
typedef typename TagList::type tag_list;
protected:
typedef typename Super::final_node_type final_node_type;
typedef tuples::cons<
ctor_args,
typename Super::ctor_args_list> ctor_args_list;
typedef typename mpl::push_front<
typename Super::index_type_list,
sequenced_index>::type index_type_list;
typedef typename mpl::push_front<
typename Super::iterator_type_list,
iterator>::type iterator_type_list;
typedef typename mpl::push_front<
typename Super::const_iterator_type_list,
const_iterator>::type const_iterator_type_list;
typedef typename Super::copy_map_type copy_map_type;
private:
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef index_proxy<sequenced_index_node<
typename Super::node_type> > safe_super;
#else
typedef safe_container<sequenced_index> safe_super;
#endif
#endif
typedef typename call_traits<value_type>::param_type value_param_type;
public:
/* construct/copy/destroy
* Default and copy ctors are in the protected section as indices are
* not supposed to be created on their own. No range ctor either.
*/
sequenced_index<Super,TagList>& operator=(
const sequenced_index<Super,TagList>& x)
{
this->final()=x.final();
return *this;
}
template <class InputIterator>
void assign(InputIterator first,InputIterator last)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
clear();
for(;first!=last;++first)push_back(*first);
}
void assign(size_type n,value_param_type value)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
clear();
for(size_type i=0;i<n;++i)push_back(value);
}
allocator_type get_allocator()const
{
return this->final().get_allocator();
}
/* iterators */
iterator begin()
{return make_iterator(node_type::from_impl(header()->next()));}
const_iterator begin()const
{return make_iterator(node_type::from_impl(header()->next()));}
iterator end(){return make_iterator(header());}
const_iterator end()const{return make_iterator(header());}
reverse_iterator rbegin(){return make_reverse_iterator(end());}
const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
reverse_iterator rend(){return make_reverse_iterator(begin());}
const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
/* capacity */
bool empty()const{return this->final_empty_();}
size_type size()const{return this->final_size_();}
size_type max_size()const{return this->final_max_size_();}
void resize(size_type n,value_param_type x=value_type())
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(n>size())insert(end(),n-size(),x);
else if(n<size()){
iterator it=begin();
std::advance(it,n);
erase(it,end());
}
}
/* access: no non-const versions provided as sequenced_index
* handles const elements.
*/
const_reference front()const{return *begin();}
const_reference back()const{return *--end();}
/* modifiers */
std::pair<iterator,bool> push_front(value_param_type x)
{return insert(begin(),x);}
void pop_front(){erase(begin());}
std::pair<iterator,bool> push_back(value_param_type x)
{return insert(end(),x);}
void pop_back(){erase(--end());}
std::pair<iterator,bool> insert(iterator position,value_param_type x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
std::pair<final_node_type*,bool> p=this->final_insert_(x);
if(p.second)relink(position.get_node(),p.first);
return std::pair<iterator,bool>(make_iterator(p.first),p.second);
}
void insert(iterator position,size_type n,value_param_type x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
for(size_type i=0;i<n;++i)insert(position,x);
}
template<typename InputIterator>
void insert(iterator position,InputIterator first,InputIterator last)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
for(;first!=last;++first)insert(position,*first);
}
iterator erase(iterator position)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
return position;
}
iterator erase(iterator first,iterator last)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
while(first!=last){
first=erase(first);
}
return first;
}
bool replace(iterator position,value_param_type x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
return this->final_replace_(
x,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier>
bool modify(iterator position,Modifier mod)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
* this is not added. Left it for all compilers as it does no
* harm.
*/
position.detach();
#endif
return this->final_modify_(
mod,static_cast<final_node_type*>(position.get_node()));
}
void swap(sequenced_index<Super,TagList>& x)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
this->final_swap_(x.final());
}
void clear()
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
erase(begin(),end());
}
/* list operations */
void splice(iterator position,sequenced_index<Super,TagList>& x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(*this,x);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
iterator first=x.begin(),last=x.end();
while(first!=last){
if(insert(position,*first).second)x.erase(first++);
else ++first;
}
}
void splice(iterator position,sequenced_index<Super,TagList>& x,iterator i)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(x==*this){
if(position!=i)relink(position.get_node(),i.get_node());
}
else{
if(insert(position,*i).second){
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer has a hard time with safe mode, and the following
* workaround is needed. Left it for all compilers as it does no
* harm.
*/
i.detach();
x.erase(x.make_iterator(i.get_node()));
#else
x.erase(i);
#endif
}
}
}
void splice(
iterator position,sequenced_index<Super,TagList>& x,
iterator first,iterator last)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(x==*this){
BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
if(position!=last)relink(
position.get_node(),first.get_node(),last.get_node());
}
else{
while(first!=last){
if(insert(position,*first).second)x.erase(first++);
else ++first;
}
}
}
void remove(value_param_type value)
{
sequenced_index_remove(
*this,std::bind2nd(std::equal_to<value_type>(),value));
}
template<typename Predicate>
void remove_if(Predicate pred)
{
sequenced_index_remove(*this,pred);
}
void unique()
{
sequenced_index_unique(*this,std::equal_to<value_type>());
}
template <class BinaryPredicate>
void unique(BinaryPredicate binary_pred)
{
sequenced_index_unique(*this,binary_pred);
}
void merge(sequenced_index<Super,TagList>& x)
{
sequenced_index_merge(*this,x,std::less<value_type>());
}
template <typename Compare>
void merge(sequenced_index<Super,TagList>& x,Compare comp)
{
sequenced_index_merge(*this,x,comp);
}
void sort()
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
sequenced_index_sort(header(),std::less<value_type>());
}
template <typename Compare>
void sort(Compare comp)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
sequenced_index_sort(header(),comp);
}
void reverse()
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
sequenced_index_node_impl::reverse(header()->impl());
}
/* relocate operations */
void relocate(iterator position,iterator i)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(position!=i)relink(position.get_node(),i.get_node());
}
void relocate(iterator position,iterator first,iterator last)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(position!=last)relink(
position.get_node(),first.get_node(),last.get_node());
}
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
sequenced_index(const ctor_args_list& args_list,const allocator_type& al):
Super(args_list.get_tail(),al)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)&&\
BOOST_WORKAROUND(BOOST_MSVC,<1300)
,safe_super(final_header())
#endif
{
header()->prior()=header()->next()=header()->impl();
}
sequenced_index(const sequenced_index<Super,TagList>& x):
Super(x)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)&&\
BOOST_WORKAROUND(BOOST_MSVC,<1300)
,safe_super(final_header())
#endif
{
/* The actual copying takes place in subsequent call to copy_().
*/
}
~sequenced_index()
{
/* the container is guaranteed to be empty by now */
}
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
iterator make_iterator(node_type* node){return iterator(node,this);}
const_iterator make_iterator(node_type* node)const
{return const_iterator(node,const_cast<sequenced_index*>(this));}
#else
iterator make_iterator(node_type* node){return iterator(node);}
const_iterator make_iterator(node_type* node)const
{return const_iterator(node);}
#endif
void copy_(const sequenced_index<Super,TagList>& x,const copy_map_type& map)
{
node_type* org=x.header();
node_type* cpy=header();
do{
node_type* next_org=node_type::from_impl(org->next());
node_type* next_cpy=map.find(static_cast<final_node_type*>(next_org));
cpy->next()=next_cpy->impl();
next_cpy->prior()=cpy->impl();
org=next_org;
cpy=next_cpy;
}while(org!=x.header());
Super::copy_(x,map);
}
node_type* insert_(value_param_type v,node_type* x)
{
node_type* res=static_cast<node_type*>(Super::insert_(v,x));
if(res==x)link(x);
return res;
}
node_type* insert_(value_param_type v,node_type* position,node_type* x)
{
node_type* res=static_cast<node_type*>(Super::insert_(v,position,x));
if(res==x)link(x);
return res;
}
void erase_(node_type* x)
{
unlink(x);
Super::erase_(x);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
}
void swap_(sequenced_index<Super,TagList>& x)
{
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
safe_super::swap(x);
#endif
Super::swap_(x);
}
bool replace_(value_param_type v,node_type* x)
{
return Super::replace_(v,x);
}
bool modify_(node_type* x)
{
BOOST_TRY{
if(!Super::modify_(x)){
unlink(x);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
return false;
}
else return true;
}
BOOST_CATCH(...){
unlink(x);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
BOOST_RETHROW;
}
BOOST_CATCH_END
}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
bool invariant_()const
{
if(size()==0||begin()==end()){
if(size()!=0||begin()!=end()||
header()->next()!=header()->impl()||
header()->prior()!=header()->impl())return false;
}
else{
size_type s=0;
for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s){
if(it.get_node()->next()->prior()!=it.get_node()->impl())return false;
if(it.get_node()->prior()->next()!=it.get_node()->impl())return false;
}
if(s!=size())return false;
}
return Super::invariant_();
}
/* This forwarding function eases things for the boost::mem_fn construct
* in BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT. Actually,
* final_check_invariant is already an inherited member function of index.
*/
void check_invariant_()const{this->final_check_invariant_();}
#endif
private:
node_type* header()const{return this->final_header();}
void link(node_type* x)
{
sequenced_index_node_impl::link(x->impl(),header()->impl());
};
static void unlink(node_type* x)
{
sequenced_index_node_impl::unlink(x->impl());
}
static void relink(node_type* position,node_type* x)
{
sequenced_index_node_impl::relink(position->impl(),x->impl());
}
static void relink(node_type* position,node_type* first,node_type* last)
{
sequenced_index_node_impl::relink(
position->impl(),first->impl(),last->impl());
}
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
void detach_iterators(node_type* x)
{
iterator it=make_iterator(x);
safe_mode::detach_equivalent_iterators(it);
}
#endif
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
BOOST_WORKAROUND(__MWERKS__,<=0x3003)
#pragma parse_mfunc_templ reset
#endif
};
/* comparison */
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator==(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator<(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator!=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return !(x==y);
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator>(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return y<x;
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator>=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return !(x<y);
}
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator<=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y)
{
return !(x>y);
}
/* specialized algorithms */
template<typename Super,typename TagList>
void swap(
sequenced_index<Super,TagList>& x,
sequenced_index<Super,TagList>& y)
{
x.swap(y);
}
} /* namespace multi_index::detail */
/* sequenced index specifier */
template <typename TagList>
struct sequenced
{
BOOST_STATIC_ASSERT(detail::is_tag<TagList>::value);
template<typename Super>
struct node_class
{
typedef detail::sequenced_index_node<Super> type;
};
template<typename Super>
struct index_class
{
typedef detail::sequenced_index<Super,TagList> type;
};
};
} /* namespace multi_index */
} /* namespace boost */
#undef BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT
#endif
@@ -1,87 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_SEQUENCED_INDEX_FWD_HPP
#define BOOST_MULTI_INDEX_SEQUENCED_INDEX_FWD_HPP
#include <boost/multi_index/tag.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename Super,typename TagList>
class sequenced_index;
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator==(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator<(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator!=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator>(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator>=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<
typename Super1,typename TagList1,
typename Super2,typename TagList2
>
bool operator<=(
const sequenced_index<Super1,TagList1>& x,
const sequenced_index<Super2,TagList2>& y);
template<typename Super,typename TagList>
void swap(
sequenced_index<Super,TagList>& x,
sequenced_index<Super,TagList>& y);
} /* namespace multi_index::detail */
/* index specifiers */
template <typename TagList=tag<> >
struct sequenced;
} /* namespace multi_index */
} /* namespace boost */
#endif
-79
View File
@@ -1,79 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_TAG_HPP
#define BOOST_MULTI_INDEX_TAG_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index/detail/no_duplicate_tags.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
/* An alias to mpl::vector used to hide MPL from the user.
* tag contains types used as tag names for indices in get() functions.
*/
/* This user_definable macro limits the number of elements of a tag;
* useful for shortening resulting symbol names (MSVC++ 6.0, for instance,
* has problems coping with very long symbol names.)
*/
#if !defined(BOOST_MULTI_INDEX_LIMIT_TAG_SIZE)
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
#define BOOST_MULTI_INDEX_LIMIT_TAG_SIZE 3
#else
#define BOOST_MULTI_INDEX_LIMIT_TAG_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
#endif
#endif
#if BOOST_MULTI_INDEX_LIMIT_TAG_SIZE<BOOST_MPL_LIMIT_VECTOR_SIZE
#define BOOST_MULTI_INDEX_TAG_SIZE BOOST_MULTI_INDEX_LIMIT_TAG_SIZE
#else
#define BOOST_MULTI_INDEX_TAG_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
#endif
namespace boost{
namespace multi_index{
namespace detail{
struct tag_marker{};
template<typename T>
struct is_tag
{
BOOST_STATIC_CONSTANT(bool,value=(is_base_and_derived<tag_marker,T>::value));
};
} /* namespace multi_index::detail */
template<
BOOST_PP_ENUM_BINARY_PARAMS(
BOOST_MULTI_INDEX_TAG_SIZE,
typename T,
=mpl::na BOOST_PP_INTERCEPT)
>
struct tag:private detail::tag_marker
{
typedef mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_TAG_SIZE,T)> type;
BOOST_STATIC_ASSERT(detail::no_duplicate_tags<type>::value);
};
} /* namespace multi_index */
} /* namespace boost */
#undef BOOST_MULTI_INDEX_TAG_SIZE
#endif
-925
View File
@@ -1,925 +0,0 @@
/* Multiply indexed container.
*
* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_HPP
#define BOOST_MULTI_INDEX_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/base_type.hpp>
#include <boost/multi_index/detail/converter.hpp>
#include <boost/multi_index/detail/def_ctor_tuple_cons.hpp>
#include <boost/multi_index/detail/header_holder.hpp>
#include <boost/multi_index/detail/has_tag.hpp>
#include <boost/multi_index/detail/no_duplicate_tags.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
#include <boost/multi_index/detail/scope_guard.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/base_from_member.hpp>
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
#include <boost/multi_index/detail/invariant_assert.hpp>
#define BOOST_MULTI_INDEX_CHECK_INVARIANT \
detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
detail::make_obj_guard(*this,&multi_index_container::check_invariant_); \
BOOST_JOIN(check_invariant_,__LINE__).touch();
#else
#define BOOST_MULTI_INDEX_CHECK_INVARIANT
#endif
namespace boost{
namespace multi_index{
template<typename Value,typename IndexSpecifierList,typename Allocator>
class multi_index_container:
private ::boost::base_from_member<
typename boost::detail::allocator::rebind_to<
Allocator,
typename detail::multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type
>::type>,
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
typename detail::multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type,
multi_index_container<Value,IndexSpecifierList,Allocator> >,
public detail::multi_index_base_type<
Value,IndexSpecifierList,Allocator>::type
{
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
BOOST_WORKAROUND(__MWERKS__,<=0x3003)
/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
* lifetime of const references bound to temporaries --precisely what
* scopeguards are.
*/
#pragma parse_mfunc_templ off
#endif
private:
#if !defined(BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename,typename,typename> friend class detail::index_base;
template <typename,typename> friend class detail::header_holder;
template <typename,typename> friend class detail::converter;
#endif
typedef typename detail::multi_index_base_type<
Value,IndexSpecifierList,Allocator>::type super;
typedef ::boost::base_from_member<
typename boost::detail::allocator::rebind_to<
Allocator,
typename super::node_type
>::type> bfm_allocator;
typedef detail::header_holder<
typename super::node_type,
multi_index_container> bfm_header;
public:
/* All types are inherited from super, a few are explicitly
* brought forward here to save us some typename's.
*/
#if defined(BOOST_MSVC)
typedef
detail::default_constructible_tuple_cons<
typename super::ctor_args_list> ctor_args_list;
#else
typedef typename super::ctor_args_list ctor_args_list;
#endif
typedef IndexSpecifierList index_specifier_type_list;
typedef typename super::index_type_list index_type_list;
typedef typename super::iterator_type_list iterator_type_list;
typedef typename super::const_iterator_type_list const_iterator_type_list;
typedef typename super::value_type value_type;
typedef typename super::final_allocator_type allocator_type;
typedef typename super::iterator iterator;
typedef typename super::const_iterator const_iterator;
BOOST_STATIC_ASSERT(
detail::no_duplicate_tags_in_index_list<index_type_list>::value);
/* global project() needs to see this publicly */
typedef typename super::node_type node_type;
/* construct/copy/destroy */
explicit multi_index_container(
#if BOOST_WORKAROUND(__IBMCPP__,<=600)
/* VisualAge seems to have an ETI issue with the default values
* for arguments args_list and al.
*/
const ctor_args_list& args_list=
typename mpl::identity<multi_index_container>::type::
ctor_args_list(),
const allocator_type& al=
typename mpl::identity<multi_index_container>::type::
allocator_type()):
#else
const ctor_args_list& args_list=ctor_args_list(),
const allocator_type& al=allocator_type()):
#endif
bfm_allocator(al),
super(args_list,bfm_allocator::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
}
template<typename InputIterator>
multi_index_container(
InputIterator first,InputIterator last,
#if BOOST_WORKAROUND(__IBMCPP__,<=600)
/* VisualAge seems to have an ETI issue with the default values
* for arguments args_list and al.
*/
const ctor_args_list& args_list=
typename mpl::identity<multi_index_container>::type::
ctor_args_list(),
const allocator_type& al=
typename mpl::identity<multi_index_container>::type::
allocator_type()):
#else
const ctor_args_list& args_list=ctor_args_list(),
const allocator_type& al=allocator_type()):
#endif
bfm_allocator(al),
super(args_list,bfm_allocator::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
BOOST_TRY{
iterator hint=super::end();
for(;first!=last;++first){
hint=super::make_iterator(insert_(*first,hint.get_node()).first);
}
}
BOOST_CATCH(...){
clean_up();
BOOST_RETHROW;
}
BOOST_CATCH_END
}
multi_index_container(
const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
bfm_allocator(x.bfm_allocator::member),
super(x),
node_count(0)
{
copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
map.clone(it.get_node());
}
super::copy_(x,map);
map.release();
node_count=x.size();
/* Not until this point are the indices required to be consistent,
* hence the position of the invariant checker.
*/
BOOST_MULTI_INDEX_CHECK_INVARIANT;
}
~multi_index_container()
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
clean_up();
}
multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
multi_index_container<Value,IndexSpecifierList,Allocator> tmp(x);
this->swap(tmp);
return *this;
}
allocator_type get_allocator()const
{
return allocator_type(bfm_allocator::member);
}
/* retrieval of indices by number */
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template<int N>
struct nth_index
{
BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
typedef typename mpl::at_c<index_type_list,N>::type type;
};
template<int N>
typename nth_index<N>::type& get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
return *this;
}
template<int N>
const typename nth_index<N>::type& get(
BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
{
BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
return *this;
}
#endif
/* retrieval of indices by tag */
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template<typename Tag>
struct index
{
typedef typename mpl::find_if<
index_type_list,
detail::has_tag<Tag>
>::type iter;
BOOST_STATIC_CONSTANT(
bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
BOOST_STATIC_ASSERT(index_found);
typedef typename mpl::deref<iter>::type type;
};
template<typename Tag>
typename index<Tag>::type& get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
{
return *this;
}
template<typename Tag>
const typename index<Tag>::type& get(
BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))const
{
return *this;
}
#endif
/* projection of iterators by number */
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template<int N>
struct nth_index_iterator
{
typedef typename nth_index<N>::type::iterator type;
};
template<int N>
struct nth_index_const_iterator
{
typedef typename nth_index<N>::type::const_iterator type;
};
template<int N,typename IteratorType>
typename nth_index_iterator<N>::type project(
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef typename nth_index<N>::type index;
BOOST_STATIC_ASSERT(
(mpl::contains<iterator_type_list,IteratorType>::value));
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(
it,static_cast<typename IteratorType::container_type&>(*this));
return index::make_iterator(static_cast<node_type*>(it.get_node()));
}
template<int N,typename IteratorType>
typename nth_index_const_iterator<N>::type project(
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
{
typedef typename nth_index<N>::type index;
BOOST_STATIC_ASSERT((
mpl::contains<iterator_type_list,IteratorType>::value||
mpl::contains<const_iterator_type_list,IteratorType>::value));
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(
it,static_cast<const typename IteratorType::container_type&>(*this));
return index::make_iterator(static_cast<node_type*>(it.get_node()));
}
#endif
/* projection of iterators by tag */
#if !defined(BOOST_NO_MEMBER_TEMPLATES)
template<typename Tag>
struct index_iterator
{
typedef typename index<Tag>::type::iterator type;
};
template<typename Tag>
struct index_const_iterator
{
typedef typename index<Tag>::type::const_iterator type;
};
template<typename Tag,typename IteratorType>
typename index_iterator<Tag>::type project(
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef typename index<Tag>::type index;
BOOST_STATIC_ASSERT(
(mpl::contains<iterator_type_list,IteratorType>::value));
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(
it,static_cast<typename IteratorType::container_type&>(*this));
return index::make_iterator(static_cast<node_type*>(it.get_node()));
}
template<typename Tag,typename IteratorType>
typename index_const_iterator<Tag>::type project(
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))const
{
typedef typename index<Tag>::type index;
BOOST_STATIC_ASSERT((
mpl::contains<iterator_type_list,IteratorType>::value||
mpl::contains<const_iterator_type_list,IteratorType>::value));
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(
it,static_cast<const typename IteratorType::container_type&>(*this));
return index::make_iterator(static_cast<node_type*>(it.get_node()));
}
#endif
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
typedef typename super::copy_map_type copy_map_type;
node_type* header()const
{
return bfm_header::member;
}
node_type* allocate_node()
{
return bfm_allocator::member.allocate(1);
}
void deallocate_node(node_type* x)
{
bfm_allocator::member.deallocate(x,1);
}
bool empty_()const
{
return node_count==0;
}
std::size_t size_()const
{
return node_count;
}
std::size_t max_size_()const
{
return static_cast<std::size_t >(-1);
}
std::pair<node_type*,bool> insert_(const Value& v)
{
node_type* x=allocate_node();
BOOST_TRY{
node_type* res=super::insert_(v,x);
if(res==x){
++node_count;
return std::pair<node_type*,bool>(res,true);
}
else{
deallocate_node(x);
return std::pair<node_type*,bool>(res,false);
}
}
BOOST_CATCH(...){
deallocate_node(x);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
std::pair<node_type*,bool> insert_(const Value& v,node_type* position)
{
node_type* x=allocate_node();
BOOST_TRY{
node_type* res=super::insert_(v,position,x);
if(res==x){
++node_count;
return std::pair<node_type*,bool>(res,true);
}
else{
deallocate_node(x);
return std::pair<node_type*,bool>(res,false);
}
}
BOOST_CATCH(...){
deallocate_node(x);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
void erase_(node_type* x)
{
super::erase_(x);
deallocate_node(x);
--node_count;
}
void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
{
std::swap(bfm_header::member,x.bfm_header::member);
super::swap_(x);
std::swap(node_count,x.node_count);
}
bool replace_(const Value& k,node_type* x)
{
return super::replace_(k,x);
}
template<typename Modifier>
bool modify_(Modifier mod,node_type* x)
{
mod(const_cast<value_type&>(x->value));
BOOST_TRY{
if(!super::modify_(x)){
deallocate_node(x);
--node_count;
return false;
}
else return true;
}
BOOST_CATCH(...){
deallocate_node(x);
--node_count;
BOOST_RETHROW;
}
BOOST_CATCH_END
}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
bool invariant_()const
{
return super::invariant_();
}
void check_invariant_()const
{
BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
}
#endif
private:
void clean_up()
{
for(iterator it=super::begin(),it_end=super::end();it!=it_end;){
erase_(it++.get_node());
}
}
std::size_t node_count;
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
BOOST_WORKAROUND(__MWERKS__,<=0x3003)
#pragma parse_mfunc_templ reset
#endif
};
/* retrieval of indices by number */
template<typename MultiIndexContainer,int N>
struct nth_index
{
BOOST_STATIC_CONSTANT(
int,
M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
BOOST_STATIC_ASSERT(N>=0&&N<M);
typedef typename mpl::at_c<
typename MultiIndexContainer::index_type_list,N>::type type;
};
template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
typename nth_index<
multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
get(
multi_index_container<Value,IndexSpecifierList,Allocator>& m
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename nth_index<
multi_index_container<
Value,IndexSpecifierList,Allocator>,
N
>::type index;
BOOST_STATIC_ASSERT(N>=0&&
N<
mpl::size<
BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
>::type::value);
return detail::converter<multi_index_type,index>::index(m);
}
template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
const typename nth_index<
multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
get(
const multi_index_container<Value,IndexSpecifierList,Allocator>& m
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename nth_index<
multi_index_container<
Value,IndexSpecifierList,Allocator>,
N
>::type index;
BOOST_STATIC_ASSERT(N>=0&&
N<
mpl::size<
BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
>::type::value);
return detail::converter<multi_index_type,index>::index(m);
}
/* retrieval of indices by tag */
template<typename MultiIndexContainer,typename Tag>
struct index
{
typedef typename MultiIndexContainer::index_type_list index_type_list;
typedef typename mpl::find_if<
index_type_list,
detail::has_tag<Tag>
>::type iter;
BOOST_STATIC_CONSTANT(
bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
BOOST_STATIC_ASSERT(index_found);
typedef typename mpl::deref<iter>::type type;
};
template<
typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
>
typename ::boost::multi_index::index<
multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
get(
multi_index_container<Value,IndexSpecifierList,Allocator>& m
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename ::boost::multi_index::index<
multi_index_container<
Value,IndexSpecifierList,Allocator>,
Tag
>::type index;
return detail::converter<multi_index_type,index>::index(m);
}
template<
typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
>
const typename ::boost::multi_index::index<
multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
get(
const multi_index_container<Value,IndexSpecifierList,Allocator>& m
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename ::boost::multi_index::index<
multi_index_container<
Value,IndexSpecifierList,Allocator>,
Tag
>::type index;
return detail::converter<multi_index_type,index>::index(m);
}
/* projection of iterators by number */
template<typename MultiIndexContainer,int N>
struct nth_index_iterator
{
typedef typename detail::prevent_eti<
nth_index<MultiIndexContainer,N>,
typename nth_index<MultiIndexContainer,N>::type>::type::iterator type;
};
template<typename MultiIndexContainer,int N>
struct nth_index_const_iterator
{
typedef typename detail::prevent_eti<
nth_index<MultiIndexContainer,N>,
typename nth_index<MultiIndexContainer,N>::type
>::type::const_iterator type;
};
template<
int N,typename IteratorType,
typename Value,typename IndexSpecifierList,typename Allocator>
typename nth_index_iterator<
multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
project(
multi_index_container<Value,IndexSpecifierList,Allocator>& m,
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename nth_index<multi_index_type,N>::type index;
#if !defined(BOOST_MSVC)||!(BOOST_MSVC<1300) /* this ain't work in MSVC++ 6.0 */
BOOST_STATIC_ASSERT((
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
IteratorType>::value));
#endif
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
typedef detail::converter<
multi_index_type,
BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
#endif
return detail::converter<multi_index_type,index>::iterator(
m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
}
template<
int N,typename IteratorType,
typename Value,typename IndexSpecifierList,typename Allocator>
typename nth_index_const_iterator<
multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
project(
const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename nth_index<multi_index_type,N>::type index;
#if !defined(BOOST_MSVC)||!(BOOST_MSVC<1300) /* this ain't work in MSVC++ 6.0 */
BOOST_STATIC_ASSERT((
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
IteratorType>::value||
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
IteratorType>::value));
#endif
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
typedef detail::converter<
multi_index_type,
BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
#endif
return detail::converter<multi_index_type,index>::const_iterator(
m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
}
/* projection of iterators by tag */
template<typename MultiIndexContainer,typename Tag>
struct index_iterator
{
typedef typename ::boost::multi_index::index<
MultiIndexContainer,Tag>::type::iterator type;
};
template<typename MultiIndexContainer,typename Tag>
struct index_const_iterator
{
typedef typename ::boost::multi_index::index<
MultiIndexContainer,Tag>::type::const_iterator type;
};
template<
typename Tag,typename IteratorType,
typename Value,typename IndexSpecifierList,typename Allocator>
typename index_iterator<
multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
project(
multi_index_container<Value,IndexSpecifierList,Allocator>& m,
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename ::boost::multi_index::index<
multi_index_type,Tag>::type index;
#if !defined(BOOST_MSVC)||!(BOOST_MSVC<1300) /* this ain't work in MSVC++ 6.0 */
BOOST_STATIC_ASSERT((
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
IteratorType>::value));
#endif
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
typedef detail::converter<
multi_index_type,
BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
#endif
return detail::converter<multi_index_type,index>::iterator(
m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
}
template<
typename Tag,typename IteratorType,
typename Value,typename IndexSpecifierList,typename Allocator>
typename index_const_iterator<
multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
project(
const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
IteratorType it
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
{
typedef multi_index_container<
Value,IndexSpecifierList,Allocator> multi_index_type;
typedef typename ::boost::multi_index::index<
multi_index_type,Tag>::type index;
#if !defined(BOOST_MSVC)||!(BOOST_MSVC<1300) /* this ain't work in MSVC++ 6.0 */
BOOST_STATIC_ASSERT((
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
IteratorType>::value||
mpl::contains<
BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
IteratorType>::value));
#endif
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
typedef detail::converter<
multi_index_type,
BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
#endif
return detail::converter<multi_index_type,index>::const_iterator(
m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
}
/* Comparison. Simple forward to first index. */
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator==(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)==get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator<(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)<get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator!=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)!=get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator>(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)>get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator>=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)>=get<0>(y);
}
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator<=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
{
return get<0>(x)<=get<0>(y);
}
/* specialized algorithms */
template<typename Value,typename IndexSpecifierList,typename Allocator>
void swap(
multi_index_container<Value,IndexSpecifierList,Allocator>& x,
multi_index_container<Value,IndexSpecifierList,Allocator>& y)
{
x.swap(y);
}
} /* namespace multi_index */
/* Associated global functions are promoted to namespace boost, except
* comparison operators and swap, which are meant to be Koenig looked-up.
*/
using multi_index::get;
using multi_index::project;
} /* namespace boost */
#undef BOOST_MULTI_INDEX_CHECK_INVARIANT
#endif
-117
View File
@@ -1,117 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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_FWD_HPP
#define BOOST_MULTI_INDEX_FWD_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/ordered_index_fwd.hpp>
#include <memory>
namespace boost{
namespace multi_index{
/* Default value for IndexSpecifierList specifies a container
* equivalent to std::set<Value>.
*/
template<
typename Value,
typename IndexSpecifierList=indexed_by<ordered_unique<identity<Value> > >,
typename Allocator=std::allocator<Value> >
class multi_index_container;
template<typename MultiIndexContainer,int N>
struct nth_index;
template<typename MultiIndexContainer,typename Tag>
struct index;
template<typename MultiIndexContainer,int N>
struct nth_index_iterator;
template<typename MultiIndexContainer,int N>
struct nth_index_const_iterator;
template<typename MultiIndexContainer,typename Tag>
struct index_iterator;
template<typename MultiIndexContainer,typename Tag>
struct index_const_iterator;
/* get and project functions not fwd declared due to problems
* with dependent typenames
*/
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator==(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator<(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator!=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator>(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator>=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<
typename Value1,typename IndexSpecifierList1,typename Allocator1,
typename Value2,typename IndexSpecifierList2,typename Allocator2
>
bool operator<=(
const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
template<typename Value,typename IndexSpecifierList,typename Allocator>
void swap(
multi_index_container<Value,IndexSpecifierList,Allocator>& x,
multi_index_container<Value,IndexSpecifierList,Allocator>& y);
} /* namespace multi_index */
/* multi_index_container, being the main type of this library, is promoted to
* namespace boost.
*/
using multi_index::multi_index_container;
} /* namespace boost */
#endif