|
Boost Users : |
From: Alan M. Carroll (amc_at_[hidden])
Date: 2006-05-30 10:16:44
I needed to do exactly this myself. My solution is attached. After
including this header, if you have an existing tuple type T, you can do
what you want with
typedef boost::tuples::add_type<the_type, T>::type extended_tuple;
Adrián Etchevarne wrote:
> Problem:
> How can I get a tuple type from a tuples::cons<> list ?
> example:
> given the type:
> cons<int, cons<float, cons<int, null_type> > >
>
> obtain
> tuple<int, float, int>
>
>
> Real problem:
> I need to insert a type T at the beginning of a tuple, how I can do this?
>
# pragma once
# include <boost/tuple/tuple.hpp>
# include <boost/bind.hpp>
# include <boost/mpl/if.hpp>
/** @file
This is an utility extention to Boost::Tuples.
The purpose is to be able to convert an existing tuple type to another tuple
type with an additional type added to the front of the list of types in the tuple.
For instance, converting a tuple of the form @c tuple<A2,A1,A0>
to @c tuple<A3,A2,A1,A0>:
@code
// T is the current tuple type tuple::<A2,A1,A0>
typedef boost::tuples::add_type<A3, T>::type longer_tuple;
@endcode
*/
namespace boost { namespace tuples {
/** Metafunction to create a @c get function suitable for @c boost::bind.
@a N is the element index (0 based) and @a T is the tuple type.
Usage:
@code
typedef boost::tuple::<int, double, string> triple;
// A bound function to get the string element.
boost::bind(boost::tuples::get_mf<2,triple>::type, _1));
@endcode
You can also use the static @c bind method to return a bound object
without explicitly calling @c boost::bind. The following is exactly equivalen
to the previous example.
@code
boost::tuples::get_mf<2,triple>::bind();
@endcode
*/
template < int N, typename T >
struct get_mf {
typedef typename boost::tuples::element<N,T>::type return_type;
inline static return_type& type(T& tuple) { return tuple.get<N>(); }
typedef return_type& (*function_type)(T&);
/* The return type was discovered via compiler errors and is sensitive to
any implementation change in Boost.bind. I'm not sure how to do this
better as Boost.bind doesn't have a facility for computing this type.
*/
inline static boost::_bi::bind_t< return_type&
, function_type
, boost::_bi::list1<typename boost::_bi::list_av_1< boost::arg<1> >::B1>
> bind() { return boost::bind(type, _1); }
};
/** Metafunction to compute a new tuple from a type and an existing tuple.
For a type @c R and a tuple <tt>tuple<T0,T1...></tt> the result is the tuple
<tt>tuple<R,T0,T1,...></tt>
Example:
@code
typedef add_type<thing_t, current_tuple_t>::type extended_tuple_t;
@endcode
*/
template < typename R, typename T, int N = 0 >
struct add_type {
//! @cond NO_DOCS
typedef typename add_type<R, T, length<T>::value >::type type;
//! @endcond NO_DOCS
};
/** Metafunction class that calls @c add_type.
Example:
@code
typedef boost::tuple<int, char, float> tuple_t;
typedef add_type_mf::apply<thing_t, tuple_t>::type extended_tuple_t;
// extended_tuple_t == boost::tuple<thing_t, int, char, float>
@endcode
*/
struct add_type_mf {
//! @cond NO_DOCS
template < typename TYPE, typename TUPLE > struct apply {
typedef typename add_type<TYPE,TUPLE>::type type;
};
//! @endcond NO_DOCS
};
//! @cond NO_DOCS
template < typename R, typename T >
struct add_type<R,T,1> {
typedef tuple<R,
typename element<0, T>::type
> type;
};
template < typename R, typename T >
struct add_type<R,T,2> {
typedef tuple<R,
typename element<0, T>::type,
typename element<1, T>::type
> type;
};
template < typename R, typename T >
struct add_type<R,T,3> {
typedef tuple<R,
typename element<0, T>::type,
typename element<1, T>::type,
typename element<2, T>::type
> type;
};
template < typename R, typename T >
struct add_type<R,T,4> {
typedef tuple<R,
typename element<0, T>::type,
typename element<1, T>::type,
typename element<2, T>::type,
typename element<3, T>::type
> type;
};
template < typename R, typename T >
struct add_type<R,T,5> {
typedef tuple<R,
typename element<0, T>::type,
typename element<1, T>::type,
typename element<2, T>::type,
typename element<3, T>::type,
typename element<4, T>::type
> type;
};
template < typename R, typename T >
struct add_type<R,T,6> {
typedef tuple<R,
typename element<0, T>::type,
typename element<1, T>::type,
typename element<2, T>::type,
typename element<3, T>::type,
typename element<4, T>::type,
typename element<5, T>::type
> type;
};
template < typename R, typename T >
struct add_type<R,T,7> {
typedef tuple<R,
typename element<0, T>::type,
typename element<1, T>::type,
typename element<2, T>::type,
typename element<3, T>::type,
typename element<4, T>::type,
typename element<5, T>::type,
typename element<6, T>::type
> type;
};
template < typename R, typename T >
struct add_type<R,T,8> {
typedef tuple<R,
typename element<0, T>::type,
typename element<1, T>::type,
typename element<2, T>::type,
typename element<3, T>::type,
typename element<4, T>::type,
typename element<5, T>::type,
typename element<6, T>::type,
typename element<7, T>::type
> type;
};
template < typename R, typename T >
struct add_type<R,T,9> {
typedef tuple<R,
typename element<0, T>::type,
typename element<1, T>::type,
typename element<2, T>::type,
typename element<3, T>::type,
typename element<4, T>::type,
typename element<5, T>::type,
typename element<6, T>::type,
typename element<7, T>::type,
typename element<8, T>::type
> type;
};
//! @endcond
}}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net