Удаление пространства имен имени типа в С++
В С++, когда мы используем 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 С++)
Ответы
Ответ 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;
}