Created
February 3, 2013 17:09
-
-
Save socantre/4702626 to your computer and use it in GitHub Desktop.
"human readable" C++ types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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