Skip to content

Instantly share code, notes, and snippets.

@socantre
Created February 3, 2013 17:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save socantre/4702626 to your computer and use it in GitHub Desktop.
Save socantre/4702626 to your computer and use it in GitHub Desktop.
"human readable" C++ types
#include <string>
#include <iostream> // cout
#include <cstdint> // intmax_t
#include <typeinfo>
#include <memory> // unique_ptr
#include <cstdlib> // free
#include <cxxabi.h> // __cxa_demangle
extern "C" template<typename T> using c_linkage = T;
template<typename T> struct type_name {
static std::string get() {
int status;
std::unique_ptr<char,c_linkage<void(*)(void*)>> name{__cxxabiv1::__cxa_demangle(typeid(T).name(),nullptr,0,&status),std::free};
if (0!=status) {
throw std::runtime_error("__cxa_demangle failed");
}
return name.get();
}
};
#define TYPE_NAME(T) template<> struct type_name<T> { static std::string get() { return #T; } }
TYPE_NAME(char);
TYPE_NAME(unsigned char);
TYPE_NAME(signed char);
TYPE_NAME(char16_t);
TYPE_NAME(char32_t);
TYPE_NAME(bool);
TYPE_NAME(unsigned int);
TYPE_NAME(int);
TYPE_NAME(unsigned short);
TYPE_NAME(unsigned long);
TYPE_NAME(unsigned long long);
TYPE_NAME(long);
TYPE_NAME(long long);
TYPE_NAME(short);
TYPE_NAME(wchar_t);
TYPE_NAME(float);
TYPE_NAME(double);
TYPE_NAME(long double);
TYPE_NAME(void);
#undef TYPE_NAME
template<typename T> struct type_name<T*> {
static std::string get() { return "pointer to " + type_name<T>::get(); }
};
template<typename T> struct type_name<T&> {
static std::string get() { return "reference to " + type_name<T>::get(); }
};
template<typename T> struct type_name<T&&> {
static std::string get() { return "rvalue reference to " + type_name<T>::get(); }
};
template<typename T> struct type_name<T const> {
static std::string get() { return "const " + type_name<T>::get(); }
};
template<typename T> struct type_name<T volatile> {
static std::string get() { return "volatile " + type_name<T>::get(); }
};
template<typename T> struct type_name<T const volatile> {
static std::string get() { return "const volatile " + type_name<T>::get(); }
};
template<typename T, typename C> struct type_name<T C::*> {
static std::string get() { return "pointer to " + type_name<C>::get() + " member " + type_name<T>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...)> {
static std::string get() { return "pointer to " + type_name<C>::get() + " member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) &> {
static std::string get() { return "pointer to " + type_name<C>::get() + " reference member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) &&> {
static std::string get() { return "pointer to " + type_name<C>::get() + " rvalue reference member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) const > {
static std::string get() { return "pointer to " + type_name<C>::get() + " const member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) volatile > {
static std::string get() { return "pointer to " + type_name<C>::get() + " volatile member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) const volatile> {
static std::string get() { return "pointer to " + type_name<C>::get() + " const volatile member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) const &> {
static std::string get() { return "pointer to " + type_name<C>::get() + " const reference member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) volatile &> {
static std::string get() { return "pointer to " + type_name<C>::get() + " volatile reference member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) const volatile &> {
static std::string get() { return "pointer to " + type_name<C>::get() + " const volatile reference member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) const &&> {
static std::string get() { return "pointer to " + type_name<C>::get() + " const rvalue reference member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) volatile &&> {
static std::string get() { return "pointer to " + type_name<C>::get() + " volatile rvalue reference member " + type_name<RetT(Args...)>::get(); }
};
template<typename C, typename RetT, typename... Args> struct type_name<RetT (C::*)(Args...) const volatile &&> {
static std::string get() { return "pointer to " + type_name<C>::get() + " const volatile rvalue reference member " + type_name<RetT(Args...)>::get(); }
};
template<typename T, std::intmax_t N> struct type_name<T[N]> {
static std::string get() { return "array of " + std::to_string(N) + " " + type_name<T>::get(); }
};
template<typename T, std::intmax_t N> struct type_name<T const [N]> {
static std::string get() { return "const " + type_name<T[N]>::get(); }
};
template<typename T, std::intmax_t N> struct type_name<T volatile [N]> {
static std::string get() { return "volatile " + type_name<T[N]>::get(); }
};
template<typename T, std::intmax_t N> struct type_name<T const volatile [N]> {
static std::string get() { return "const volatile " + type_name<T[N]>::get(); }
};
template<typename T> struct type_name<T[]> {
static std::string get() { return "array of unknown bound of " + type_name<T>::get(); }
};
template<typename T> struct type_name<T const []> {
static std::string get() { return "const " + type_name<T[]>::get(); }
};
template<typename T> struct type_name<T volatile []> {
static std::string get() { return "volatile " + type_name<T[]>::get(); }
};
template<typename T> struct type_name<T const volatile []> {
static std::string get() { return "const volatile " + type_name<T[]>::get(); }
};
template<typename... Args> struct type_name_list { static std::string get() { return ""; } };
template<typename Arg> struct type_name_list<Arg> { static std::string get() { return type_name<Arg>::get(); } };
template<typename Arg, typename... Args> struct type_name_list<Arg,Args...> { static std::string get() { return type_name<Arg>::get() + ", " + type_name_list<Args...>::get(); } };
template<typename RetT, typename... Args> struct type_name<RetT(Args...)> {
static std::string get() { return "function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) &> {
static std::string get() { return "illegal reference function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) &&> {
static std::string get() { return "illegal rvalue reference function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) const> {
static std::string get() { return "illegal const function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) const &> {
static std::string get() { return "illegal const reference function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) const &&> {
static std::string get() { return "illegal const rvalue reference function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) volatile> {
static std::string get() { return "illegal volatile function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) volatile &> {
static std::string get() { return "illegal volatile reference function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) volatile &&> {
static std::string get() { return "illegal volatile rvalue reference function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) const volatile> {
static std::string get() { return "illegal const volatile function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) const volatile &> {
static std::string get() { return "illegal const volatile reference function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
template<typename RetT, typename... Args> struct type_name<RetT(Args...) const volatile &&> {
static std::string get() { return "illegal const volatile rvalue reference function taking (" + type_name_list<Args...>::get() + ") and returning " + type_name<RetT>::get(); }
};
int main() {
std::cout << type_name<std::string>::get() << '\n';
std::cout << type_name<int>::get() << '\n';
std::cout << type_name<char*>::get() << '\n';
std::cout << type_name<unsigned short&&>::get() << '\n';
std::cout << type_name<double&&>::get() << '\n';
std::cout << type_name<long long const>::get() << '\n';
std::cout << type_name<volatile unsigned>::get() << '\n';
std::cout << type_name<float const volatile>::get() << '\n';
struct S {};
std::cout << type_name<int const S::*>::get() << '\n';
std::cout << type_name<void (S::*)(int)>::get() << '\n';
std::cout << type_name<void (S::*)(int) const >::get() << '\n';
std::cout << type_name<void (S::*)(int) volatile >::get() << '\n';
std::cout << type_name<void (S::*)(int) const volatile>::get() << '\n';
std::cout << type_name<void (S::*)(int) &>::get() << '\n';
std::cout << type_name<void (S::*)(int) const &>::get() << '\n';
std::cout << type_name<void (S::*)(int) volatile &>::get() << '\n';
std::cout << type_name<void (S::*)(int) const volatile &>::get() << '\n';
std::cout << type_name<void (S::*)(int) &&>::get() << '\n';
std::cout << type_name<void (S::*)(int) const &&>::get() << '\n';
std::cout << type_name<void (S::*)(int) volatile &&>::get() << '\n';
std::cout << type_name<void (S::*)(int) const volatile &&>::get() << '\n';
std::cout << type_name<wchar_t [1]>::get() << '\n';
std::cout << type_name<wchar_t const [2]>::get() << '\n';
std::cout << type_name<wchar_t volatile [10]>::get() << '\n';
std::cout << type_name<wchar_t const volatile [10]>::get() << '\n';
std::cout << type_name<wchar_t []>::get() << '\n';
std::cout << type_name<wchar_t const []>::get() << '\n';
std::cout << type_name<wchar_t volatile []>::get() << '\n';
std::cout << type_name<wchar_t const volatile []>::get() << '\n';
std::cout << type_name<void (void)>::get() << '\n';
enum X {};
std::cout << type_name<void volatile const *(* volatile (&(std::string::*)(int,X,double,long long,int * const) const volatile &&))[10]>::get() << '\n';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment