|
//https://gist.github.com/eral/4123759 |
|
|
|
#if defined(__INTEL_COMPILER) |
|
# include <cstring> |
|
#endif |
|
#if defined(__GNUC__) |
|
# include <cxxabi.h> |
|
#endif |
|
|
|
#include <string> |
|
#include <utility> |
|
#include <iterator> |
|
#include <algorithm> |
|
#include <iostream> |
|
#include <typeinfo> |
|
#include <cstddef> |
|
|
|
|
|
#if (0 < _MSC_VER) |
|
//VC++ 2012 2010 2008 2005 |
|
//const char *__cdecl utility::detail::typenameof_::typenameof<int>(int *) |
|
# define UTILITY_TYPENAMEOF_ANALYZE_DIRECT_INSERTION |
|
#elif defined(__INTEL_COMPILER) |
|
//ICC 13.0.1 |
|
//const char *utility::detail::typenameof_::typenameof(T *) [with T = int] |
|
# define UTILITY_TYPENAMEOF_ANALYZE_NOTE_ARGUMENT_ONLY |
|
#elif defined(__clang__) |
|
# if ((4 <= __clang_major__) || ((3 == __clang_major__) && (1 <= __clang_minor__))) |
|
//Clang 3.2 3.1 |
|
//const char *utility::detail::typenameof_::typenameof(T *) [T = int] |
|
# define UTILITY_TYPENAMEOF_ANALYZE_NOTE_ARGUMENT_ONLY |
|
# else |
|
//Clang 3.0 |
|
//const char *utility::detail::typenameof_::typenameof(int *) |
|
# define UTILITY_TYPENAMEOF_ANALYZE_DIRECT_INSERTION |
|
# endif |
|
#elif defined(__GNUC__) |
|
//GCC 4.8.0 4.7.2 4.6.3 4.5.3 4.4.7 |
|
//const char *utility::detail::typenameof_::typenameof(T*) [with T = int] |
|
# define UTILITY_TYPENAMEOF_ANALYZE_NOTE_ARGUMENT_ONLY |
|
#endif |
|
|
|
#if (0 < _MSC_VER) |
|
# define UTILITY_TYPENAMEOF_PRETTY_FUNCTION __FUNCSIG__ |
|
#else |
|
# define UTILITY_TYPENAMEOF_PRETTY_FUNCTION __PRETTY_FUNCTION__ |
|
#endif |
|
|
|
|
|
namespace utility { |
|
namespace detail { namespace typenameof_ { |
|
|
|
template <typename T> |
|
struct range { |
|
T begin; |
|
T end; |
|
range(T be, T en): begin(be), end(en) {} |
|
}; |
|
|
|
template <std::size_t N> |
|
class string : private string<N-1> { |
|
typedef string<N-1> super_type; |
|
char m_value; |
|
protected: |
|
string(const char *begin, const char *end): super_type(begin, end), m_value((begin+N-1 < end)? begin[N-1]: '\0') {} |
|
public: |
|
const char *get() { |
|
return reinterpret_cast<const char *>(this); |
|
} |
|
string(const range<const char *> &src): super_type(src.begin, src.end), m_value('\0') {} |
|
}; |
|
template <> |
|
class string<0> { |
|
protected: |
|
string(const char *, const char *) {} |
|
public: |
|
}; |
|
|
|
range<const char *> analyze(const char *begin, const char *end, char begin_mark, std::size_t begin_ofst, char end_mark, std::size_t end_ofst) { |
|
return range<const char *>(&*(std::find(begin, end, begin_mark) + begin_ofst) |
|
, &*std::find(std::reverse_iterator<const char *>(end) |
|
, std::reverse_iterator<const char *>(begin) |
|
, end_mark |
|
) + end_ofst |
|
); |
|
} |
|
|
|
#if defined(UTILITY_TYPENAMEOF_ANALYZE_DIRECT_INSERTION) |
|
template<std::size_t N> |
|
range<const char *> analyze(const char (&pretty_function)[N]) { |
|
return analyze(pretty_function, pretty_function + N, '(', 1, '*', 0); |
|
} |
|
#elif defined(UTILITY_TYPENAMEOF_ANALYZE_NOTE_ARGUMENT_ONLY) |
|
# if defined(__INTEL_COMPILER) |
|
range<const char *> analyze(const char *pretty_function) { |
|
std::size_t N = std::strlen(pretty_function) + 1; |
|
return analyze(pretty_function, pretty_function + N, '=', 2, ']', 0); |
|
} |
|
# else |
|
template<std::size_t N> |
|
range<const char *> analyze(const char (&pretty_function)[N]) { |
|
return analyze(pretty_function, pretty_function + N, '=', 2, ']', 0); |
|
} |
|
# endif |
|
#else |
|
range<const char *> analyze(const char *pretty_function) { |
|
std::size_t N = std::strlen(pretty_function) + 1; |
|
return range(pretty_function, pretty_function + N); |
|
} |
|
#endif |
|
|
|
template <typename T> |
|
const char *typenameof(T*) { |
|
#if defined(__INTEL_COMPILER) |
|
range<const char *> typename_range = analyze(UTILITY_TYPENAMEOF_PRETTY_FUNCTION); |
|
static std::string typename_string(typename_range.begin, typename_range.end); |
|
return typename_string.c_str(); |
|
#else |
|
range<const char *> typename_range = analyze(UTILITY_TYPENAMEOF_PRETTY_FUNCTION); |
|
static string<sizeof(UTILITY_TYPENAMEOF_PRETTY_FUNCTION)> typename_string(typename_range); |
|
return typename_string.get(); |
|
#endif |
|
} |
|
}} |
|
|
|
template <typename T> |
|
const char *typenameof() { |
|
return detail::typenameof_::typenameof<T>(0); |
|
} |
|
template <typename T> |
|
const char *typenameof(const T &) { |
|
return detail::typenameof_::typenameof<T>(0); |
|
} |
|
} |
|
|
|
#undef UTILITY_TYPENAMEOF_ANALYZE_DIRECT_INSERTION |
|
#undef UTILITY_TYPENAMEOF_ANALYZE_NOTE_ARGUMENT_ONLY |
|
#undef UTILITY_TYPENAMEOF_PRETTY_FUNCTION |
|
|
|
|
|
|
|
|
|
|
|
#if (0 < _MSC_VER) |
|
std::string demangle(const std::string &src) { |
|
return src; |
|
} |
|
#elif defined(__GNUC__) |
|
std::string demangle(const std::string &src) { |
|
int status; |
|
char *buf = abi::__cxa_demangle(src.c_str(), 0, 0, &status); |
|
std::string result(buf); |
|
free(buf); |
|
return result; |
|
} |
|
#else |
|
std::string demangle(const std::string &src) { |
|
return src; |
|
} |
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
namespace hage { namespace hige { |
|
template <typename T> |
|
class huge { |
|
public: |
|
class hege { |
|
public: |
|
template <typename U> |
|
struct hoge { |
|
void test() { |
|
std::cout << "|`::utility::typenameof()` |`\"" << ::utility::typenameof(this) << "\"`|" << std::endl; |
|
std::cout << "|`demangle(type_info::name())`|`\"" << demangle(typeid(this).name()) << "\"`|" << std::endl; |
|
} |
|
}; |
|
}; |
|
}; |
|
}} |
|
|
|
int main(void) |
|
{ |
|
std::cout << "|`::utility::typenameof<>` |`\"" << ::utility::typenameof<int>() << "\"`|" << std::endl; |
|
std::cout << "|`demangle(type_info::name())`|`\"" << demangle(typeid(int).name()) << "\"`|" << std::endl; |
|
|
|
{ |
|
typedef ::std::pair<int *, long> test_type; |
|
test_type instance; |
|
std::cout << "|`::utility::typenameof()` |`\"" << ::utility::typenameof(instance) << "\"`|" << std::endl; |
|
std::cout << "|`demangle(type_info::name())`|`\"" << demangle(typeid(test_type()).name()) << "\"`|" << std::endl; |
|
} |
|
|
|
{ |
|
typedef ::hage::hige::huge< ::std::size_t *>::hege::hoge< ::std::pair<int *, long> > test_type; |
|
std::cout << "|`::utility::typenameof<>` |`\"" << ::utility::typenameof<test_type>() << "\"`|" << std::endl; |
|
std::cout << "|`demangle(type_info::name())`|`\"" << demangle(typeid(test_type).name()) << "\"`|" << std::endl; |
|
|
|
test_type instance; |
|
instance.test(); |
|
} |
|
|
|
return 0; |
|
} |
ICC 13.0 に取り敢えず対応。
コンパイルタイム時に文字長が取れないので
std::strlen
を使っています。