Garciat
9/22/2013 - 7:35 AM

tuple_explode.cpp

/*

La primera idea que se me vino a la mente para
http://channel9.msdn.com/Events/GoingNative/2013/The-Way-of-the-Exploding-Tuple

No recomendaria su uso, pero es otra forma de atacar al reto.

*/
#include <cstring>
#include <tuple>
#include <type_traits>
#include <iostream>

template <unsigned... Nums>
struct stat_seq { };

template <unsigned... Nums>
struct stat_seq_builder;

template <unsigned... Nums>
struct stat_seq_builder<0, Nums...> {
	typedef stat_seq<0, Nums...> type;
};

template <unsigned I, unsigned... Nums>
struct stat_seq_builder<I, Nums...>
	: stat_seq_builder<I - 1, I, Nums...> { };

template <typename Func, typename... Ts, unsigned... Nums>
auto explode_helper(Func&& f, const std::tuple<Ts...>& tup, stat_seq<Nums...>)
	-> typename std::result_of<Func (Ts...)>::type
{
	return f(std::get<Nums>(tup)...);
}

template <typename Func, typename... Ts>
auto explode(Func&& f, const std::tuple<Ts...>& tup)
	-> typename std::result_of<Func (Ts...)>::type
{
	return explode_helper(std::forward<Func>(f), tup,
			typename stat_seq_builder<sizeof...(Ts) - 1>::type());
}

int f(int a, double b, const char* c) {
	return a + (int)b + std::strlen(c);
}

int main() {
	auto t1 = std::make_tuple(1, 4.2, "hello");
	
	std::cout << explode(f, t1) << std::endl;
}