获取模板类型字符串

#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,class std::allocator >]
[unsigned int]
[int]

参考

你可能感兴趣的:(c++)