#include <iostream>
#include <type_traits>
#include <typeinfo>

template<typename ...Args>
struct holder;

namespace
{
	template<typename ...Args>
	struct print_helper;

	template<typename Arg, typename ...Args>
	struct print_helper<Arg, Args...>
	{
		static void print()
		{
			std::cout << typeid(Arg).name() << ", ";
			print_helper<Args...>::print();
		}
	};

	template<typename Arg>
	struct print_helper<Arg>
	{
		static void print()
		{
			std::cout << typeid(Arg).name() << std::endl;
		}
	};

	template<typename ...Args>
	struct print_helper<holder<Args...>>
	{
		static void print()
		{
			print_helper<Args...>::print();
		}
	};
}

template<typename ...Args>
void print()
{
	print_helper<Args...>::print();
}

namespace
{
	template<typename Applier, typename T>
	struct apply_helper
	{
		typedef typename Applier::template apply<T>::type type;
	};

	template<typename Applier, typename ... Args>
	struct transform_helper
	{
		typedef holder<typename apply_helper<Applier, Args>::type...> type;
	};
}

template<typename Applier, typename ... Args>
struct transform
{
	typedef typename transform_helper<Applier, Args...>::type type;
};

template<typename Applier, typename ... Args>
struct transform<Applier, holder<Args...>>
{
	typedef typename transform<Applier, Args...>::type type;
};

namespace
{
	template<typename T>
	struct type_replacer_helper
	{
		typedef T type;
	};

	template<>
	struct type_replacer_helper<int>
	{
		typedef float type;
	};
}

struct type_replacer
{
	template<typename T>
	struct apply
	{
		typedef typename type_replacer_helper<T>::type type;
	};
};

using namespace std;

int main() {
	
	typedef holder<int, int, char, int, float> t1;
	typedef typename transform<type_replacer, t1>::type t2;
	
	print<t1>();
	print<t2>();
	
	return 0;
}