Printing a variable's type and value is fairly simple. But variable names don't exist at runtime, so the only way to obtain a variable's name as a string, without hard-coding it, is to use a macro at compile-time. Macros have a feature to stringify tokens.
Try something like this (sorry, this is from memory, I can't get to a compiler at the moment, I'll update this later today):
#include <iomanip>
#include <typeinfo>
#include <type_traits>
template <typename T>
std::string getTypeName()
{
    // TODO: to get a more human-readable output, use
    // if-constexpr, or template specialization, or one
    // of the solutions from https://stackoverflow.com/q/281818/65863... 
    return typeid(T).name();
} 
template<typename T>
std::string stringify(const T& param)
{
    std::ostringstream oss;
    if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, char*> || std::is_same_v<T, const char*>)
        oss << std::quoted(param);
    else
        oss << param;
    return oss.str();
}
template <typename T>
void doLog(int num, std::string_view name, const T& value)
{
    std::cout << "input" << num << ":" << std::endl
        << "\ttype: " << getTypeName<T>() << "," << std::endl
        << "\tname: " << #param << "," << std::endl
        << "\tvalue: " << stringify(param) << "," << std::endl;
} 
#define LOG(num, param) doLog(num, #param, param)
void func(std::string& input_name, const int n){
    LOG(1, input_name)
    LOG(2, n)
}