mirror of
https://github.com/boostorg/multi_index.git
synced 2026-07-21 13:23:43 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f0b6472499 | |||
| 4ee5a7e0e9 | |||
| a657e1df3b |
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user