#include <iostream>
#include <tuple>
template<typename T> struct FunctionSignatureParser; // Must declare a primary template with a missing implementation
template<typename Result, typename...Args> struct FunctionSignatureParser<Result(Args...)>
{
	using return_type = Result;
	using args_tuple = std::tuple<Args...>;
	template <size_t i> struct arg
	{
		typedef typename std::tuple_element<i, args_tuple>::type type;
	};
};
short square(char x) { // 8-bit integer as input, 16-bit integer as output
    return short(x)*short(x);
}
int main() {
        char answer = 42;
        static_assert(std::is_same<char, FunctionSignatureParser<decltype(square)>::arg<0>::type>::value, "Function 'square' does not use an argument of type 'char'");
        static_assert(std::is_same<short, FunctionSignatureParser<decltype(square)>::return_type>::value, "Function 'square' does not return a value of type 'short'");
        short sqrAnswer = square(answer);
        std::cout << "The square of " << +answer << " is " << +sqrAnswer << std::endl;
        return 0;
}