简体   繁体   English

编译器独立 class 名称

[英]Compiler independent class name

I need to print the name of a class such as我需要打印 class 的名称,例如

template<typename... Args>
struct S{};

Using typeid(S<int,std::vector<double>>).name() its fairly simple to print something representative.使用typeid(S<int,std::vector<double>>).name()打印有代表性的东西相当简单。 With boost demangle it might even be readable on gcc.使用boost demangle ,它甚至可以在 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请参阅Wikipedia上标题为“不同编译器如何处理相同功能”的表格

Demo.演示。

#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
}

Is it possible to print a variable's type in standard C++?是否可以在标准 C++ 中打印变量的类型?

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.您可能会编写一个 function 模板,该模板使用特定于平台的代码来确定模板参数的名称,但这很难做到,而且很脆弱。

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.将条目添加到typeid的内部 map 到字符串。 This could be hidden behind a macro like REGISTER_TYPE(x) , but it would still need to be done for every type.这可以隐藏在像REGISTER_TYPE(x)这样的宏后面,但仍然需要为每种类型完成。

You can then easily write some_library::lookup_type_name<some_type>() which searches the registered types and returns the string.然后,您可以轻松编写some_library::lookup_type_name<some_type>()来搜索已注册的类型并返回字符串。 You could also write an overload especially for S which looked up the name of its template parameters too.你也可以为S编写一个重载,它也会查找它的模板参数的名称。

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.这正是 Celma 中的“类型名称”子库所做的。

See examples of the usage in the test file: https://github.com/Gemini67/Celma/blob/master/src/library/common/test/test_type_name.cpp查看测试文件中的使用示例: 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整个库的起点在这里: https://github.com/Gemini67/Celma

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM