#include <iostream>
#include <fstream>

class arg_list
{
public:
	arg_list( int first, int last ) : first_( first ), last_( last ) {}
	
	int first_;
	int last_;
};

template< class Char_Type, class Traits >
std::basic_ostream< Char_Type, Traits > & operator <<( std::basic_ostream< Char_Type, Traits > & out, const arg_list &a )
{
	for( int arg = a.first_; arg != a.last_; ++arg )
	{
		out << " T" << arg;
		if( arg == a.last_ - 1 )
		{
			out << " ";
		}
		else
		{
			out << ",";
		}
	}
	return out;
}

class macro_arg_list : public arg_list
{
public:
	macro_arg_list( int first, int last ) : arg_list( first, last ) {}
};

template< class Char_Type, class Traits >
std::basic_ostream< Char_Type, Traits > & operator <<( std::basic_ostream< Char_Type, Traits > & out, const macro_arg_list &a )
{
	if( a.first_ != a.last_ )
	{
		out << "(";

		out << static_cast< const arg_list & >( a );
		
		out << ")";
	}
	return out;
}

int main()
{
	const int max_args = 50;
	
	std::ofstream out( "typelistext.hpp" );
	out << "#ifdef BOOST_HAS_TYPE_LIST_EXTENSION" << std::endl;
	
	out << "#  define TYPELIST_0 type_list[]" << std::endl;
	
	for( int arg_count = 1; arg_count != max_args + 1; ++arg_count )
	{
		out << "#  define TYPELIST_" << arg_count << macro_arg_list( 0, arg_count ) << " \\" << std::endl;
		out << "      type_list[" << arg_list( 0, arg_count ) << "]" << std::endl;
	}

	out << "#  define TYPELIST_0_T( Tail ) Tail" << std::endl;
	
	for( int arg_count = 1; arg_count != max_args + 1; ++arg_count )
	{
		out << "#  define TYPELIST_" << arg_count << "_T(" << arg_list( 0, arg_count ) << ", Tail ) \\" << std::endl;
		out << "      type_list[" << arg_list( 0, arg_count ) << "| Tail ]" << std::endl;
	}
	
	out << "#else" << std::endl;
	
	out << "#  define TYPELIST_0 ::boost::loki::null_typelist" << std::endl;
	
	for( int arg_count = 1; arg_count != max_args + 1; ++arg_count )
	{
		out << "#  define TYPELIST_" << arg_count << macro_arg_list( 0, arg_count ) << " \\" << std::endl;
		out << "      ::boost::loki::type_list< T0, TYPELIST_" << arg_count - 1 << macro_arg_list( 1, arg_count ) << " >" << std::endl;
	}

	out << "#  define TYPELIST_0_T( Tail ) Tail" << std::endl;
	
	for( int arg_count = 1; arg_count != max_args + 1; ++arg_count )
	{
		out << "#  define TYPE_LIST_" << arg_count << "_T(" << arg_list( 0, arg_count + 1 ) << ", Tail ) \\" << std::endl;
		out << "      ::boost::loki::type_list< T0, TYPELIST_" << arg_count - 1 << "_T(" << arg_list( 1, arg_count + 1 ); 
		if( arg_count != 1 )
			out << ",";
		out << " Tail ) >" << std::endl;
	}
	
	out << "#endif // BOOST_HAS_TYPE_LIST_EXTENSION" << std::endl;
	return 0;
}


