Last active
October 13, 2015 02:18
-
-
Save eral/4123759 to your computer and use it in GitHub Desktop.
typenameof
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
//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; | |
} |
戻り値をstd::string
からconst char *
に変更。
これに伴いTMPにて文字長が取得出来無いICCに於いて、関数内static変数てにメモリアロケートが走ると言う酷い構成に為りました。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
__PRETTY_FUNCTION__
const char *utility::detail::typenameof_::typenameof(T*) [with T = int]
__PRETTY_FUNCTION__
const char *utility::detail::typenameof_::typenameof(T *) [T = int]
const char *utility::detail::typenameof_::typenameof(int *)
__PRETTY_FUNCTION__
const char *utility::detail::typenameof_::typenameof(T *) [with T = int]
__FUNCSIG__
const char *__cdecl utility::detail::typenameof_::typenameof<int>(int *)