The type of an element can be obtained with ntuple<>'s typeinfo<> member class template.
enum what_t { eInt, eDouble, eChar };
what_t what( int ) { return eInt; }
what_t what( double ) { return eDouble; }
what_t what( char ) { return eChar; }
int main()
{
typedef ntuple< int, double, char > tuple_t;
tuple_t::typeinfo< 0 >::type _int( 3 );
tuple_t::typeinfo< 1 >::type _double( 4.5 );
tuple_t::typeinfo< 2 >::type _char( 'a' );
CHECK( what( _int ) == eInt && _int == 3 );
CHECK( what( _double ) == eDouble && _double == 4.5 );
CHECK( what( _char ) == eChar && _char == 'a' );
tuple_t tuple( _int, _double, _char );
std::cout << tuple << std::endl;
tuple_t::typeinfo< 0 >::remainder_type r = tuple.remainder();
CHECK( r == ntuple_( _double, _char ) );
return 0;
}
Test Result: gcc34 Passed, msvc80 Passed, msvc71 Passed
Output
(3,4.5,a)
ntuple has two member class templates for creating new tuple types.
template < template < typename > class MF > struct meta_apply;
This member creates a tuple type by applying the meta-function MF to each element-type in turn.
In the test below widen is a meta-function that transforms char and short to int and float to double.
enum what_t { e_char, e_short, e_int, e_long, e_float, e_double };
#define JOIN( A, B ) A ## B
#define WHAT( Type ) \
what_t what( Type ) { return JOIN(e_, Type); }
WHAT( char )
WHAT( short )
WHAT( int )
WHAT( long )
WHAT( float )
WHAT( double )
#undef WHAT
#undef JOIN
template < typename T > struct widen
{
typedef T type;
};
#define WIDEN( From, To ) \
template <> struct widen< From > { typedef To type; }
WIDEN( char, int );
WIDEN( short, int );
WIDEN( float, double );
#undef WIDEN
bool main()
{
typedef ntuple< char, short, int, long, float, double > original_t;
/* DOIT
*/
typedef original_t::meta_apply< widen >::type wide_t;
original_t original( 'a', 1, 2, 3, 1e20, 1e40 );
wide_t wide( original );
CHECK( original == wide );
CHECK( what( original.at<0>() ) == e_char && what( wide.at<0>() ) == e_int );
CHECK( what( original.at<1>() ) == e_short && what( wide.at<1>() ) == e_int );
CHECK( what( original.at<2>() ) == e_int && what( wide.at<2>() ) == e_int );
CHECK( what( original.at<3>() ) == e_long && what( wide.at<3>() ) == e_long );
CHECK( what( original.at<4>() ) == e_float && what( wide.at<4>() ) == e_double );
CHECK( what( original.at<5>() ) == e_double && what( wide.at<5>() ) == e_double );
std::cout << "original: " << original << "\twide: " << wide << std::endl;
return true;
}
Test Result: gcc34 Passed, msvc80 Passed, msvc71 Passed
Output
original: (a,1,2,3,1e+020,1e+040) wide: (97,1,2,3,1e+020,1e+040)
template < template < typename, int > class IMF, int Offset = 0 > struct meta_index_apply;
As with meta_apply<>``_ above ``meta_index_apply<> transforms its tuple type into another tuple type, however meta_index_apply<> also passes the index of the element to its meta-function argument.
The following test uses constify, a meta-function that adds a const qualifier to the first N elements.
template < typename T, bool B > struct constify_helper
{
typedef T type;
};
template < typename T > struct constify_helper< T, true >
{
typedef T const type;
};
template < typename T, int Off > struct constify
{
typedef typename constify_helper< T, (Off < 0) >::type type;
};
bool is_const( int &value )
{
std::cout << value << " - is NOT constant\n";
return false;
}
bool is_const( int const &value )
{
std::cout << value << " - is constant\n";
return true;
}
bool main()
{
typedef ntuple< int, int, int, int, int > tuple_t;
typedef tuple_t::meta_index_apply< constify, -2 >::type const2_t;
const2_t const2( 0, 1, 2, 3, 4 );
std::cout << std::boolalpha;
CHECK( is_const( const2.at<0>() ) );
CHECK( is_const( const2.at<1>() ) );
CHECK( !is_const( const2.at<2>() ) );
CHECK( !is_const( const2.at<3>() ) );
CHECK( !is_const( const2.at<4>() ) );
return true;
}
Test Result: gcc34 Passed, msvc80 Passed, msvc71 Passed
Output
0 - is constant 1 - is constant 2 - is NOT constant 3 - is NOT constant 4 - is NOT constant