The boost::mpl
algorithms seem not to be able to work on std::tuple
types out of the box, e.g., the following does not compile (boost-1.46.0, g++ snapshot 2011-02-19):
#include <tuple>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>
namespace mpl=boost::mpl;
typedef mpl::vector<int,float,bool> types;
static_assert(mpl::contains<types, float>::value, "vector contains bool");
typedef std::tuple<int,float,bool> types2;
// the following does not compile:
// error: no class template named ‘apply’ in ‘struct boost::mpl::contains_impl<boost::mpl::non_sequence_tag>’
static_assert(mpl::contains<types2, float>::value, "tuple contains bool");
What is the easiest way to make the boost::mpl
algorithms work on std::tuple
?
boost::fusion
provide this functionality (as it does so for boost::tuple
)?boost::tuple
to std::tuple
easily?Converting from std::tuple to boost types and back seems to be the easiest way
#include <iostream>
#include <tuple>
#include <type_traits>
#include <boost/mpl/if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/vector.hpp>
namespace mpl = boost::mpl;
template<typename Sequence, typename T>
struct push_front;
template<template<typename...> class Sequence, typename T, typename ... Args>
struct push_front< Sequence<Args...>,T> {
typedef Sequence<T, Args...> type;
};
template<template<typename...> class To, typename From> struct tuple_change;
template<template<typename...> class To, template<typename...> class From, typename ... Args>
struct tuple_change<To, From<Args...>>
{
typedef To<Args...> type;
};
template<typename Sequence, size_t N>
struct at : std::tuple_element<N,Sequence> { };
template<typename Sequence>
struct empty;
template<template<typename...> class Sequence, typename ... Args>
struct empty<Sequence<Args...>> {
typedef Sequence<> type;
};
template<
size_t N,
typename Sequence,
template<typename> class Pred,
typename ... Args >
struct while_impl
{
typedef typename mpl::if_c<
Pred<
typename at<Sequence, sizeof...(Args) - N -1>::type
>::value,
typename push_front<
typename while_impl<N-1, Sequence, Pred, Args...>::type,
typename at<Sequence,sizeof...(Args)-N-1>::type
>::type,
typename empty< Sequence > ::type
>::type type;
};
template<
typename Sequence,
template<typename> class Pred,
typename ... Args >
struct while_impl<-1, Sequence, Pred, Args...>
: empty<Sequence> {
};
template<
typename Sequence,
template<typename> class Pred>
struct while_;
template<
template<typename...> class Sequence,
template<typename> class Pred,
typename ... Args >
struct while_< Sequence<Args...>, Pred >
{
typedef typename while_impl<sizeof...(Args)-1, Sequence<Args...>, Pred, Args...>::type type;
};
template<typename T>
struct not_na : mpl::not_< std::is_same<mpl_::na, T> >
{ };
template<template<typename...> class To, typename From>
struct to_boost;
template<template<typename...> class To, typename...Args >
struct to_boost<To, std::tuple<Args...> > :
tuple_change< mpl::vector, std::tuple<Args...> >
{ };
template< typename From >
struct to_std;
template<template<typename...> class From, typename...Args >
struct to_std< From<Args...> > :
while_<typename tuple_change< std::tuple, From<Args...> >::type, not_na>
{ };
static_assert(
std::is_same<
mpl::vector< char, int, bool>,
typename to_boost<mpl::vector, std::tuple<char, int, bool> >::type
>::value,
"tuple_change to boost failed");
static_assert(
std::is_same<
std::tuple< char, int, bool>,
typename to_std< mpl::vector<char, int, bool> >::type
>::value,
"tuple_change from boost failed");
int main(){ return 0;}
*tested with:
boost_1_46_0 and g++-4.5 on MacOSx
boost_1_45_0 and g++-4.5 on Ubuntu 10.10