Listing 2
#include <boost/tuple/tuple.hpp>
// Template to append a type to a cons, thus creating a new cons.
template< class CONS, class TYPE >
struct AppendCons
{
typedef boost::tuples::cons<
typename CONS::head_type, typename AppendCons<
typename CONS::tail_type, TYPE >::type > type;
};
// Partially specialize for the end of the list.
template< class TYPE >
struct AppendCons< boost::tuples::null_type, TYPE >
{
typedef boost::tuples::cons<
TYPE, boost::tuples::null_type > type;
};
// A type that collects values. Like Boost tuple, this type is a cons.
// However, unlike Boost tuple, it is left-associative. That's
// because the dot operator is left-associative.
template< class HEAD, class TAIL >
struct GenTuple
{
// The GenTuple defining the first part of the set.
HEAD head;
// Use of TAIL reference makes it possible for the compiler to optimize.
// However, it also means that the object lifetime must be shorter than
// the values it manages. Fortunately, this class
// is only intended to be used as a temporary.
const TAIL &tail;
// Generate the type of Boost cons, which is the workhorse behind tuple.
typedef typename AppendCons<
typename HEAD::cons, TAIL >::type cons;
// Count the items in the tuple.
enum { DEPTH = HEAD::DEPTH+1 };
GenTuple( const HEAD &h, const TAIL &t ) :
head( h ),
tail( t ) {}
// Return new object that also implements add, which lets you chain calls.
template< class NEXT >
GenTuple< GenTuple< HEAD, TAIL >, NEXT >
add( const NEXT &next ) const
{
return GenTuple< GenTuple< HEAD, TAIL >, NEXT >
( *this, next );
}
// Construct, initialize, and return a Boost tuple.
cons tuple() const
{
cons value;
prepareTuple( value );
return value;
}
// Recursively fill in the tuple.
template< class TUPLE >
void prepareTuple( TUPLE &t ) const
{
head.prepareTuple( t );
::boost::tuples::get<DEPTH>(t) = tail;
}
// Discourage declaration of non-temporaries.
GenTuple();
};
// Start with a type that generates an empty tuple.
struct GenTupleStart
{
enum { DEPTH = -1 };
typedef boost::tuples::null_type cons;
template< class TUPLE >
void prepareTuple( TUPLE &t ) const
{
}
};
// Start the process with a function.
template< class FIRST >
GenTuple< GenTupleStart, FIRST >
genTuple( const FIRST &first )
{
return GenTuple< GenTupleStart, FIRST >
( GenTupleStart(), first );
}