For example:
int a = 12;
cout << typeof(a) << endl;
Expected output:
int
Another take on @康桓瑋's answer (originally ), making less assumptions about the prefix and suffix specifics, and inspired by @Val's answer - but without polluting the global namespace; without any conditions; and hopefully easier to read.
The popular compilers provide a macro with the current function's signature. Now, functions are templatable; so the signature contains the template arguments. So, the basic approach is: Given a type, be in a function with that type as a template argument.
Unfortunately, the type name is wrapped in text describing the function, which is different between compilers. For example, with GCC, the signature of template
with type double
is: int foo() [T = double]
.
So, how do you get rid of the wrapper text? @HowardHinnant's solution is the shortest and most "direct": Just use per-compiler magic numbers to remove a prefix and a suffix. But obviously, that's very brittle; and nobody likes magic numbers in their code. Instead, you get the macro value for a type with a known name, you can determine what prefix and suffix constitute the wrapping.
#include
template constexpr std::string_view type_name();
template <>
constexpr std::string_view type_name()
{ return "void"; }
namespace detail {
using type_name_prober = void;
template
constexpr std::string_view wrapped_type_name()
{
#ifdef __clang__
return __PRETTY_FUNCTION__;
#elif defined(__GNUC__)
return __PRETTY_FUNCTION__;
#elif defined(_MSC_VER)
return __FUNCSIG__;
#else
#error "Unsupported compiler"
#endif
}
constexpr std::size_t wrapped_type_name_prefix_length() {
return wrapped_type_name().find(type_name());
}
constexpr std::size_t wrapped_type_name_suffix_length() {
return wrapped_type_name().length()
- wrapped_type_name_prefix_length()
- type_name().length();
}
} // namespace detail
template
constexpr std::string_view type_name() {
constexpr auto wrapped_name = detail::wrapped_type_name();
constexpr auto prefix_length = detail::wrapped_type_name_prefix_length();
constexpr auto suffix_length = detail::wrapped_type_name_suffix_length();
constexpr auto type_name_length = wrapped_name.length() - prefix_length - suffix_length;
return wrapped_name.substr(prefix_length, type_name_length);
}
See it on GodBolt. This should be working with MSVC as well.