If you wanted to not convert the std::tuple into a mpl type, you can overload the tag dispatching boost mpl uses:
#include <tuple>
#include <boost/mpl/sequence_tag.hpp>
#include <boost/mpl/pop_front_fwd.hpp>
#include <boost/mpl/push_front_fwd.hpp>
#include <boost/mpl/push_back_fwd.hpp>
#include <boost/mpl/front_fwd.hpp>
#include <boost/mpl/empty_fwd.hpp>
#include <boost/mpl/size_fwd.hpp>
#include <boost/mpl/at_fwd.hpp>
#include <boost/mpl/back_fwd.hpp>
#include <boost/mpl/clear_fwd.hpp>
#include <boost/mpl/pop_back_fwd.hpp>
#include <boost/mpl/iterator_tags.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/begin_end_fwd.hpp>
namespace boost { namespace mpl {
namespace aux { struct std_tuple; }
template<class ... Args>
struct sequence_tag<std::tuple<Args...> >
{
typedef aux::std_tuple type;
};
template<>
struct front_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
: std::tuple_element<0, Tuple>
{
};
};
template<>
struct empty_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
: std::integral_constant<bool, std::tuple_size<Tuple>::value == 0>
{
};
};
template<>
struct pop_front_impl< aux::std_tuple >
{
template< typename Tuple > struct apply;
template< class First, class ... Types > struct apply<std::tuple<First, Types...>>
{
typedef std::tuple<Types...> type;
};
};
template<>
struct push_front_impl< aux::std_tuple >
{
template< typename Tuple, typename T > struct apply;
template< typename T, typename ... Args >
struct apply<std::tuple<Args...>, T>
{
typedef std::tuple<T, Args...> type;
};
};
template<>
struct push_back_impl< aux::std_tuple >
{
template< typename Tuple, typename T > struct apply;
template< typename T, typename ... Args >
struct apply<std::tuple<Args...>, T>
{
typedef std::tuple<Args..., T> type;
};
};
template<>
struct size_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
: std::tuple_size<Tuple>
{
};
};
template<>
struct at_impl< aux::std_tuple >
{
template< typename Tuple, typename N > struct apply
: std::tuple_element<N::value, Tuple>
{
};
};
template<>
struct back_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
: std::tuple_element<std::tuple_size<Tuple>::value - 1, Tuple>
{
};
};
template<>
struct clear_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
{
typedef std::tuple<> type;
};
};
template<>
struct pop_back_impl< aux::std_tuple >
{
template<int ...> struct tuple_seq {};
template<int N, int ...S> struct tuple_gens : tuple_gens<N-1, N-1, S...> {};
template<int ...S> struct tuple_gens<0, S...>{ typedef tuple_seq<S...> type; };
template < class Tuple, class Index> struct apply_impl;
template < class Tuple, int ... S> struct apply_impl<Tuple, tuple_seq<S...>>
{
typedef std::tuple<typename std::tuple_element<S, Tuple>::type...> type;
};
template< typename Tuple > struct apply : apply_impl<Tuple, typename tuple_gens<std::tuple_size<Tuple>::value - 1>::type> { };
};
template< class ... Args >
struct tuple_iter;
template< class ... Args >
struct tuple_iter<std::tuple<Args...>>
{
typedef aux::std_tuple tag;
typedef forward_iterator_tag category;
};
template<>
struct begin_impl< aux::std_tuple >
{
template< class Tuple > struct apply
{
typedef tuple_iter<Tuple> type;
};
};
template<>
struct end_impl< aux::std_tuple >
{
template< typename > struct apply
{
typedef tuple_iter<std::tuple<>> type;
};
};
template< typename First, class ... Args >
struct deref< tuple_iter<std::tuple<First, Args...> > >
{
typedef First type;
};
template< typename First, class ... Args >
struct next< tuple_iter<std::tuple<First, Args...>> >
{
typedef tuple_iter< std::tuple<Args...> > type;
};
} }
And the associated test:
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/clear.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/aux_/test.hpp>
MPL_TEST_CASE()
{
typedef std::tuple<int, char, bool> Tuple;
MPL_ASSERT((is_same<front<Tuple>::type, int>));
MPL_ASSERT_RELATION( size<Tuple>::type::value, ==, 3 );
MPL_ASSERT(( is_same< pop_front<Tuple>::type, std::tuple<char, bool> > ));
MPL_ASSERT(( is_same< push_front<Tuple, unsigned>::type, std::tuple<unsigned, int, char, bool> > ));
MPL_ASSERT(( is_same< push_back<Tuple, unsigned>::type, std::tuple<int, char, bool, unsigned> > ));
MPL_ASSERT_RELATION( empty<Tuple>::type::value, ==, false );
MPL_ASSERT(( is_same< at_c<Tuple, 0>::type, int > ));
MPL_ASSERT(( is_same< at_c<Tuple, 1>::type, char > ));
MPL_ASSERT(( is_same< back<Tuple>::type, bool > ));
MPL_ASSERT(( is_same< clear<Tuple>::type, std::tuple<> > ));
MPL_ASSERT(( is_same< pop_back<Tuple>::type, std::tuple<int, char> > ));
MPL_ASSERT(( contains<Tuple, int> ));
MPL_ASSERT(( contains<Tuple, char> ));
MPL_ASSERT(( contains<Tuple, bool> ));
MPL_ASSERT_NOT(( contains<Tuple, unsigned> ));
}
I tested this with gcc 4.7.2 and clang 3.2. It should contain everything you need to use anything in the mpl (actually a litte more than it needs). You can think of a tuple as a mpl::list (forward iterator compile type). So, to make it play nice you should implmenet what boost::mpl::list does. A quick look into the boost/mpl/list/aux_ directory:
begin_end.hpp empty.hpp iterator.hpp pop_front.hpp push_back.hpp size.hpp
clear.hpp front.hpp push_front.hpp tag.hpp
are the relevant files that need to be implemented.
std::tuple
s or code that expectsstd::tuple
s -- you would have to convert types in both directions which is somewhat awkward. I also thought thatboost::tuple
was something like an "early prototype" after whichstd::tuple
later on was modeled, and thus thatstd::tuple
would replaceboost::tuple
in the long run? – Withamto_boost
andto_std
template that allows conversion to and from arbitrary boost mpl Sequences – Gabel