Skip to content

Instantly share code, notes, and snippets.

@DieHertz
Last active May 27, 2016 22:58
Show Gist options
  • Save DieHertz/8951647 to your computer and use it in GitHub Desktop.
Save DieHertz/8951647 to your computer and use it in GitHub Desktop.
#ifndef type_name_h
#define type_name_h
#include <string>
#include <type_traits>
#include <typeinfo>
template<typename... T> struct type_name {
static std::string get() { return {}; }
};
template<typename T1, typename T2, typename... T> struct type_name<T1, T2, T...> {
static std::string get() {
return type_name<T1>::get() + ", " + type_name<T2>::get()
+ (sizeof...(T) ? (", " + type_name<T...>::get()) : "");
}
};
template<typename T> struct type_name<T> {
static std::string get() {
return typeid(T).name();
}
};
template<typename T> struct type_name<T&>{
static std::string get() {
return type_name<T>::get() + "&";
}
};
template<typename T> struct type_name<T&&>{
static std::string get() {
return type_name<T>::get() + "&&";
}
};
template<typename T> struct type_name<const T> {
static std::string get() {
return "const " + type_name<T>::get();
}
};
template<typename T> struct type_name<T* const> {
static std::string get() {
return type_name<T>::get() + "* const";
}
};
template<typename T> struct type_name<volatile T> {
static std::string get() {
return type_name<T>::get() + " volatile";
}
};
template<typename T> struct type_name<T*> {
static std::string get() {
return type_name<T>::get() + "*";
}
};
template <typename T, std::size_t N> struct type_name<T[N]> {
static std::string get() {
return type_name<T>::get() + "[" + std::to_string(N) + "]";
}
};
template <typename T> struct type_name<T[]> {
static std::string get() {
return type_name<T>::get() + "[]";
}
};
template <typename T, std::size_t N> struct type_name<const T[N]> {
static std::string get() {
return "const " + type_name<T>::get() + "[" + std::to_string(N) + "]";
}
};
template <typename T> struct type_name<const T[]> {
static std::string get() {
return "const " + type_name<T>::get() + "[]";
}
};
/** \brief function type
*/
template <typename T, typename... Args> struct type_name<T(Args...)> {
static std::string get() {
return type_name<T>::get() + "(" + type_name<Args...>::get() + ")";
}
};
/** \brief function pointer type
*/
template <typename T, typename... Args> struct type_name<T(*)(Args...)> {
static std::string get() {
return type_name<T>::get() + " (*)(" + type_name<Args...>::get() + ")";
}
};
/** \brief member pointer
*/
template <typename T, class U> struct type_name<T U::*> {
static std::string get() {
return type_name<T>::get() + " " + type_name<U>::get() + "::*";
}
};
/** \brief member function pointer
*/
template <typename T, class U, typename... Args> struct type_name<T (U::*)(Args...)> {
static std::string get() {
return type_name<T>::get() + " (" + type_name<U>::get() + "::*)(" + type_name<Args...>::get() + ")";
}
};
/** \brief const-qualified member function pointer
*/
template <typename T, class U, typename... Args> struct type_name<T (U::*)(Args...) const> {
static std::string get() {
return type_name<T>::get() + " (" + type_name<U>::get() + "::*)(" + type_name<Args...>::get() + ") const";
}
};
/** \brief lvalue-ref-qualified member function pointer
*/
template <typename T, class U, typename... Args> struct type_name<T (U::*)(Args...) &> {
static std::string get() {
return type_name<T>::get() + " (" + type_name<U>::get() + "::*)(" + type_name<Args...>::get() + ") &";
}
};
/** \brief rvalue-ref-qualified member function pointer
*/
template <typename T, class U, typename... Args> struct type_name<T (U::*)(Args...) &&> {
static std::string get() {
return type_name<T>::get() + " (" + type_name<U>::get() + "::*)(" + type_name<Args...>::get() + ") &&";
}
};
template<template <class...> class T, class... U> struct type_name<T<U...>> {
static std::string get() {
return std::string{typeid(T<U...>).name()} + "<" + type_name<U...>::get() + ">";
}
};
#define SPECIALIZE_TYPE_NAME(type) template<> struct type_name<type> {\
static std::string get() { return #type; } \
};
SPECIALIZE_TYPE_NAME(void)
SPECIALIZE_TYPE_NAME(char)
SPECIALIZE_TYPE_NAME(signed char)
SPECIALIZE_TYPE_NAME(unsigned char)
SPECIALIZE_TYPE_NAME(short)
SPECIALIZE_TYPE_NAME(unsigned short)
SPECIALIZE_TYPE_NAME(int)
SPECIALIZE_TYPE_NAME(unsigned int)
SPECIALIZE_TYPE_NAME(long)
SPECIALIZE_TYPE_NAME(unsigned long)
SPECIALIZE_TYPE_NAME(long long)
SPECIALIZE_TYPE_NAME(unsigned long long)
SPECIALIZE_TYPE_NAME(bool)
SPECIALIZE_TYPE_NAME(float)
SPECIALIZE_TYPE_NAME(double)
SPECIALIZE_TYPE_NAME(long double)
#undef SPECIALIZE_TYPE_NAME
#endif /* type_name_h */
@DieHertz
Copy link
Author

    // sample code
    const int& a = 0;
    cout << type_name<decltype(a)>::get() << endl;
    cout << type_name<const void>::get() << endl;
    cout << type_name<char>::get() << endl;
    cout << type_name<signed char>::get() << endl;
    cout << type_name<unsigned char>::get() << endl;
    cout << type_name<const void* const * const **>::get() << endl;
    cout << type_name<decltype(&Foo::bar)>::get() << endl;
    cout << type_name<decltype(&Foo::baz)>::get() << endl;
    cout << type_name<decltype(&Foo::baz2)>::get() << endl;
    cout << type_name<decltype(&Foo::baz3)>::get() << endl;
    cout << type_name<decltype(f)>::get() << endl;
    cout << type_name<decltype(&f)>::get() << endl;
    cout << type_name<std::string>::get() << endl;
    cout << type_name<const void*>::get() << endl;
    cout << type_name<int[2]>::get() << endl;
    cout << type_name<int[]>::get() << endl;
    cout << type_name<const int[2]>::get() << endl;
    cout << type_name<const int[]>::get() << endl;

Output:

hertz$ g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.2
Thread model: posix

hertz$ ./a.out
const int&
const void
char
signed char
unsigned char
const void* const* const**
int 3Foo::*
void (3Foo::*)(int) const
void (3Foo::*)(int) &
void (3Foo::*)(int) &&
void(int, char, int*, const NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE<char, NSt3__111char_traitsIcEE<char>, NSt3__19allocatorIcEE<char>>&)
void ( *)(int, char, int*, const NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE<char, NSt3__111char_traitsIcEE<char>, NSt3__19allocatorIcEE<char>>&)
NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE<char, NSt3__111char_traitsIcEE<char>, NSt3__19allocatorIcEE<char>>
const void*
int[2]
int[]
const int[2]
const int[]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment