Удаление пространства имен типа name в C ++ - PullRequest
20 голосов
/ 08 октября 2011

В C ++, когда мы используем 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 C ++)

Ответы [ 5 ]

9 голосов
/ 08 октября 2011

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

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

3 голосов
/ 18 октября 2011

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

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

лучшее решение и полностью переносимый (протестирован в gcc и vc ++), также ниже:

return n;

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

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

3 голосов
/ 17 октября 2011

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

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

В GCC есть магическая переменная с именем __ FUNCTION __ как часть расширения языка GNU C , которая рассматривается как переменная , на С ++. (Относится к нему по-разному в зависимости от версии GCC.)

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

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

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

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

1 голос
/ 17 октября 2011

Если вы просто хотите определить функцию-член, которая будет возвращать строковое имя класса без пространства имен, то мне интересно, зачем вам вообще использовать 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"; }

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

0 голосов
/ 29 ноября 2013
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;
}
...