#include <iostream>
#include <tuple>
#include <cassert>

template<std::size_t ...Indices>
struct index_tuple{
};
template<typename Left,typename Right>
struct concat_index_tuple;
template<std::size_t ...Lefts,std::size_t ...Rights>
struct concat_index_tuple<index_tuple<Lefts...>,index_tuple<Rights...>>{
	using type = index_tuple<Lefts...,Rights...>;
};
template<std::size_t Beg,std::size_t End>
struct make_index_tuple{
	using type = typename concat_index_tuple<
					index_tuple<Beg>,
					typename make_index_tuple<Beg + 1,End>::type
	>::type;
};
template<std::size_t End>
struct make_index_tuple<End,End>{
	using type = index_tuple<End>;
};
template<typename Tuple>
struct tuple_index;
template<typename ...Ts>
struct tuple_index<std::tuple<Ts...>>{
	using type = typename make_index_tuple<0,sizeof...(Ts) - 1>::type;
};

template<typename T>
void output_impl(std::size_t s,T const& x){
	assert(s == 0);
	std::cout << x << std::endl;
}
template<typename T,typename ...Us>
void output_impl(std::size_t s,T const& x,Us const& ...xs){
	if(s){
		output_impl(s - 1,xs...);
	}
	else{
		std::cout << x << std::endl;
	}
}
template<std::size_t ...Indices,typename ...Types>
void output_unpack(std::size_t s,std::tuple<Types...> const& t,index_tuple<Indices...>){
	output_impl(s,std::get<Indices>(t)...);
}
template<typename Tuple>
void output(std::size_t s,Tuple const& t){
	output_unpack(s,t,typename tuple_index<Tuple>::type{});
}

int main() {
	int i;
	std::cout << "Enter index" << std::endl;
	std::cin >> i;
	output(i,std::make_tuple("a",42,3.14f,&i));
	return 0;
}