typeid, как получить только имя типа - PullRequest
2 голосов
/ 08 января 2020

Пример кода:

    MainWindow::MainWindow(QWidget *parent) {
        QString strTemp = typeid(this).name();
        qDebug() << strTemp;
    }

Я хочу получить только имя класса, в приведенном выше примере я просто "MainWindow", что я получаю:

    class MainWindow *

Конечно, я могу написать подпрограмму, которая берет эту строку, а затем удаляет части класса и указателя, выделяя только имя класса. Есть ли что-нибудь, что уже делает это?

В отсутствие какой-либо стандартной подпрограммы я сделал следующее:

        QString strTemp = typeid(this).name();
        qDebug() << strTemp;
        QStringList lstParts = strTemp.split(" ");

        if ( lstParts.length > 1 ) {
            strTemp = lstParts[1];
        }
        qDebug() << strTemp;

Выше приведено только имя типа. В конце мне просто понадобился __FUNCTION__, который дает имя класса и метод, из которого он вызывается, и который даст:

    MainWindow::MainWindow

Ответы [ 4 ]

3 голосов
/ 08 января 2020

cppreference говорит следующее о std::type_info::name():

Возвращает определенную реализацию символьную строку с нулевым символом в конце, содержащую имя типа. Нет никаких гарантий ; в частности, возвращаемая строка может быть идентичной для нескольких типов и изменяться между вызовами одной и той же программы.

Так что тот факт, что вы получили class MainWindow в качестве вывода здесь под одним компилятором, не означает, что вы получите тот же вывод под другим компилятором (или даже тот же, но более новая версия).

2 голосов
/ 08 января 2020

Почему бы не использовать 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;
}

Полная демонстрация

0 голосов
/ 08 января 2020

Вы действительно не должны полагаться ни на std::typeid, ни на boost или любые другие C ++ - only-library . Ни один из них не гарантирует, что вы получите имя типа, особенно с искаженными типами, на разных компиляторах. Используя виртуальную функцию, даже RTTI может влиять на название типа. Ничто не мешает вашему компилятору переименовать «MainWindow» в «CellarDoor». Пока единственный способ go - это использовать какой-то тип Reflection (который пока не является частью C ++) или какой-то препроцессор. ComicSansMS предоставил хороший ответ , где вы катите свою собственную простую реализацию отражения.

Однако, поскольку вы используете QT, вы можете использовать для этого метаобъекты QT . На самом деле у него есть метод, предназначенный именно для этой цели; className .

QMetaObject :: className () возвращает имя класса в виде строки во время выполнения, не требуя поддержки собственной информации типа времени выполнения (RTTI) через C ++ компилятор.

Просто вызовите metaObject()->className():

MainWindow::MainWindow(QWidget *parent) {
    qDebug() << metaObject()->className();
}

mo c запускается перед любым компилятором и запекает имя класса в коде. Глядя на сгенерированный код mo c, вы увидите что-то вроде:

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\0buttonClicked\0"
};
0 голосов
/ 08 января 2020

std::type_info::name() плохо подходит для такого рода задач. Как указано в ответе @ pkrysiak , возвращаемое значение этой функции определяется реализацией, поэтому его невозможно сократить до имени типа, которое отображается в исходном коде переносимым способом.

Лучшим подходом в этом случае будет использование собственного механизма отражения, который даст вам полный контроль над строкой типа. К сожалению, на данный момент язык не предлагает большой поддержки для этого, поэтому полученный механизм будет немного взломан. Например, вы можете сделать что-то вроде этого:

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