I need to print the name of a class such as
template<typename... Args>
struct S{};
Using typeid(S<int,std::vector<double>>).name()
its fairly simple to print something representative. With boost demangle it might even be readable on gcc.
Is there any way to get the name so the name is the same between different compilers?
Not really. The mangled name is, in general, compiler-specific. See the table titled "How different compilers mangle the same functions" on Wikipedia
#include <string_view>
#include <vector>
template<typename... Args>
struct S{};
template <typename T>
constexpr auto type_name()
{
std::string_view name, prefix, suffix;
#ifdef __clang__
name = __PRETTY_FUNCTION__;
prefix = "auto type_name() [T = ";
suffix = "]";
#elif defined(__GNUC__)
name = __PRETTY_FUNCTION__;
prefix = "constexpr auto type_name() [with T = ";
suffix = "]";
#elif defined(_MSC_VER)
name = __FUNCSIG__;
prefix = "auto __cdecl type_name<";
suffix = ">(void)";
#endif
name.remove_prefix(prefix.size());
name.remove_suffix(suffix.size());
return name;
}
int main()
{
#ifdef _MSC_VER
static_assert(type_name<S<int, std::vector<double>>>() == "struct S<int,class std::vector<double,class std::allocator<double> > >");
#else
static_assert(type_name<S<int, std::vector<double>>>() == "S<int, std::vector<double, std::allocator<double> > >");
#endif
}
No. There is no portable way to get the name as a string for an arbitrary type across all platforms.
You can potentially write a function template that uses platform-specific code to determine a name of a template parameter, but that is tricky to do, and brittle.
Alternatively, if you only want names for your types, or you are willing to register names for every type that you need a name for, then you can do something like:
some_library::register_type_name<some_type>("some_type");
some_library::register_type_name<some_other_type>("some_other_type");
adding entries to an internal map of typeid
to string. This could be hidden behind a macro like REGISTER_TYPE(x)
, but it would still need to be done for every type.
You can then easily write some_library::lookup_type_name<some_type>()
which searches the registered types and returns the string. You could also write an overload especially for S
which looked up the name of its template parameters too.
You could write a library that provides a name for all standard types, plus containers of standard types, plus make it extensible for project specific types...
That's exactly what the "type name" sub-library in Celma does.
See examples of the usage in the test file: https://github.com/Gemini67/Celma/blob/master/src/library/common/test/test_type_name.cpp
The starting point for the whole library is here: https://github.com/Gemini67/Celma
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.