typeid,如何仅获取类型名称
typeid, how to get just type name only
示例代码:
MainWindow::MainWindow(QWidget *parent) {
QString strTemp = typeid(this).name();
qDebug() << strTemp;
}
我只想获取 class 名称,在上面的示例中我只是在 "MainWindow" 之后,我得到的是:
class MainWindow *
当然,我可以编写一个例程来获取此字符串,然后去除 class 和指针部分,仅隔离 class 名称。有没有什么已经做到了?
在没有任何标准套路的情况下,我是这样做的:
QString strTemp = typeid(this).name();
qDebug() << strTemp;
QStringList lstParts = strTemp.split(" ");
if ( lstParts.length > 1 ) {
strTemp = lstParts[1];
}
qDebug() << strTemp;
以上结果只有类型名称。最后我只需要
__FUNCTION__
给出了 class 名称和调用它的方法将给出:
MainWindow::MainWindow
cppreference 说了以下关于 std::type_info::name()
的内容:
Returns an implementation defined null-terminated character string containing the name of the type. No guarantees are given; in particular, the returned string can be identical for several types and change between invocations of the same program.
所以你在一个编译器下得到 class MainWindow
作为输出的事实并不意味着你会在不同的编译器(甚至是相同的编译器但更新的版本)下得到相同的输出。
为什么不使用 boost::typeindex::type_id_with_cvr
并使用一些类型特征,例如 remove_pointer_t
以获得所需的结果?
#include <iostream>
#include <sstream>
#include <string>
#include <boost/type_index.hpp>
class MainWindow {
public:
void test()
{
std::ostringstream os;
os <<
boost::typeindex::type_id_with_cvr<std::remove_pointer_t<decltype(this)>>().pretty_name()
;
std::string s = os.str(); // easy transform to QString
std::cout << s << std::endl;
}
};
int main()
{
MainWindow{}.test(); // as output MainWindow
return 0;
}
std::type_info::name()
不适合这种任务。正如 所指出的,此函数的 return 值是实现定义的,因此无法将其分解为类型名称,因为它以可移植的方式出现在源代码中。
在这种情况下,更好的方法是推出您自己的反射机制,这将使您能够完全控制类型字符串。不幸的是,该语言目前并没有为此提供很多支持,因此由此产生的机制有点像 hack。例如,您可以这样做:
#define ENABLE_REFLECTION_TYPE_NAME(class_name) \
inline constexpr char const* type_name(class_name const&) { \
return #class_name; \
}
class Foo {};
ENABLE_REFLECTION_TYPE_NAME(Foo)
ENABLE_REFLECTION_TYPE_NAME(MainWindow)
MainWindow::MainWindow(QWidget *parent) {
QString strTemp = type_name(*this);
qDebug() << strTemp; // prints "MainWindow"
Foo f;
QString strTemp2 = type_name(f);
qDebug() << strTemp2; // prints "Foo"
}
你真的不应该依赖 std::typeid
,也不应该依赖 boost 或任何其他 C++-only-library。 None 其中保证您将在不同的编译器上获得类型名,尤其是对于损坏的类型。使用虚函数甚至 RTTI 都会影响类型的名称。没有什么能阻止您的编译器将 "MainWindow" 重命名为 "CellarDoor"。到目前为止,唯一的方法是使用某种反射(它(还)不是 C++ 的一部分)或一些预处理器。 ComicSansMS 提供了一个很好的 ,您可以在其中滚动自己的简单反射实现。
但是,由于您使用的是 QT,因此可以使用 QT Metaobjects for this. It actually has a method dedicated for this exact purpose; className。
QMetaObject::className() returns the class name as a string at run-time, without requiring native run-time type information (RTTI) support through the C++ compiler.
只需调用 metaObject()->className()
:
MainWindow::MainWindow(QWidget *parent) {
qDebug() << metaObject()->className();
}
moc 在任何编译器之前运行,并将 class 名称烘焙到代码中。查看 moc 生成的代码,您会看到如下内容:
static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
{
QT_MOC_LITERAL(0, 0, 10), // "MainWindow"
QT_MOC_LITERAL(1, 11, 13), // "buttonClicked"
QT_MOC_LITERAL(2, 25, 0) // ""
},
"MainWindow[=11=]buttonClicked[=11=]"
};
示例代码:
MainWindow::MainWindow(QWidget *parent) {
QString strTemp = typeid(this).name();
qDebug() << strTemp;
}
我只想获取 class 名称,在上面的示例中我只是在 "MainWindow" 之后,我得到的是:
class MainWindow *
当然,我可以编写一个例程来获取此字符串,然后去除 class 和指针部分,仅隔离 class 名称。有没有什么已经做到了?
在没有任何标准套路的情况下,我是这样做的:
QString strTemp = typeid(this).name();
qDebug() << strTemp;
QStringList lstParts = strTemp.split(" ");
if ( lstParts.length > 1 ) {
strTemp = lstParts[1];
}
qDebug() << strTemp;
以上结果只有类型名称。最后我只需要
__FUNCTION__
给出了 class 名称和调用它的方法将给出:
MainWindow::MainWindow
cppreference 说了以下关于 std::type_info::name()
的内容:
Returns an implementation defined null-terminated character string containing the name of the type. No guarantees are given; in particular, the returned string can be identical for several types and change between invocations of the same program.
所以你在一个编译器下得到 class MainWindow
作为输出的事实并不意味着你会在不同的编译器(甚至是相同的编译器但更新的版本)下得到相同的输出。
为什么不使用 boost::typeindex::type_id_with_cvr
并使用一些类型特征,例如 remove_pointer_t
以获得所需的结果?
#include <iostream>
#include <sstream>
#include <string>
#include <boost/type_index.hpp>
class MainWindow {
public:
void test()
{
std::ostringstream os;
os <<
boost::typeindex::type_id_with_cvr<std::remove_pointer_t<decltype(this)>>().pretty_name()
;
std::string s = os.str(); // easy transform to QString
std::cout << s << std::endl;
}
};
int main()
{
MainWindow{}.test(); // as output MainWindow
return 0;
}
std::type_info::name()
不适合这种任务。正如
在这种情况下,更好的方法是推出您自己的反射机制,这将使您能够完全控制类型字符串。不幸的是,该语言目前并没有为此提供很多支持,因此由此产生的机制有点像 hack。例如,您可以这样做:
#define ENABLE_REFLECTION_TYPE_NAME(class_name) \
inline constexpr char const* type_name(class_name const&) { \
return #class_name; \
}
class Foo {};
ENABLE_REFLECTION_TYPE_NAME(Foo)
ENABLE_REFLECTION_TYPE_NAME(MainWindow)
MainWindow::MainWindow(QWidget *parent) {
QString strTemp = type_name(*this);
qDebug() << strTemp; // prints "MainWindow"
Foo f;
QString strTemp2 = type_name(f);
qDebug() << strTemp2; // prints "Foo"
}
你真的不应该依赖 std::typeid
,也不应该依赖 boost 或任何其他 C++-only-library。 None 其中保证您将在不同的编译器上获得类型名,尤其是对于损坏的类型。使用虚函数甚至 RTTI 都会影响类型的名称。没有什么能阻止您的编译器将 "MainWindow" 重命名为 "CellarDoor"。到目前为止,唯一的方法是使用某种反射(它(还)不是 C++ 的一部分)或一些预处理器。 ComicSansMS 提供了一个很好的
但是,由于您使用的是 QT,因此可以使用 QT Metaobjects for this. It actually has a method dedicated for this exact purpose; className。
QMetaObject::className() returns the class name as a string at run-time, without requiring native run-time type information (RTTI) support through the C++ compiler.
只需调用 metaObject()->className()
:
MainWindow::MainWindow(QWidget *parent) {
qDebug() << metaObject()->className();
}
moc 在任何编译器之前运行,并将 class 名称烘焙到代码中。查看 moc 生成的代码,您会看到如下内容:
static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
{
QT_MOC_LITERAL(0, 0, 10), // "MainWindow"
QT_MOC_LITERAL(1, 11, 13), // "buttonClicked"
QT_MOC_LITERAL(2, 25, 0) // ""
},
"MainWindow[=11=]buttonClicked[=11=]"
};