开发者

Removing namespace of type name in C++

In C++, when we use typeid to get type name of an object or class, it will show a decorated(mangled) string. I use cxxabi to demangle it:

#include <cxxabi.h>开发者_如何学Python;
#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;
}

The output in gcc is:

MyNamespace::MyBaseClass

I need to remove MyNamespace:: from above string. i can remove them by string manipulating .

But is there a standard way with cxxabi or other libraries to do this or a clear solution?(At least portable between gcc and Visual C++)


There is no standard way to do this, period, because there is no standard way to do name mangling. How to represent names was intentionally unspecified. There is no ABI in the C++ standard. The function you are using, abi::__cxa_demangle, is a part of the Itanium C++ ABI. That function may or may not exist elsewhere.

As far as a way to do what you want using the Itanium C++ ABI, they intentionally do not provide such a capability.


I dont know if this would corresponds to your needs but i liked to mention about it.

There is something you can do to get the name of a class that you had write. And it may be considered as portable between gcc and Visual C++.

In GCC there is a magic variable named __FUNCTION__ as part of the gnu c language extensions, which treated as a variable, in C++. ( Treating it differs in C according to the GCC version. )

In Visual Studio there is a predefined macro which is in the same name and does the same job. Description is here.

You use __FUNCTION__ to get the name of the current function. So, to get the name of the class, may be you can use it in class constructor like this:

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

So, you get "MyBaseClass" response if you call name() function of an instance of this class.


I investigated cxxabi and other c++ libraries for this issue and there isn't any pre-defined method to remove namespaces from that(at least in my googling).

I wonder why you dont want to manipulate the string?!

the best solution and fully portable (tested in gcc and vc++) is simipily below:

return n;

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

When you search n for a colon from last (= lastColorPos) and capture string from lastColorPos to end, it is definetly the class name.


If you just want to define a member-function which will return the string-name of the class, without the namespace, then I'm wondering why would you even use cxxabi or even __FUNCTION__ or anything else, other than simply doing this:

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

I mean you have full control on the implementation of the class, then why make it complicate when just one return-statement is enough? You can add another member function as well:

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

Have a look at this somewhat related topic, maybe you will get more hints:

  • Reflect a class' inheritance tree in C++?


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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜