#include <iostream>
#include <tuple>
#include <typeinfo>

template <typename T>
struct function_traits;

template <typename T_Ret, typename ...T_Args>
struct function_traits<T_Ret(T_Args...)> {
	// Number of arguments.
	enum { arity = sizeof...(T_Args) };
	// Argument types.
	template <size_t i>
	struct args {
		using type
			= typename std::tuple_element<i, std::tuple<T_Args...>>::type;
	};
};

int main() {
	using Arg0 = function_traits<int(float)>::args<0>::type;
	//using Arg1 = function_traits<int(float)>::args<1>::type; // Error, should be void.
	
	std::cout << typeid(Arg0).name() << std::endl;
	//std::cout << typeid(Arg1).name() << std::endl;
}
