#include <iostream>
#include <typeinfo>
#include <memory>
#include <cxxabi.h>
#include <string>

template <typename T> std::string TypeName(T) {

    auto name = typeid(T).name();
    int status = 0;

    std::unique_ptr<char, void(*)(void*)> res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };

    return ((status == 0) ? res.get() : name);
}


int main()
{
	int i = 0;
	float f = 0.f;

	std::cout << TypeName(i) << '\n'; // int
	std::cout << TypeName(f) << '\n'; // float, so far so good

	std::cout << TypeName(&i) << '\n'; // int *
	std::cout << TypeName(&f) << '\n'; // float *, as expected

	const int ci = 1;
	const float cf = 1.f;

	std::cout << TypeName(ci) << '\n'; // int!
	std::cout << TypeName(cf) << '\n'; // float!

	int &ri = i;
	float &rf = f;

	std::cout << TypeName(ri) << '\n'; // int!
	std::cout << TypeName(rf) << '\n'; // float!

	const int &cri = i;
	const float &crf = f;

	std::cout << TypeName(cri) << '\n'; // int!
	std::cout << TypeName(crf) << '\n'; // float!

	return 0;
}