C++ Boost multi-index type identification
In boost multi-index, can I verify w开发者_开发问答hether a particular index type is ordered/not through meta programming? There are the ordered indexes, hash indexes, sequence indexes etc. Can I find them out through meta programming?
Suppose there is a index like:
int main()
{
typedef multi_index_container<double> double_set;
return 0;
}
I want to know whether the double_set index is ordered or hashed or sequenced. Of course in this case, it is ordered.
Yes:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/distance.hpp>
#include <boost/mpl/begin.hpp>
namespace mpl = boost::mpl;
namespace mi = boost::multi_index;
//
// checking for ordered_unique:
//
template <typename MI>
struct is_nth_index_ordered_unique_helper : mpl::false_ {};
template <typename KeyFromValue, typename Compare>
struct is_nth_index_ordered_unique_helper<
mi::ordered_unique<KeyFromValue,Compare>
> : mpl::true_ {};
template <typename TagList, typename KeyFromValue, typename Compare>
struct is_nth_index_ordered_unique_helper<
mi::ordered_unique<TagList,KeyFromValue,Compare>
> : mpl::true_ {};
template <typename MI, int N>
struct is_nth_index_ordered_unique
: is_nth_index_ordered_unique_helper<
typename mpl::at_c< typename MI::index_specifier_type_list, N >::type
> {};
//
// checking for ordered_non_unique:
//
template <typename MI>
struct is_nth_index_ordered_non_unique_helper : mpl::false_ {};
template <typename KeyFromValue, typename Compare>
struct is_nth_index_ordered_non_unique_helper<
mi::ordered_non_unique<KeyFromValue,Compare>
> : mpl::true_ {};
template <typename TagList, typename KeyFromValue, typename Compare>
struct is_nth_index_ordered_non_unique_helper<
mi::ordered_non_unique<TagList,KeyFromValue,Compare>
> : mpl::true_ {};
template <typename MI, int N>
struct is_nth_index_ordered_non_unique
: is_nth_index_ordered_non_unique_helper<
typename mpl::at_c< typename MI::index_specifier_type_list, N >::type
> {};
//
// Combined (ordered_{non_,}unique):
//
template <typename MI, int N>
struct is_nth_index_ordered
: mpl::or_<
is_nth_index_ordered_unique<MI,N>,
is_nth_index_ordered_non_unique<MI,N>
> {};
//
// checking for sequenced:
//
template <typename MI>
struct is_nth_index_sequenced_helper : mpl::false_ {};
template <typename TagList>
struct is_nth_index_sequenced_helper<
mi::sequenced<TagList>
> : mpl::true_ {};
template <typename MI, int N>
struct is_nth_index_sequenced
: is_nth_index_sequenced_helper<
typename mpl::at_c< typename MI::index_specifier_type_list, N >::type
> {};
//
// test with example container:
//
typedef mi::multi_index_container<double> double_set_1;
BOOST_MPL_ASSERT(( is_nth_index_ordered<double_set_1,0> ));
BOOST_MPL_ASSERT(( mpl::not_< is_nth_index_sequenced<double_set_1,0> > ));
// or
BOOST_STATIC_ASSERT(( is_nth_index_ordered<double_set_1,0>::value ));
BOOST_STATIC_ASSERT(( mpl::not_< is_nth_index_sequenced<double_set_1,0> >::value ));
//
// And now with tag dispatch:
//
template <typename MI, typename Tag>
struct tag_to_n
: mpl::distance<
typename mpl::begin<typename MI::index_type_list>::type,
typename MI::template index<Tag>::iter
> {};
template <typename MI, typename Tag>
struct is_tagged_index_ordered_unique
: is_nth_index_ordered_unique<MI,tag_to_n<MI,Tag>::value> {};
template <typename MI, typename Tag>
struct is_tagged_index_ordered_non_unique
: is_nth_index_ordered_non_unique<MI,tag_to_n<MI,Tag>::value> {};
template <typename MI, typename Tag>
struct is_tagged_index_ordered
: is_nth_index_ordered<MI,tag_to_n<MI,Tag>::value> {};
template <typename MI, typename Tag>
struct is_tagged_index_sequenced
: is_nth_index_sequenced<MI,tag_to_n<MI,Tag>::value> {};
//
// test with another example container:
//
struct as_set {};
struct as_list {};
typedef mi::multi_index_container<
double,
mi::indexed_by<
mi::sequenced< mi::tag<as_list> >,
mi::ordered_non_unique< mi::tag<as_set>, mi::identity<double> >
>
> double_set_2;
void fun() {
double_set_2 ds2;
}
BOOST_MPL_ASSERT(( is_nth_index_sequenced<double_set_2,0> ));
BOOST_MPL_ASSERT(( is_nth_index_ordered<double_set_2,1> ));
BOOST_MPL_ASSERT(( mpl::not_< is_nth_index_ordered<double_set_2,0> > ));
BOOST_MPL_ASSERT(( mpl::not_< is_nth_index_sequenced<double_set_2,1> > ));
BOOST_MPL_ASSERT(( is_tagged_index_sequenced<double_set_2,as_list> ));
BOOST_MPL_ASSERT(( is_tagged_index_ordered<double_set_2,as_set> ));
BOOST_MPL_ASSERT(( mpl::not_< is_tagged_index_ordered<double_set_2,as_list> > ));
BOOST_MPL_ASSERT(( mpl::not_< is_tagged_index_sequenced<double_set_2,as_set> > ));
精彩评论