Подтвердить что ты не робот

Удаление пространства имен имени типа в С++

В С++, когда мы используем typeid для получения типа имени объекта или класса, он отображает украшенную (искаженную) строку. Я использую cxxabi, чтобы развернуть его:

#include <cxxabi.h>
#include <typeinfo>

namespace MyNamespace {

class MyBaseClass
{
public:
    const std::string name()
    {
        int status;
        char *realname = abi::__cxa_demangle(typeid (*this).name(),0,0, &status);
        std::string n = realname;
        free(realname);
        return n;
    }
};

}

int main()
{
    MyNamespace::MyBaseClass h;
    std::cout << h.name() << std::endl;
}

Вывод в gcc:

MyNamespace:: MyBaseClass

Мне нужно удалить MyNamespace:: из строки выше. , я могу удалить их с помощью строки.

Но есть стандартный способ с cxxabi или другими библиотеками для этого или четкое решение? (По крайней мере, переносимый между gcc и Visual С++)

4b9b3361

Ответ 1

Нет стандартного способа сделать это, период, потому что нет стандартного способа выполнения манипуляции с именами. Как представлять имена было намеренно неопределенным. В стандарте С++ нет ABI. Функция, которую вы используете, abi::__cxa_demangle, является частью Itanium С++ ABI. Эта функция может существовать или отсутствовать в другом месте.

Что касается способа сделать то, что вы хотите использовать с помощью Itanium С++ ABI, они намеренно не предоставляют такую ​​возможность.

Ответ 2

Я не знаю, соответствует ли это вашим потребностям, но мне понравилось упоминать об этом.

Есть что-то, что вы можете сделать, чтобы получить имя класса, который вы пишете. И это можно считать переносимым между gcc и Visual С++.

В GCC есть волшебная переменная с именем __ FUNCTION __ как часть языковых расширений gnu c, которые обрабатывались как a переменная, на С++. (Лечение зависит от C в соответствии с версией GCC.)

В Visual Studio существует предопределенный макрос, который имеет одно имя и выполняет ту же работу. Описание здесь.

Вы используете __ FUNCTION __, чтобы получить имя текущей функции. Итак, чтобы получить имя класса, возможно, вы можете использовать его в конструкторе класса следующим образом:

namespace MyNamespace
{
    class MyBaseClass
    {
    public:
        MyBaseClass(): myName(__FUNCTION__){}
        string name() { return myName; }
    private:
        string myName;
    };
}

Итак, вы получаете ответ "MyBaseClass", если вы вызываете функцию name() экземпляра этого класса.

Ответ 3

Если вы просто хотите определить функцию-член, которая вернет имя-строку класса без пространства имен, тогда мне интересно, почему бы вы даже использовать cxxabi или даже __FUNCTION__ или что-то еще, кроме этого:

namespace MyNamespace
{
    class MyBaseClass
    {
    public:
        //make the function const as well
        std::string name() const { return "MyBaseClass"; }
    };
}

Я имею в виду, что у вас есть полный контроль над реализацией класса, то почему это осложняет ситуацию, когда достаточно одного оператора return? Вы также можете добавить еще одну функцию-член:

std::string fullname() const { return "MyNamespace::MyBaseClass"; }

Посмотрите на эту несколько связанную тему, возможно, вы получите больше советов:

Ответ 4

Я исследовал cxxabi и другие библиотеки С++ для этой проблемы, и нет никакого предопределенного метода удаления пространств имен из этого (по крайней мере, в моем googling).

Интересно, почему вы не хотите манипулировать строкой?!

лучшее решение и полностью переносимое (протестированное в gcc и vС++) выглядит следующим образом:

return n;удаp >

return n.substr(n.find_last_of(':')+1);

При поиске n для двоеточия из последнего (= lastColorPos) и записи строки из lastColorPos в конец, это definetly имя класса.

Ответ 5

std::string removeNS( const std::string & source, const std::string & namespace_ )
{
    std::string dst = source;
    size_t position = source.find( namespace_ );
    while ( position != std::string::npos )
    {
        dst.erase( position, namespace_.length() );
        position = dst.find( namespace_, position + 1 );
    }
    return dst;
}

int main()
{
    MyNamespace::MyBaseClass h;
    std::cout << removeNS( h.name(), "MyNamespace::" ) << std::endl;
}