#include
#include
#include
#include
#define FUNC_EXTRACT_VARIABLES(begin_skip, end_skip) \
namespace eular { \
namespace detail { \
static const uint32_t skip_size_at_begin = begin_skip; \
static const uint32_t skip_size_at_end = end_skip; \
} \
}
#define COMPILER_MSVC 1
#define COMPILER_GNUC 2
#define COMPILER_CLANG 3
#define COMPILER_APPLECLANG 4
#if defined( __clang__ )
#if defined __apple_build_version__
#define COMPILER_TYPE COMPILER_APPLECLANG
#else
#define COMPILER_TYPE COMPILER_CLANG
#endif
#elif defined( __GNUC__ )
#define COMPILER_TYPE COMPILER_GNUC
#elif defined( _MSC_VER )
#define COMPILER_TYPE COMPILER_MSVC
#else
#error "Unknown compiler."
#endif
#if COMPILER_TYPE == COMPILER_MSVC
// strlen("const char *__cdecl eular::detail::type_name<"), strlen(">(void)")
FUNC_EXTRACT_VARIABLES(45, 7)
#elif COMPILER_TYPE == COMPILER_GNUC
// strlen("const char* eular::detail::type_name() [with T = "), strlen("]")
FUNC_EXTRACT_VARIABLES(49, 1)
#elif COMPILER_TYPE == COMPILER_CLANG || COMPILER_TYPE == COMPILER_APPLECLANG
// sizeof("const char* eular::detail::type_name() [T = "), sizeof("]")
FUNC_EXTRACT_VARIABLES(44, 1)
#else
#error "This compiler does not supported extracting a function signature via preprocessor!"
#endif
namespace eular {
namespace detail {
const char* extract_type_signature(const char *signature)
{
return &signature[eular::detail::skip_size_at_begin];
}
template<typename T>
const char *type_name()
{
return extract_type_signature(
#if COMPILER_TYPE == COMPILER_MSVC
__FUNCSIG__
#elif COMPILER_TYPE == COMPILER_GNUC
__PRETTY_FUNCTION__
#elif COMPILER_TYPE == COMPILER_CLANG || COMPILER_TYPE == COMPILER_APPLECLANG
__PRETTY_FUNCTION__
#else
#error "Don't know how the extract type signatur for this compiler!"
#endif
);
}
uint32_t get_size(const char *s)
{
return (std::char_traits<char>::length(s) - eular::detail::skip_size_at_end);
}
template<typename T>
std::string get_type_name()
{
return std::string(type_name<T>(), get_size(type_name<T>()));
}
} // namespace detail
} // namespace eular
int main()
{
printf("[%s]\n", eular::detail::get_type_name<std::string>().c_str());
printf("[%s]\n", eular::detail::get_type_name<std::wstring>().c_str());
printf("[%s]\n", eular::detail::get_type_name<std::size_t>().c_str());
printf("[%s]\n", eular::detail::get_type_name<std::int32_t>().c_str());
return 0;
}
输出
[class std::basic_string]
[class std::basic_string<wchar_t,struct std::char_traits,class std::allocator >]
[unsigned int]
[int]