Can I obtain C++ type names in a constexpr way?
c++, c++14, compile-time, constexpr, reflection
Solution
Edit: Updated based on this answer to the non-constexpr-specific question; it is the result of refinements by several people including @HowardHinnant, @康桓瑋 @Val and myself.
The language standard does not - to my knowledge - provide any facility for obtaining type names. So, we resort to compiler-specific approaches. This works with GCC, clang and MSVC.
#include <string_view>
// If you can't use C++17's standard library, you'll need to use the GSL
// string_view or implement your own struct (which would not be very difficult,
// since we only need a few methods here)
template <typename T> constexpr std::string_view type_name();
template <>
constexpr std::string_view type_name<void>()
{ return "void"; }
namespace detail {
using type_name_prober = void;
template <typename T>
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<type_name_prober>().find(type_name<type_name_prober>());
}
constexpr std::size_t wrapped_type_name_suffix_length() {
return wrapped_type_name<type_name_prober>().length()
- wrapped_type_name_prefix_length()
- type_name<type_name_prober>().length();
}
} // namespace detail
template <typename T>
constexpr std::string_view type_name() {
constexpr auto wrapped_name = detail::wrapped_type_name<T>();
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);
}
Problem
I would like to use the name of a type at compile time. For example, suppose I've written: ``` constexpr size_t my_strlen(const char* s) { const char* cp = s; while(*cp != '\0') { cp++; }; return cp - s; } ``` and now I want to have: ``` template <typename T> constexpr auto type_name_length = my_strlen(typeid(T).name()); ``` But alas, `typeid(T).name()` is just `const char*`, not constexpr... is there some other, constexpr way to get a type's name?